Completed
Branch BUG-11006-abandoned-transactio... (628436)
by
unknown
66:11 queued 54:45
created
core/business/EE_Registration_Processor.class.php 2 patches
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -188,28 +188,28 @@  discard block
 block discarded – undo
188 188
 
189 189
 
190 190
 
191
-    /**
192
-     *    toggle_incomplete_registration_status_to_default
193
-     *        changes any incomplete registrations to either the event or global default registration status
194
-     *
195
-     * @access public
196
-     * @param EE_Registration $registration
197
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up to client code
198
-     * @param Context|null    $context
199
-     * @return void
200
-     * @throws EE_Error
201
-     * @throws InvalidArgumentException
202
-     * @throws ReflectionException
203
-     * @throws RuntimeException
204
-     * @throws EntityNotFoundException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     */
191
+	/**
192
+	 *    toggle_incomplete_registration_status_to_default
193
+	 *        changes any incomplete registrations to either the event or global default registration status
194
+	 *
195
+	 * @access public
196
+	 * @param EE_Registration $registration
197
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up to client code
198
+	 * @param Context|null    $context
199
+	 * @return void
200
+	 * @throws EE_Error
201
+	 * @throws InvalidArgumentException
202
+	 * @throws ReflectionException
203
+	 * @throws RuntimeException
204
+	 * @throws EntityNotFoundException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 */
208 208
 	public function toggle_incomplete_registration_status_to_default(
209
-	    EE_Registration $registration,
210
-        $save = true,
211
-        Context $context = null
212
-    ) {
209
+		EE_Registration $registration,
210
+		$save = true,
211
+		Context $context = null
212
+	) {
213 213
 		$existing_reg_status = $registration->status_ID();
214 214
 		// set initial REG_Status
215 215
 		$this->set_old_reg_status( $registration->ID(), $existing_reg_status );
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
 			}
232 232
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
233 233
 			if ( ! EE_Processor_Base::$IPN ) {
234
-                // otherwise, send out notifications
234
+				// otherwise, send out notifications
235 235
 				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
236 236
 			}
237 237
 			// DEBUG LOG
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
 			}
279 279
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
280 280
 			if ( ! EE_Processor_Base::$IPN ) {
281
-                // otherwise, send out notifications
281
+				// otherwise, send out notifications
282 282
 				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
283 283
 			}
284 284
 			// DEBUG LOG
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 			}
366 366
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
367 367
 			if ( ! EE_Processor_Base::$IPN ) {
368
-                // otherwise, send out notifications
368
+				// otherwise, send out notifications
369 369
 				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
370 370
 			}
371 371
 			// DEBUG LOG
@@ -406,10 +406,10 @@  discard block
 block discarded – undo
406 406
 			// 	false,
407 407
 			// 	'EE_Transaction: ' . $registration->transaction()->ID()
408 408
 			// );
409
-            if ( ! $registration->is_primary_registrant()) {
410
-                return;
411
-            }
412
-            do_action(
409
+			if ( ! $registration->is_primary_registrant()) {
410
+				return;
411
+			}
412
+			do_action(
413 413
 				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
414 414
 				$registration,
415 415
 				$additional_details
@@ -444,7 +444,7 @@  discard block
 block discarded – undo
444 444
 		// set new  REG_Status
445 445
 		$this->set_new_reg_status( $registration->ID(), $registration->status_ID() );
446 446
 		return $this->reg_status_updated( $registration->ID() )
447
-		       && $this->new_reg_status( $registration->ID() ) === EEM_Registration::status_id_approved
447
+			   && $this->new_reg_status( $registration->ID() ) === EEM_Registration::status_id_approved
448 448
 			? true
449 449
 			: false;
450 450
 	}
@@ -524,15 +524,15 @@  discard block
 block discarded – undo
524 524
 
525 525
 
526 526
 
527
-    /**
528
-     * update_registration_after_being_canceled_or_declined
529
-     *
530
-     * @param \EE_Registration $registration
531
-     * @param array            $closed_reg_statuses
532
-     * @param bool             $update_reg
533
-     * @return bool
534
-     * @throws \EE_Error
535
-     */
527
+	/**
528
+	 * update_registration_after_being_canceled_or_declined
529
+	 *
530
+	 * @param \EE_Registration $registration
531
+	 * @param array            $closed_reg_statuses
532
+	 * @param bool             $update_reg
533
+	 * @return bool
534
+	 * @throws \EE_Error
535
+	 */
536 536
 	public function update_registration_after_being_canceled_or_declined(
537 537
 		EE_Registration $registration,
538 538
 		$closed_reg_statuses = array(),
@@ -540,14 +540,14 @@  discard block
 block discarded – undo
540 540
 	) {
541 541
 		// these reg statuses should not be considered in any calculations involving monies owing
542 542
 		$closed_reg_statuses = ! empty( $closed_reg_statuses )
543
-            ? $closed_reg_statuses
543
+			? $closed_reg_statuses
544 544
 			: EEM_Registration::closed_reg_statuses();
545 545
 		if ( ! in_array( $registration->status_ID(), $closed_reg_statuses, true ) ) {
546 546
 			return false;
547 547
 		}
548
-        // release a reserved ticket by decrementing ticket and datetime reserved values
549
-        $registration->release_reserved_ticket(true);
550
-        $registration->set_final_price(0);
548
+		// release a reserved ticket by decrementing ticket and datetime reserved values
549
+		$registration->release_reserved_ticket(true);
550
+		$registration->set_final_price(0);
551 551
 		if ( $update_reg ) {
552 552
 			$registration->save();
553 553
 		}
Please login to merge, or discard this patch.
Spacing   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -8,8 +8,8 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\exceptions\InvalidDataTypeException;
9 9
 use EventEspresso\core\exceptions\InvalidInterfaceException;
10 10
 
11
-if ( ! defined( 'EVENT_ESPRESSO_VERSION')) { exit('No direct script access allowed'); }
12
-EE_Registry::instance()->load_class( 'Processor_Base' );
11
+if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('No direct script access allowed'); }
12
+EE_Registry::instance()->load_class('Processor_Base');
13 13
 
14 14
 /**
15 15
  * Class EE_Registration_Processor
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 	 */
72 72
 	public static function instance() {
73 73
 		// check if class object is instantiated
74
-		if ( ! self::$_instance instanceof EE_Registration_Processor ) {
74
+		if ( ! self::$_instance instanceof EE_Registration_Processor) {
75 75
 			self::$_instance = new self();
76 76
 		}
77 77
 		return self::$_instance;
@@ -91,8 +91,8 @@  discard block
 block discarded – undo
91 91
 	 * @param int $REG_ID
92 92
 	 * @return string
93 93
 	 */
94
-	public function old_reg_status( $REG_ID ) {
95
-		return isset( $this->_old_reg_status[ $REG_ID ] ) ? $this->_old_reg_status[ $REG_ID ] : null;
94
+	public function old_reg_status($REG_ID) {
95
+		return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
96 96
 	}
97 97
 
98 98
 
@@ -101,10 +101,10 @@  discard block
 block discarded – undo
101 101
 	 * @param int $REG_ID
102 102
 	 * @param string $old_reg_status
103 103
 	 */
104
-	public function set_old_reg_status( $REG_ID, $old_reg_status ) {
104
+	public function set_old_reg_status($REG_ID, $old_reg_status) {
105 105
 		// only set the first time
106
-		if ( ! isset( $this->_old_reg_status[ $REG_ID ] ) ) {
107
-			$this->_old_reg_status[ $REG_ID ] = $old_reg_status;
106
+		if ( ! isset($this->_old_reg_status[$REG_ID])) {
107
+			$this->_old_reg_status[$REG_ID] = $old_reg_status;
108 108
 		}
109 109
 	}
110 110
 
@@ -114,8 +114,8 @@  discard block
 block discarded – undo
114 114
 	 * @param int $REG_ID
115 115
 	 * @return string
116 116
 	 */
117
-	public function new_reg_status( $REG_ID ) {
118
-		return isset( $this->_new_reg_status[ $REG_ID ] ) ? $this->_new_reg_status[ $REG_ID ] : null;
117
+	public function new_reg_status($REG_ID) {
118
+		return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
119 119
 	}
120 120
 
121 121
 
@@ -124,8 +124,8 @@  discard block
 block discarded – undo
124 124
 	 * @param int $REG_ID
125 125
 	 * @param string $new_reg_status
126 126
 	 */
127
-	public function set_new_reg_status( $REG_ID, $new_reg_status ) {
128
-		$this->_new_reg_status[ $REG_ID ] = $new_reg_status;
127
+	public function set_new_reg_status($REG_ID, $new_reg_status) {
128
+		$this->_new_reg_status[$REG_ID] = $new_reg_status;
129 129
 	}
130 130
 
131 131
 
@@ -136,8 +136,8 @@  discard block
 block discarded – undo
136 136
 	 * @param int $REG_ID
137 137
 	 * @return bool
138 138
 	 */
139
-	public function reg_status_updated( $REG_ID ) {
140
-		return $this->new_reg_status( $REG_ID ) !== $this->old_reg_status( $REG_ID ) ? true : false;
139
+	public function reg_status_updated($REG_ID) {
140
+		return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID) ? true : false;
141 141
 	}
142 142
 
143 143
 
@@ -146,13 +146,13 @@  discard block
 block discarded – undo
146 146
 	 * @param \EE_Registration $registration
147 147
 	 * @throws \EE_Error
148 148
 	 */
149
-	public function update_registration_status_and_trigger_notifications( \EE_Registration $registration ) {
150
-		$this->toggle_incomplete_registration_status_to_default( $registration, false );
151
-		$this->toggle_registration_status_for_default_approved_events( $registration, false );
152
-		$this->toggle_registration_status_if_no_monies_owing( $registration, false );
149
+	public function update_registration_status_and_trigger_notifications(\EE_Registration $registration) {
150
+		$this->toggle_incomplete_registration_status_to_default($registration, false);
151
+		$this->toggle_registration_status_for_default_approved_events($registration, false);
152
+		$this->toggle_registration_status_if_no_monies_owing($registration, false);
153 153
 		$registration->save();
154 154
 		// trigger notifications
155
-		$this->trigger_registration_update_notifications( $registration );
155
+		$this->trigger_registration_update_notifications($registration);
156 156
 	}
157 157
 
158 158
 
@@ -167,18 +167,18 @@  discard block
 block discarded – undo
167 167
 	 * @return boolean
168 168
 	 * @throws \EE_Error
169 169
 	 */
170
-	public function manually_update_registration_status( EE_Registration $registration, $new_reg_status = '', $save = true ) {
170
+	public function manually_update_registration_status(EE_Registration $registration, $new_reg_status = '', $save = true) {
171 171
 		// set initial REG_Status
172
-		$this->set_old_reg_status( $registration->ID(), $registration->status_ID() );
172
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
173 173
 		// set incoming REG_Status
174
-		$this->set_new_reg_status( $registration->ID(), $new_reg_status );
174
+		$this->set_new_reg_status($registration->ID(), $new_reg_status);
175 175
 		// toggle reg status but only if it has changed and the user can do so
176 176
 		if (
177
-			$this->reg_status_updated( $registration->ID() ) &&
178
-			EE_Registry::instance()->CAP->current_user_can( 'ee_edit_registration', 'toggle_registration_status', $registration->ID() )
177
+			$this->reg_status_updated($registration->ID()) &&
178
+			EE_Registry::instance()->CAP->current_user_can('ee_edit_registration', 'toggle_registration_status', $registration->ID())
179 179
 		) {
180 180
 			// change status to new value
181
-			if ( $registration->set_status( $this->new_reg_status( $registration->ID() ) ) && $save ) {
181
+			if ($registration->set_status($this->new_reg_status($registration->ID())) && $save) {
182 182
 				$registration->save();
183 183
 			}
184 184
 			return TRUE;
@@ -212,27 +212,27 @@  discard block
 block discarded – undo
212 212
     ) {
213 213
 		$existing_reg_status = $registration->status_ID();
214 214
 		// set initial REG_Status
215
-		$this->set_old_reg_status( $registration->ID(), $existing_reg_status );
215
+		$this->set_old_reg_status($registration->ID(), $existing_reg_status);
216 216
 		// is the registration currently incomplete ?
217
-		if ( $registration->status_ID() === EEM_Registration::status_id_incomplete ) {
217
+		if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
218 218
 			// grab default reg status for the event, if set
219 219
 			$event_default_registration_status = $registration->event()->default_registration_status();
220 220
 			// if no default reg status is set for the event, then use the global value
221
-			$STS_ID = ! empty( $event_default_registration_status )
221
+			$STS_ID = ! empty($event_default_registration_status)
222 222
 				? $event_default_registration_status
223 223
 				: EE_Registry::instance()->CFG->registration->default_STS_ID;
224 224
 			// if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
225 225
 			$STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment : $STS_ID;
226 226
 			// set incoming REG_Status
227
-			$this->set_new_reg_status( $registration->ID(), $STS_ID );
228
-			$registration->set_status( $STS_ID, false, $context );
229
-			if ( $save ) {
227
+			$this->set_new_reg_status($registration->ID(), $STS_ID);
228
+			$registration->set_status($STS_ID, false, $context);
229
+			if ($save) {
230 230
 				$registration->save();
231 231
 			}
232 232
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
233
-			if ( ! EE_Processor_Base::$IPN ) {
233
+			if ( ! EE_Processor_Base::$IPN) {
234 234
                 // otherwise, send out notifications
235
-				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
235
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
236 236
 			}
237 237
 			// DEBUG LOG
238 238
 			//$this->log(
@@ -257,10 +257,10 @@  discard block
 block discarded – undo
257 257
 	 * @return boolean
258 258
 	 * @throws \EE_Error
259 259
 	 */
260
-	public function toggle_registration_status_for_default_approved_events( EE_Registration $registration, $save = TRUE ) {
260
+	public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = TRUE) {
261 261
 		$reg_status = $registration->status_ID();
262 262
 		// set initial REG_Status
263
-		$this->set_old_reg_status( $registration->ID(), $reg_status );
263
+		$this->set_old_reg_status($registration->ID(), $reg_status);
264 264
 		// if not already, toggle reg status to approved IF the event default reg status is approved
265 265
 		// ( as long as the registration wasn't cancelled or declined at some point )
266 266
 		if (
@@ -270,16 +270,16 @@  discard block
 block discarded – undo
270 270
 			$registration->event()->default_registration_status() === EEM_Registration::status_id_approved
271 271
 		) {
272 272
 			// set incoming REG_Status
273
-			$this->set_new_reg_status( $registration->ID(), EEM_Registration::status_id_approved );
273
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
274 274
 			// toggle status to approved
275
-			$registration->set_status( EEM_Registration::status_id_approved );
276
-			if ( $save ) {
275
+			$registration->set_status(EEM_Registration::status_id_approved);
276
+			if ($save) {
277 277
 				$registration->save();
278 278
 			}
279 279
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
280
-			if ( ! EE_Processor_Base::$IPN ) {
280
+			if ( ! EE_Processor_Base::$IPN) {
281 281
                 // otherwise, send out notifications
282
-				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
282
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
283 283
 			}
284 284
 			// DEBUG LOG
285 285
 			//$this->log(
@@ -307,19 +307,19 @@  discard block
 block discarded – undo
307 307
 	 * @return bool
308 308
 	 * @throws \EE_Error
309 309
 	 */
310
-	public function toggle_registration_status_if_no_monies_owing( EE_Registration $registration, $save = TRUE, $additional_details = array() ) {
310
+	public function toggle_registration_status_if_no_monies_owing(EE_Registration $registration, $save = TRUE, $additional_details = array()) {
311 311
 		// set initial REG_Status
312
-		$this->set_old_reg_status( $registration->ID(), $registration->status_ID() );
312
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
313 313
 		//EEH_Debug_Tools::printr( $additional_details, '$additional_details', __FILE__, __LINE__ );
314 314
 		// was a payment just made ?
315 315
 		if (
316
-			isset( $additional_details[ 'payment_updates' ], $additional_details[ 'last_payment' ] ) &&
317
-			$additional_details[ 'payment_updates' ] &&
318
-			$additional_details[ 'last_payment' ] instanceof EE_Payment
316
+			isset($additional_details['payment_updates'], $additional_details['last_payment']) &&
317
+			$additional_details['payment_updates'] &&
318
+			$additional_details['last_payment'] instanceof EE_Payment
319 319
 		) {
320
-			$payment = $additional_details[ 'last_payment' ];
320
+			$payment = $additional_details['last_payment'];
321 321
 			$total_paid = 0;
322
-			foreach ( self::$_amount_paid as $reg => $amount_paid ) {
322
+			foreach (self::$_amount_paid as $reg => $amount_paid) {
323 323
 				$total_paid += $amount_paid;
324 324
 			}
325 325
 		} else {
@@ -343,30 +343,30 @@  discard block
 block discarded – undo
343 343
 					$registration->transaction()->is_completed() ||
344 344
 					$registration->transaction()->is_overpaid() ||
345 345
 					$registration->transaction()->is_free() ||
346
-					apply_filters( 'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing', false, $registration )
346
+					apply_filters('FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing', false, $registration)
347 347
 				) || (
348 348
 					$payment instanceof EE_Payment &&
349 349
 					$payment->is_approved() &&
350 350
 					// this specific registration has not yet been paid for
351
-					! isset( self::$_amount_paid[ $registration->ID() ] ) &&
351
+					! isset(self::$_amount_paid[$registration->ID()]) &&
352 352
 					// payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
353 353
 					$payment->amount() - $total_paid >= $registration->final_price()
354 354
 				)
355 355
 			)
356 356
 		) {
357 357
 			// mark as paid
358
-			self::$_amount_paid[ $registration->ID() ] = $registration->final_price();
358
+			self::$_amount_paid[$registration->ID()] = $registration->final_price();
359 359
 			// track new REG_Status
360
-			$this->set_new_reg_status( $registration->ID(), EEM_Registration::status_id_approved );
360
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
361 361
 			// toggle status to approved
362
-			$registration->set_status( EEM_Registration::status_id_approved );
363
-			if ( $save ) {
362
+			$registration->set_status(EEM_Registration::status_id_approved);
363
+			if ($save) {
364 364
 				$registration->save();
365 365
 			}
366 366
 			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
367
-			if ( ! EE_Processor_Base::$IPN ) {
367
+			if ( ! EE_Processor_Base::$IPN) {
368 368
                 // otherwise, send out notifications
369
-				add_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10 );
369
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
370 370
 			}
371 371
 			// DEBUG LOG
372 372
 			//$this->log(
@@ -392,10 +392,10 @@  discard block
 block discarded – undo
392 392
 	 * @param array 	$additional_details
393 393
 	 * @return void
394 394
 	 */
395
-	public function trigger_registration_update_notifications( $registration, $additional_details = array() ) {
395
+	public function trigger_registration_update_notifications($registration, $additional_details = array()) {
396 396
 		try {
397
-			if ( ! $registration instanceof EE_Registration ) {
398
-				throw new EE_Error( __( 'An invalid registration was received.', 'event_espresso' ) );
397
+			if ( ! $registration instanceof EE_Registration) {
398
+				throw new EE_Error(__('An invalid registration was received.', 'event_espresso'));
399 399
 			}
400 400
 			// EE_Registry::instance()->load_helper( 'Debug_Tools' );
401 401
 			// EEH_Debug_Tools::log(
@@ -414,8 +414,8 @@  discard block
 block discarded – undo
414 414
 				$registration,
415 415
 				$additional_details
416 416
 			);
417
-		} catch( Exception $e ) {
418
-			EE_Error::add_error( $e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine() );
417
+		} catch (Exception $e) {
418
+			EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
419 419
 		}
420 420
 	}
421 421
 
@@ -429,22 +429,22 @@  discard block
 block discarded – undo
429 429
 	 * @return bool
430 430
 	 * @throws \EE_Error
431 431
 	 */
432
-	public function update_registration_after_checkout_or_payment(  EE_Registration $registration, $additional_details = array() ) {
432
+	public function update_registration_after_checkout_or_payment(EE_Registration $registration, $additional_details = array()) {
433 433
 		// set initial REG_Status
434
-		$this->set_old_reg_status( $registration->ID(), $registration->status_ID() );
434
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
435 435
 
436 436
 		// if the registration status gets updated, then save the registration
437 437
 		if (
438
-			$this->toggle_registration_status_for_default_approved_events( $registration, false )
439
-			|| $this->toggle_registration_status_if_no_monies_owing( $registration, false, $additional_details )
438
+			$this->toggle_registration_status_for_default_approved_events($registration, false)
439
+			|| $this->toggle_registration_status_if_no_monies_owing($registration, false, $additional_details)
440 440
 		) {
441 441
 			$registration->save();
442 442
 		}
443 443
 
444 444
 		// set new  REG_Status
445
-		$this->set_new_reg_status( $registration->ID(), $registration->status_ID() );
446
-		return $this->reg_status_updated( $registration->ID() )
447
-		       && $this->new_reg_status( $registration->ID() ) === EEM_Registration::status_id_approved
445
+		$this->set_new_reg_status($registration->ID(), $registration->status_ID());
446
+		return $this->reg_status_updated($registration->ID())
447
+		       && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved
448 448
 			? true
449 449
 			: false;
450 450
 	}
@@ -460,20 +460,20 @@  discard block
 block discarded – undo
460 460
 	 * @return void
461 461
 	 * @throws \EE_Error
462 462
 	 */
463
-	public function update_registration_final_prices( $transaction, $save_regs = true ) {
464
-		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() );
465
-		foreach( $transaction->registrations() as $registration ) {
463
+	public function update_registration_final_prices($transaction, $save_regs = true) {
464
+		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item($transaction->total_line_item());
465
+		foreach ($transaction->registrations() as $registration) {
466 466
 			/** @var EE_Line_Item $line_item */
467
-			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration( $registration );
468
-			if( isset( $reg_final_price_per_ticket_line_item[ $line_item->ID() ] ) ) {
469
-				$registration->set_final_price( $reg_final_price_per_ticket_line_item[ $line_item->ID() ] );
470
-				if( $save_regs ) {
467
+			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
468
+			if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
469
+				$registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
470
+				if ($save_regs) {
471 471
 					$registration->save();
472 472
 				}
473 473
 			}
474 474
 		}
475 475
 		//and make sure there's no rounding problem
476
-		$this->fix_reg_final_price_rounding_issue( $transaction );
476
+		$this->fix_reg_final_price_rounding_issue($transaction);
477 477
 	}
478 478
 
479 479
 
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
 	 * @return boolean success verifying that there is NO difference after this method is done
494 494
 	 * @throws \EE_Error
495 495
 	 */
496
-	public function fix_reg_final_price_rounding_issue( $transaction ) {
496
+	public function fix_reg_final_price_rounding_issue($transaction) {
497 497
 		$reg_final_price_sum = EEM_Registration::instance()->sum(
498 498
 			array(
499 499
 				array(
@@ -502,9 +502,9 @@  discard block
 block discarded – undo
502 502
 			),
503 503
 			'REG_final_price'
504 504
 		);
505
-		$diff =  $transaction->total() - (float) $reg_final_price_sum;
505
+		$diff = $transaction->total() - (float) $reg_final_price_sum;
506 506
 		//ok then, just grab one of the registrations
507
-		if( $diff !== 0 ) {
507
+		if ($diff !== 0) {
508 508
 			$a_reg = EEM_Registration::instance()->get_one(
509 509
 					array(
510 510
 						array(
@@ -513,7 +513,7 @@  discard block
 block discarded – undo
513 513
 					));
514 514
 			$success = $a_reg instanceof EE_Registration
515 515
 				? $a_reg->save(
516
-					array( 'REG_final_price' => $a_reg->final_price() + $diff )
516
+					array('REG_final_price' => $a_reg->final_price() + $diff)
517 517
 				)
518 518
 				: false;
519 519
 			return $success ? true : false;
@@ -539,16 +539,16 @@  discard block
 block discarded – undo
539 539
 		$update_reg = true
540 540
 	) {
541 541
 		// these reg statuses should not be considered in any calculations involving monies owing
542
-		$closed_reg_statuses = ! empty( $closed_reg_statuses )
542
+		$closed_reg_statuses = ! empty($closed_reg_statuses)
543 543
             ? $closed_reg_statuses
544 544
 			: EEM_Registration::closed_reg_statuses();
545
-		if ( ! in_array( $registration->status_ID(), $closed_reg_statuses, true ) ) {
545
+		if ( ! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
546 546
 			return false;
547 547
 		}
548 548
         // release a reserved ticket by decrementing ticket and datetime reserved values
549 549
         $registration->release_reserved_ticket(true);
550 550
         $registration->set_final_price(0);
551
-		if ( $update_reg ) {
551
+		if ($update_reg) {
552 552
 			$registration->save();
553 553
 		}
554 554
 		return true;
@@ -571,23 +571,23 @@  discard block
 block discarded – undo
571 571
 		$update_reg = true
572 572
 	) {
573 573
 		// these reg statuses should not be considered in any calculations involving monies owing
574
-		$closed_reg_statuses = ! empty( $closed_reg_statuses ) ? $closed_reg_statuses
574
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
575 575
 			: EEM_Registration::closed_reg_statuses();
576
-		if ( in_array( $registration->status_ID(), $closed_reg_statuses ) ) {
576
+		if (in_array($registration->status_ID(), $closed_reg_statuses)) {
577 577
 			return false;
578 578
 		}
579 579
 		$ticket = $registration->ticket();
580
-		if ( ! $ticket instanceof EE_Ticket ) {
580
+		if ( ! $ticket instanceof EE_Ticket) {
581 581
 			throw new EE_Error(
582 582
 				sprintf(
583
-					__( 'The Ticket for Registration %1$d was not found or is invalid.',
584
-						'event_espresso' ),
583
+					__('The Ticket for Registration %1$d was not found or is invalid.',
584
+						'event_espresso'),
585 585
 					$registration->ticket_ID()
586 586
 				)
587 587
 			);
588 588
 		}
589
-		$registration->set_final_price( $ticket->price() );
590
-		if ( $update_reg ) {
589
+		$registration->set_final_price($ticket->price());
590
+		if ($update_reg) {
591 591
 			$registration->save();
592 592
 		}
593 593
 		return true;
@@ -625,7 +625,7 @@  discard block
 block discarded – undo
625 625
 		$total_ticket_count = 1
626 626
 	) {
627 627
 		EE_Error::doing_it_wrong(
628
-			__CLASS__ . '::' . __FUNCTION__,
628
+			__CLASS__.'::'.__FUNCTION__,
629 629
 			sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
630 630
 				'\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'),
631 631
 			'4.9.1',
@@ -668,7 +668,7 @@  discard block
 block discarded – undo
668 668
 	public function generate_reg_url_link($att_nmbr, $item)
669 669
 	{
670 670
 		EE_Error::doing_it_wrong(
671
-			__CLASS__ . '::' . __FUNCTION__,
671
+			__CLASS__.'::'.__FUNCTION__,
672 672
 			sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
673 673
 				'EventEspresso\core\domain\entities\RegUrlLink'),
674 674
 			'4.9.1',
@@ -688,11 +688,11 @@  discard block
 block discarded – undo
688 688
 	 * @return string
689 689
 	 * @throws \EE_Error
690 690
 	 */
691
-	public function generate_reg_code( EE_Registration $registration ) {
691
+	public function generate_reg_code(EE_Registration $registration) {
692 692
 		EE_Error::doing_it_wrong(
693
-			__CLASS__ . '::' . __FUNCTION__,
693
+			__CLASS__.'::'.__FUNCTION__,
694 694
 			sprintf(
695
-				__( 'This method is deprecated. Please use "%s" instead', 'event_espresso' ),
695
+				__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
696 696
 				'EventEspresso\core\domain\entities\RegCode'
697 697
 			),
698 698
 			'4.9.1',
@@ -701,7 +701,7 @@  discard block
 block discarded – undo
701 701
 		return apply_filters(
702 702
 			'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
703 703
 			new RegCode(
704
-				RegUrlLink::fromRegistration( $registration ),
704
+				RegUrlLink::fromRegistration($registration),
705 705
 				$registration->transaction(),
706 706
 				$registration->ticket()
707 707
 			),
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 2 patches
Indentation   +1934 added lines, -1934 removed lines patch added patch discarded remove patch
@@ -18,1940 +18,1940 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Used to reference when a registration has never been checked in.
23
-     *
24
-     * @deprecated use \EE_Checkin::status_checked_never instead
25
-     * @type int
26
-     */
27
-    const checkin_status_never = 2;
28
-
29
-    /**
30
-     * Used to reference when a registration has been checked in.
31
-     *
32
-     * @deprecated use \EE_Checkin::status_checked_in instead
33
-     * @type int
34
-     */
35
-    const checkin_status_in = 1;
36
-
37
-
38
-    /**
39
-     * Used to reference when a registration has been checked out.
40
-     *
41
-     * @deprecated use \EE_Checkin::status_checked_out instead
42
-     * @type int
43
-     */
44
-    const checkin_status_out = 0;
45
-
46
-
47
-    /**
48
-     * extra meta key for tracking reg status os trashed registrations
49
-     *
50
-     * @type string
51
-     */
52
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
-
54
-
55
-    /**
56
-     * extra meta key for tracking if registration has reserved ticket
57
-     *
58
-     * @type string
59
-     */
60
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
-
62
-
63
-    /**
64
-     * @param array  $props_n_values          incoming values
65
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
-     *                                        used.)
67
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
-     *                                        date_format and the second value is the time format
69
-     * @return EE_Registration
70
-     * @throws EE_Error
71
-     */
72
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
-    {
74
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Registration
84
-     */
85
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
-    {
87
-        return new self($props_n_values, true, $timezone);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Event ID
93
-     *
94
-     * @param        int $EVT_ID Event ID
95
-     * @throws EE_Error
96
-     * @throws RuntimeException
97
-     */
98
-    public function set_event($EVT_ID = 0)
99
-    {
100
-        $this->set('EVT_ID', $EVT_ID);
101
-    }
102
-
103
-
104
-    /**
105
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
-     * be routed to internal methods
107
-     *
108
-     * @param string $field_name
109
-     * @param mixed  $field_value
110
-     * @param bool   $use_default
111
-     * @throws EE_Error
112
-     * @throws EntityNotFoundException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     * @throws ReflectionException
117
-     * @throws RuntimeException
118
-     */
119
-    public function set($field_name, $field_value, $use_default = false)
120
-    {
121
-        switch ($field_name) {
122
-            case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
124
-                    $this->set_reg_code($field_value, $use_default);
125
-                }
126
-                break;
127
-            case 'STS_ID':
128
-                $this->set_status($field_value, $use_default);
129
-                break;
130
-            default:
131
-                parent::set($field_name, $field_value, $use_default);
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * Set Status ID
138
-     * updates the registration status and ALSO...
139
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
-     *
142
-     * @param string       $new_STS_ID
143
-     * @param boolean      $use_default
144
-     * @param Context|null $context
145
-     * @return bool
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     * @throws RuntimeException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     */
154
-    public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
155
-    {
156
-        // get current REG_Status
157
-        $old_STS_ID = $this->status_ID();
158
-        // if status has changed
159
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
-            && ! empty($old_STS_ID) // and that old status is actually set
161
-            && ! empty($new_STS_ID) // as well as the new status
162
-            && $this->ID() // ensure registration is in the db
163
-        ) {
164
-            // TO approved
165
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
-                // reserve a space by incrementing ticket and datetime sold values
167
-                $this->_reserve_registration_space();
168
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
-                // OR FROM  approved
170
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
-                // release a space by decrementing ticket and datetime sold values
172
-                $this->_release_registration_space();
173
-                do_action(
174
-                    'AHEE__EE_Registration__set_status__from_approved',
175
-                    $this,
176
-                    $old_STS_ID,
177
-                    $new_STS_ID,
178
-                    $context
179
-                );
180
-            }
181
-            // update status
182
-            parent::set('STS_ID', $new_STS_ID, $use_default);
183
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
185
-                $this->updateTransactionAfterStatusChange();
186
-            }
187
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
-            return true;
189
-        }
190
-        //even though the old value matches the new value, it's still good to
191
-        //allow the parent set method to have a say
192
-        parent::set('STS_ID', $new_STS_ID, $use_default);
193
-        return true;
194
-    }
195
-
196
-
197
-    /**
198
-     * update REGs and TXN when cancelled or declined registrations involved
199
-     *
200
-     * @param string       $new_STS_ID
201
-     * @param string       $old_STS_ID
202
-     * @param Context|null $context
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
210
-    {
211
-        // these reg statuses should not be considered in any calculations involving monies owing
212
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
-        // true if registration has been cancelled or declined
214
-        $this->updateIfCanceled(
215
-            $closed_reg_statuses,
216
-            $new_STS_ID,
217
-            $old_STS_ID,
218
-            $context
219
-        );
220
-        $this->updateIfDeclined(
221
-            $closed_reg_statuses,
222
-            $new_STS_ID,
223
-            $old_STS_ID,
224
-            $context
225
-        );
226
-    }
227
-
228
-
229
-    /**
230
-     * update REGs and TXN when cancelled or declined registrations involved
231
-     *
232
-     * @param array        $closed_reg_statuses
233
-     * @param string       $new_STS_ID
234
-     * @param string       $old_STS_ID
235
-     * @param Context|null $context
236
-     * @throws EE_Error
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     * @throws ReflectionException
241
-     */
242
-    private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
243
-    {
244
-        // true if registration has been cancelled or declined
245
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
-        ) {
248
-            /** @type EE_Registration_Processor $registration_processor */
249
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
-            /** @type EE_Transaction_Processor $transaction_processor */
251
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
-            // cancelled or declined registration
253
-            $registration_processor->update_registration_after_being_canceled_or_declined(
254
-                $this,
255
-                $closed_reg_statuses
256
-            );
257
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
-                $this,
259
-                $closed_reg_statuses,
260
-                false
261
-            );
262
-            do_action(
263
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
264
-                $this,
265
-                $old_STS_ID,
266
-                $new_STS_ID,
267
-                $context
268
-            );
269
-            return;
270
-        }
271
-    }
272
-
273
-
274
-    /**
275
-     * update REGs and TXN when cancelled or declined registrations involved
276
-     *
277
-     * @param array        $closed_reg_statuses
278
-     * @param string       $new_STS_ID
279
-     * @param string       $old_STS_ID
280
-     * @param Context|null $context
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
288
-    {
289
-        // true if reinstating cancelled or declined registration
290
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
-        ) {
293
-            /** @type EE_Registration_Processor $registration_processor */
294
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
-            /** @type EE_Transaction_Processor $transaction_processor */
296
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
-            // reinstating cancelled or declined registration
298
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
-                $this,
300
-                $closed_reg_statuses
301
-            );
302
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
-                $this,
304
-                $closed_reg_statuses,
305
-                false
306
-            );
307
-            do_action(
308
-                'AHEE__EE_Registration__set_status__after_reinstated',
309
-                $this,
310
-                $old_STS_ID,
311
-                $new_STS_ID,
312
-                $context
313
-            );
314
-        }
315
-    }
316
-
317
-
318
-    /**
319
-     * @param Context|null $context
320
-     * @return bool
321
-     */
322
-    private function statusChangeUpdatesTransaction(Context $context = null)
323
-    {
324
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
325
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
-            array('spco_reg_step_attendee_information_process_registrations'),
327
-            $context,
328
-            $this
329
-        );
330
-        return ! (
331
-            $context instanceof Context
332
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
-        );
334
-    }
335
-
336
-
337
-    /**
338
-     * @throws EE_Error
339
-     * @throws EntityNotFoundException
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     * @throws RuntimeException
345
-     */
346
-    private function updateTransactionAfterStatusChange()
347
-    {
348
-        /** @type EE_Transaction_Payments $transaction_payments */
349
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
-        $this->transaction()->update_status_based_on_total_paid(true);
352
-    }
353
-
354
-
355
-    /**
356
-     *        get Status ID
357
-     */
358
-    public function status_ID()
359
-    {
360
-        return $this->get('STS_ID');
361
-    }
362
-
363
-
364
-    /**
365
-     * increments this registration's related ticket sold and corresponding datetime sold values
366
-     *
367
-     * @return void
368
-     * @throws EE_Error
369
-     * @throws EntityNotFoundException
370
-     */
371
-    private function _reserve_registration_space()
372
-    {
373
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
374
-        // so stop tracking that this reg has a ticket reserved
375
-        $this->release_reserved_ticket();
376
-        $ticket = $this->ticket();
377
-        $ticket->increase_sold();
378
-        $ticket->save();
379
-        // possibly set event status to sold out
380
-        $this->event()->perform_sold_out_status_check();
381
-    }
382
-
383
-
384
-    /**
385
-     * Gets the ticket this registration is for
386
-     *
387
-     * @param boolean $include_archived whether to include archived tickets or not.
388
-     * @return EE_Ticket|EE_Base_Class
389
-     * @throws \EE_Error
390
-     */
391
-    public function ticket($include_archived = true)
392
-    {
393
-        $query_params = array();
394
-        if ($include_archived) {
395
-            $query_params['default_where_conditions'] = 'none';
396
-        }
397
-        return $this->get_first_related('Ticket', $query_params);
398
-    }
399
-
400
-
401
-    /**
402
-     * Gets the event this registration is for
403
-     *
404
-     * @return EE_Event
405
-     * @throws EE_Error
406
-     * @throws EntityNotFoundException
407
-     */
408
-    public function event()
409
-    {
410
-        $event = $this->get_first_related('Event');
411
-        if (! $event instanceof \EE_Event) {
412
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
413
-        }
414
-        return $event;
415
-    }
416
-
417
-
418
-    /**
419
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
420
-     * with the author of the event this registration is for.
421
-     *
422
-     * @since 4.5.0
423
-     * @return int
424
-     * @throws EE_Error
425
-     * @throws EntityNotFoundException
426
-     */
427
-    public function wp_user()
428
-    {
429
-        $event = $this->event();
430
-        if ($event instanceof EE_Event) {
431
-            return $event->wp_user();
432
-        }
433
-        return 0;
434
-    }
435
-
436
-
437
-    /**
438
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
439
-     *
440
-     * @return void
441
-     * @throws \EE_Error
442
-     */
443
-    private function _release_registration_space()
444
-    {
445
-        $ticket = $this->ticket();
446
-        $ticket->decrease_sold();
447
-        $ticket->save();
448
-    }
449
-
450
-
451
-    /**
452
-     * tracks this registration's ticket reservation in extra meta
453
-     * and can increment related ticket reserved and corresponding datetime reserved values
454
-     *
455
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
456
-     * @return void
457
-     * @throws \EE_Error
458
-     */
459
-    public function reserve_ticket($update_ticket = false)
460
-    {
461
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
462
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
463
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
464
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
465
-                $ticket = $this->ticket();
466
-                $ticket->increase_reserved();
467
-                $ticket->save();
468
-            }
469
-        }
470
-    }
471
-
472
-
473
-    /**
474
-     * stops tracking this registration's ticket reservation in extra meta
475
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
476
-     *
477
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
478
-     * @return void
479
-     * @throws \EE_Error
480
-     */
481
-    public function release_reserved_ticket($update_ticket = false)
482
-    {
483
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
484
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
485
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
486
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
487
-                $ticket = $this->ticket();
488
-                $ticket->decrease_reserved();
489
-                $ticket->save();
490
-            }
491
-        }
492
-    }
493
-
494
-
495
-    /**
496
-     * Set Attendee ID
497
-     *
498
-     * @param        int $ATT_ID Attendee ID
499
-     * @throws EE_Error
500
-     * @throws RuntimeException
501
-     */
502
-    public function set_attendee_id($ATT_ID = 0)
503
-    {
504
-        $this->set('ATT_ID', $ATT_ID);
505
-    }
506
-
507
-
508
-    /**
509
-     *        Set Transaction ID
510
-     *
511
-     * @param        int $TXN_ID Transaction ID
512
-     * @throws EE_Error
513
-     * @throws RuntimeException
514
-     */
515
-    public function set_transaction_id($TXN_ID = 0)
516
-    {
517
-        $this->set('TXN_ID', $TXN_ID);
518
-    }
519
-
520
-
521
-    /**
522
-     *        Set Session
523
-     *
524
-     * @param    string $REG_session PHP Session ID
525
-     * @throws EE_Error
526
-     * @throws RuntimeException
527
-     */
528
-    public function set_session($REG_session = '')
529
-    {
530
-        $this->set('REG_session', $REG_session);
531
-    }
532
-
533
-
534
-    /**
535
-     *        Set Registration URL Link
536
-     *
537
-     * @param    string $REG_url_link Registration URL Link
538
-     * @throws EE_Error
539
-     * @throws RuntimeException
540
-     */
541
-    public function set_reg_url_link($REG_url_link = '')
542
-    {
543
-        $this->set('REG_url_link', $REG_url_link);
544
-    }
545
-
546
-
547
-    /**
548
-     *        Set Attendee Counter
549
-     *
550
-     * @param        int $REG_count Primary Attendee
551
-     * @throws EE_Error
552
-     * @throws RuntimeException
553
-     */
554
-    public function set_count($REG_count = 1)
555
-    {
556
-        $this->set('REG_count', $REG_count);
557
-    }
558
-
559
-
560
-    /**
561
-     *        Set Group Size
562
-     *
563
-     * @param        boolean $REG_group_size Group Registration
564
-     * @throws EE_Error
565
-     * @throws RuntimeException
566
-     */
567
-    public function set_group_size($REG_group_size = false)
568
-    {
569
-        $this->set('REG_group_size', $REG_group_size);
570
-    }
571
-
572
-
573
-    /**
574
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
575
-     *    EEM_Registration::status_id_not_approved
576
-     *
577
-     * @return        boolean
578
-     */
579
-    public function is_not_approved()
580
-    {
581
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
582
-    }
583
-
584
-
585
-    /**
586
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
587
-     *    EEM_Registration::status_id_pending_payment
588
-     *
589
-     * @return        boolean
590
-     */
591
-    public function is_pending_payment()
592
-    {
593
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
594
-    }
595
-
596
-
597
-    /**
598
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
599
-     *
600
-     * @return        boolean
601
-     */
602
-    public function is_approved()
603
-    {
604
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
605
-    }
606
-
607
-
608
-    /**
609
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
610
-     *
611
-     * @return        boolean
612
-     */
613
-    public function is_cancelled()
614
-    {
615
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
616
-    }
617
-
618
-
619
-    /**
620
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
621
-     *
622
-     * @return        boolean
623
-     */
624
-    public function is_declined()
625
-    {
626
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
627
-    }
628
-
629
-
630
-    /**
631
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
632
-     *    EEM_Registration::status_id_incomplete
633
-     *
634
-     * @return        boolean
635
-     */
636
-    public function is_incomplete()
637
-    {
638
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
639
-    }
640
-
641
-
642
-    /**
643
-     *        Set Registration Date
644
-     *
645
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
646
-     *                                                 Date
647
-     * @throws EE_Error
648
-     * @throws RuntimeException
649
-     */
650
-    public function set_reg_date($REG_date = false)
651
-    {
652
-        $this->set('REG_date', $REG_date);
653
-    }
654
-
655
-
656
-    /**
657
-     *    Set final price owing for this registration after all ticket/price modifications
658
-     *
659
-     * @access    public
660
-     * @param    float $REG_final_price
661
-     * @throws EE_Error
662
-     * @throws RuntimeException
663
-     */
664
-    public function set_final_price($REG_final_price = 0.00)
665
-    {
666
-        $this->set('REG_final_price', $REG_final_price);
667
-    }
668
-
669
-
670
-    /**
671
-     *    Set amount paid towards this registration's final price
672
-     *
673
-     * @access    public
674
-     * @param    float $REG_paid
675
-     * @throws EE_Error
676
-     * @throws RuntimeException
677
-     */
678
-    public function set_paid($REG_paid = 0.00)
679
-    {
680
-        $this->set('REG_paid', $REG_paid);
681
-    }
682
-
683
-
684
-    /**
685
-     *        Attendee Is Going
686
-     *
687
-     * @param        boolean $REG_att_is_going Attendee Is Going
688
-     * @throws EE_Error
689
-     * @throws RuntimeException
690
-     */
691
-    public function set_att_is_going($REG_att_is_going = false)
692
-    {
693
-        $this->set('REG_att_is_going', $REG_att_is_going);
694
-    }
695
-
696
-
697
-    /**
698
-     * Gets the related attendee
699
-     *
700
-     * @return EE_Attendee
701
-     * @throws EE_Error
702
-     */
703
-    public function attendee()
704
-    {
705
-        return $this->get_first_related('Attendee');
706
-    }
707
-
708
-
709
-    /**
710
-     *        get Event ID
711
-     */
712
-    public function event_ID()
713
-    {
714
-        return $this->get('EVT_ID');
715
-    }
716
-
717
-
718
-    /**
719
-     *        get Event ID
720
-     */
721
-    public function event_name()
722
-    {
723
-        $event = $this->event_obj();
724
-        if ($event) {
725
-            return $event->name();
726
-        } else {
727
-            return null;
728
-        }
729
-    }
730
-
731
-
732
-    /**
733
-     * Fetches the event this registration is for
734
-     *
735
-     * @return EE_Event
736
-     * @throws EE_Error
737
-     */
738
-    public function event_obj()
739
-    {
740
-        return $this->get_first_related('Event');
741
-    }
742
-
743
-
744
-    /**
745
-     *        get Attendee ID
746
-     */
747
-    public function attendee_ID()
748
-    {
749
-        return $this->get('ATT_ID');
750
-    }
751
-
752
-
753
-    /**
754
-     *        get PHP Session ID
755
-     */
756
-    public function session_ID()
757
-    {
758
-        return $this->get('REG_session');
759
-    }
760
-
761
-
762
-    /**
763
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
764
-     *
765
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
766
-     * @return string
767
-     */
768
-    public function receipt_url($messenger = 'html')
769
-    {
770
-
771
-        /**
772
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
773
-         * already in use on old system.  If there is then we just return the standard url for it.
774
-         *
775
-         * @since 4.5.0
776
-         */
777
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
778
-        $has_custom             = EEH_Template::locate_template(
779
-            $template_relative_path,
780
-            array(),
781
-            true,
782
-            true,
783
-            true
784
-        );
785
-
786
-        if ($has_custom) {
787
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
788
-        }
789
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
790
-    }
791
-
792
-
793
-    /**
794
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
795
-     *
796
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
797
-     * @return string
798
-     * @throws EE_Error
799
-     */
800
-    public function invoice_url($messenger = 'html')
801
-    {
802
-        /**
803
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
804
-         * already in use on old system.  If there is then we just return the standard url for it.
805
-         *
806
-         * @since 4.5.0
807
-         */
808
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
809
-        $has_custom             = EEH_Template::locate_template(
810
-            $template_relative_path,
811
-            array(),
812
-            true,
813
-            true,
814
-            true
815
-        );
816
-
817
-        if ($has_custom) {
818
-            if ($messenger == 'html') {
819
-                return $this->invoice_url('launch');
820
-            }
821
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
822
-
823
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
824
-            if ($messenger == 'html') {
825
-                $query_args['html'] = true;
826
-            }
827
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
828
-        }
829
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
830
-    }
831
-
832
-
833
-    /**
834
-     * get Registration URL Link
835
-     *
836
-     * @access public
837
-     * @return string
838
-     * @throws \EE_Error
839
-     */
840
-    public function reg_url_link()
841
-    {
842
-        return (string) $this->get('REG_url_link');
843
-    }
844
-
845
-
846
-    /**
847
-     * Echoes out invoice_url()
848
-     *
849
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
850
-     * @return void
851
-     * @throws EE_Error
852
-     */
853
-    public function e_invoice_url($type = 'launch')
854
-    {
855
-        echo $this->invoice_url($type);
856
-    }
857
-
858
-
859
-    /**
860
-     * Echoes out payment_overview_url
861
-     */
862
-    public function e_payment_overview_url()
863
-    {
864
-        echo $this->payment_overview_url();
865
-    }
866
-
867
-
868
-    /**
869
-     * Gets the URL of the thank you page with this registration REG_url_link added as
870
-     * a query parameter
871
-     *
872
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
873
-     *                            payment overview url.
874
-     * @return string
875
-     * @throws EE_Error
876
-     */
877
-    public function payment_overview_url($clear_session = false)
878
-    {
879
-        return add_query_arg(array(
880
-            'e_reg_url_link' => $this->reg_url_link(),
881
-            'step'           => 'payment_options',
882
-            'revisit'        => true,
883
-            'clear_session' => (bool) $clear_session
884
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
885
-    }
886
-
887
-
888
-    /**
889
-     * Gets the URL of the thank you page with this registration REG_url_link added as
890
-     * a query parameter
891
-     *
892
-     * @return string
893
-     * @throws EE_Error
894
-     */
895
-    public function edit_attendee_information_url()
896
-    {
897
-        return add_query_arg(array(
898
-            'e_reg_url_link' => $this->reg_url_link(),
899
-            'step'           => 'attendee_information',
900
-            'revisit'        => true,
901
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
902
-    }
903
-
904
-
905
-    /**
906
-     * Simply generates and returns the appropriate admin_url link to edit this registration
907
-     *
908
-     * @return string
909
-     * @throws EE_Error
910
-     */
911
-    public function get_admin_edit_url()
912
-    {
913
-        return EEH_URL::add_query_args_and_nonce(array(
914
-            'page'    => 'espresso_registrations',
915
-            'action'  => 'view_registration',
916
-            '_REG_ID' => $this->ID(),
917
-        ), admin_url('admin.php'));
918
-    }
919
-
920
-
921
-    /**
922
-     *    is_primary_registrant?
923
-     */
924
-    public function is_primary_registrant()
925
-    {
926
-        return $this->get('REG_count') == 1 ? true : false;
927
-    }
928
-
929
-
930
-    /**
931
-     * This returns the primary registration object for this registration group (which may be this object).
932
-     *
933
-     * @return EE_Registration
934
-     * @throws EE_Error
935
-     */
936
-    public function get_primary_registration()
937
-    {
938
-        if ($this->is_primary_registrant()) {
939
-            return $this;
940
-        }
941
-
942
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
943
-        /** @var EE_Registration $primary_registrant */
944
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
945
-            array(
946
-                'TXN_ID'    => $this->transaction_ID(),
947
-                'REG_count' => 1,
948
-            ),
949
-        ));
950
-        return $primary_registrant;
951
-    }
952
-
953
-
954
-    /**
955
-     *        get  Attendee Number
956
-     *
957
-     * @access        public
958
-     */
959
-    public function count()
960
-    {
961
-        return $this->get('REG_count');
962
-    }
963
-
964
-
965
-    /**
966
-     *        get Group Size
967
-     */
968
-    public function group_size()
969
-    {
970
-        return $this->get('REG_group_size');
971
-    }
972
-
973
-
974
-    /**
975
-     *        get Registration Date
976
-     */
977
-    public function date()
978
-    {
979
-        return $this->get('REG_date');
980
-    }
981
-
982
-
983
-    /**
984
-     * gets a pretty date
985
-     *
986
-     * @param string $date_format
987
-     * @param string $time_format
988
-     * @return string
989
-     * @throws EE_Error
990
-     */
991
-    public function pretty_date($date_format = null, $time_format = null)
992
-    {
993
-        return $this->get_datetime('REG_date', $date_format, $time_format);
994
-    }
995
-
996
-
997
-    /**
998
-     * final_price
999
-     * the registration's share of the transaction total, so that the
1000
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1001
-     *
1002
-     * @return float
1003
-     * @throws EE_Error
1004
-     */
1005
-    public function final_price()
1006
-    {
1007
-        return $this->get('REG_final_price');
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * pretty_final_price
1013
-     *  final price as formatted string, with correct decimal places and currency symbol
1014
-     *
1015
-     * @return string
1016
-     * @throws EE_Error
1017
-     */
1018
-    public function pretty_final_price()
1019
-    {
1020
-        return $this->get_pretty('REG_final_price');
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * get paid (yeah)
1026
-     *
1027
-     * @return float
1028
-     * @throws EE_Error
1029
-     */
1030
-    public function paid()
1031
-    {
1032
-        return $this->get('REG_paid');
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * pretty_paid
1038
-     *
1039
-     * @return float
1040
-     * @throws EE_Error
1041
-     */
1042
-    public function pretty_paid()
1043
-    {
1044
-        return $this->get_pretty('REG_paid');
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * owes_monies_and_can_pay
1050
-     * whether or not this registration has monies owing and it's' status allows payment
1051
-     *
1052
-     * @param array $requires_payment
1053
-     * @return bool
1054
-     * @throws EE_Error
1055
-     */
1056
-    public function owes_monies_and_can_pay($requires_payment = array())
1057
-    {
1058
-        // these reg statuses require payment (if event is not free)
1059
-        $requires_payment = ! empty($requires_payment)
1060
-            ? $requires_payment
1061
-            : EEM_Registration::reg_statuses_that_allow_payment();
1062
-        if (in_array($this->status_ID(), $requires_payment) &&
1063
-            $this->final_price() != 0 &&
1064
-            $this->final_price() != $this->paid()
1065
-        ) {
1066
-            return true;
1067
-        } else {
1068
-            return false;
1069
-        }
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     * Prints out the return value of $this->pretty_status()
1075
-     *
1076
-     * @param bool $show_icons
1077
-     * @return void
1078
-     * @throws EE_Error
1079
-     */
1080
-    public function e_pretty_status($show_icons = false)
1081
-    {
1082
-        echo $this->pretty_status($show_icons);
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     * Returns a nice version of the status for displaying to customers
1088
-     *
1089
-     * @param bool $show_icons
1090
-     * @return string
1091
-     * @throws EE_Error
1092
-     */
1093
-    public function pretty_status($show_icons = false)
1094
-    {
1095
-        $status = EEM_Status::instance()->localized_status(
1096
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1097
-            false,
1098
-            'sentence'
1099
-        );
1100
-        $icon   = '';
1101
-        switch ($this->status_ID()) {
1102
-            case EEM_Registration::status_id_approved:
1103
-                $icon = $show_icons
1104
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1105
-                    : '';
1106
-                break;
1107
-            case EEM_Registration::status_id_pending_payment:
1108
-                $icon = $show_icons
1109
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1110
-                    : '';
1111
-                break;
1112
-            case EEM_Registration::status_id_not_approved:
1113
-                $icon = $show_icons
1114
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1115
-                    : '';
1116
-                break;
1117
-            case EEM_Registration::status_id_cancelled:
1118
-                $icon = $show_icons
1119
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1120
-                    : '';
1121
-                break;
1122
-            case EEM_Registration::status_id_incomplete:
1123
-                $icon = $show_icons
1124
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1125
-                    : '';
1126
-                break;
1127
-            case EEM_Registration::status_id_declined:
1128
-                $icon = $show_icons
1129
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1130
-                    : '';
1131
-                break;
1132
-            case EEM_Registration::status_id_wait_list:
1133
-                $icon = $show_icons
1134
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1135
-                    : '';
1136
-                break;
1137
-        }
1138
-        return $icon . $status[$this->status_ID()];
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     *        get Attendee Is Going
1144
-     */
1145
-    public function att_is_going()
1146
-    {
1147
-        return $this->get('REG_att_is_going');
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * Gets related answers
1153
-     *
1154
-     * @param array $query_params like EEM_Base::get_all
1155
-     * @return EE_Answer[]
1156
-     * @throws EE_Error
1157
-     */
1158
-    public function answers($query_params = null)
1159
-    {
1160
-        return $this->get_many_related('Answer', $query_params);
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets the registration's answer value to the specified question
1166
-     * (either the question's ID or a question object)
1167
-     *
1168
-     * @param EE_Question|int $question
1169
-     * @param bool            $pretty_value
1170
-     * @return array|string if pretty_value= true, the result will always be a string
1171
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1172
-     * will convert it into some kind of string)
1173
-     * @throws EE_Error
1174
-     */
1175
-    public function answer_value_to_question($question, $pretty_value = true)
1176
-    {
1177
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1178
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1179
-    }
1180
-
1181
-
1182
-    /**
1183
-     * question_groups
1184
-     * returns an array of EE_Question_Group objects for this registration
1185
-     *
1186
-     * @return EE_Question_Group[]
1187
-     * @throws EE_Error
1188
-     * @throws EntityNotFoundException
1189
-     */
1190
-    public function question_groups()
1191
-    {
1192
-        $question_groups = array();
1193
-        if ($this->event() instanceof EE_Event) {
1194
-            $question_groups = $this->event()->question_groups(
1195
-                array(
1196
-                    array(
1197
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1198
-                    ),
1199
-                    'order_by' => array('QSG_order' => 'ASC'),
1200
-                )
1201
-            );
1202
-        }
1203
-        return $question_groups;
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * count_question_groups
1209
-     * returns a count of the number of EE_Question_Group objects for this registration
1210
-     *
1211
-     * @return int
1212
-     * @throws EE_Error
1213
-     * @throws EntityNotFoundException
1214
-     */
1215
-    public function count_question_groups()
1216
-    {
1217
-        $qg_count = 0;
1218
-        if ($this->event() instanceof EE_Event) {
1219
-            $qg_count = $this->event()->count_related(
1220
-                'Question_Group',
1221
-                array(
1222
-                    array(
1223
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1224
-                    ),
1225
-                )
1226
-            );
1227
-        }
1228
-        return $qg_count;
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Returns the registration date in the 'standard' string format
1234
-     * (function may be improved in the future to allow for different formats and timezones)
1235
-     *
1236
-     * @return string
1237
-     * @throws EE_Error
1238
-     */
1239
-    public function reg_date()
1240
-    {
1241
-        return $this->get_datetime('REG_date');
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1247
-     * the ticket this registration purchased, or the datetime they have registered
1248
-     * to attend)
1249
-     *
1250
-     * @return EE_Datetime_Ticket
1251
-     * @throws EE_Error
1252
-     */
1253
-    public function datetime_ticket()
1254
-    {
1255
-        return $this->get_first_related('Datetime_Ticket');
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * Sets the registration's datetime_ticket.
1261
-     *
1262
-     * @param EE_Datetime_Ticket $datetime_ticket
1263
-     * @return EE_Datetime_Ticket
1264
-     * @throws EE_Error
1265
-     */
1266
-    public function set_datetime_ticket($datetime_ticket)
1267
-    {
1268
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1269
-    }
1270
-
1271
-    /**
1272
-     * Gets deleted
1273
-     *
1274
-     * @return bool
1275
-     * @throws EE_Error
1276
-     */
1277
-    public function deleted()
1278
-    {
1279
-        return $this->get('REG_deleted');
1280
-    }
1281
-
1282
-    /**
1283
-     * Sets deleted
1284
-     *
1285
-     * @param boolean $deleted
1286
-     * @return bool
1287
-     * @throws EE_Error
1288
-     * @throws RuntimeException
1289
-     */
1290
-    public function set_deleted($deleted)
1291
-    {
1292
-        if ($deleted) {
1293
-            $this->delete();
1294
-        } else {
1295
-            $this->restore();
1296
-        }
1297
-    }
1298
-
1299
-
1300
-    /**
1301
-     * Get the status object of this object
1302
-     *
1303
-     * @return EE_Status
1304
-     * @throws EE_Error
1305
-     */
1306
-    public function status_obj()
1307
-    {
1308
-        return $this->get_first_related('Status');
1309
-    }
1310
-
1311
-
1312
-    /**
1313
-     * Returns the number of times this registration has checked into any of the datetimes
1314
-     * its available for
1315
-     *
1316
-     * @return int
1317
-     * @throws EE_Error
1318
-     */
1319
-    public function count_checkins()
1320
-    {
1321
-        return $this->get_model()->count_related($this, 'Checkin');
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1327
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1328
-     *
1329
-     * @return int
1330
-     * @throws EE_Error
1331
-     */
1332
-    public function count_checkins_not_checkedout()
1333
-    {
1334
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1340
-     *
1341
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1342
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1343
-     *                                          consider registration status as well as datetime access.
1344
-     * @return bool
1345
-     * @throws EE_Error
1346
-     */
1347
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1348
-    {
1349
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1350
-
1351
-        //first check registration status
1352
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1353
-            return false;
1354
-        }
1355
-        //is there a datetime ticket that matches this dtt_ID?
1356
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1357
-            array(
1358
-                'TKT_ID' => $this->get('TKT_ID'),
1359
-                'DTT_ID' => $DTT_ID,
1360
-            ),
1361
-        )))
1362
-        ) {
1363
-            return false;
1364
-        }
1365
-
1366
-        //final check is against TKT_uses
1367
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1368
-    }
1369
-
1370
-
1371
-    /**
1372
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1373
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1374
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1375
-     * then return false.  Otherwise return true.
1376
-     *
1377
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1378
-     * @return bool true means can checkin.  false means cannot checkin.
1379
-     * @throws EE_Error
1380
-     */
1381
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1382
-    {
1383
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384
-
1385
-        if (! $DTT_ID) {
1386
-            return false;
1387
-        }
1388
-
1389
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1390
-
1391
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392
-        // check-in or not.
1393
-        if (! $max_uses || $max_uses === EE_INF) {
1394
-            return true;
1395
-        }
1396
-
1397
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1398
-        //go ahead and toggle.
1399
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1400
-            return true;
1401
-        }
1402
-
1403
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1404
-        //disallows further check-ins.
1405
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1406
-            array(
1407
-                'REG_ID' => $this->ID(),
1408
-                'CHK_in' => true,
1409
-            ),
1410
-        ), 'DTT_ID', true);
1411
-        // checkins have already reached their max number of uses
1412
-        // so registrant can NOT checkin
1413
-        if ($count_unique_dtt_checkins >= $max_uses) {
1414
-            EE_Error::add_error(
1415
-                esc_html__(
1416
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1417
-                    'event_espresso'
1418
-                ),
1419
-                __FILE__,
1420
-                __FUNCTION__,
1421
-                __LINE__
1422
-            );
1423
-            return false;
1424
-        }
1425
-        return true;
1426
-    }
1427
-
1428
-
1429
-    /**
1430
-     * toggle Check-in status for this registration
1431
-     * Check-ins are toggled in the following order:
1432
-     * never checked in -> checked in
1433
-     * checked in -> checked out
1434
-     * checked out -> checked in
1435
-     *
1436
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1437
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1438
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1439
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1440
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1441
-     * @throws EE_Error
1442
-     */
1443
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1444
-    {
1445
-        if (empty($DTT_ID)) {
1446
-            $datetime = $this->get_latest_related_datetime();
1447
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448
-            // verify the registration can checkin for the given DTT_ID
1449
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1450
-            EE_Error::add_error(
1451
-                sprintf(
1452
-                    esc_html__(
1453
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1454
-                        'event_espresso'
1455
-                    ),
1456
-                    $this->ID(),
1457
-                    $DTT_ID
1458
-                ),
1459
-                __FILE__,
1460
-                __FUNCTION__,
1461
-                __LINE__
1462
-            );
1463
-            return false;
1464
-        }
1465
-        $status_paths = array(
1466
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1467
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1468
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1469
-        );
1470
-        //start by getting the current status so we know what status we'll be changing to.
1471
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1472
-        $status_to  = $status_paths[$cur_status];
1473
-        // database only records true for checked IN or false for checked OUT
1474
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1475
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1476
-        // add relation - note Check-ins are always creating new rows
1477
-        // because we are keeping track of Check-ins over time.
1478
-        // Eventually we'll probably want to show a list table
1479
-        // for the individual Check-ins so that they can be managed.
1480
-        $checkin = EE_Checkin::new_instance(array(
1481
-            'REG_ID' => $this->ID(),
1482
-            'DTT_ID' => $DTT_ID,
1483
-            'CHK_in' => $new_status,
1484
-        ));
1485
-        // if the record could not be saved then return false
1486
-        if ($checkin->save() === 0) {
1487
-            if (WP_DEBUG) {
1488
-                global $wpdb;
1489
-                $error = sprintf(
1490
-                    esc_html__(
1491
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1492
-                        'event_espresso'
1493
-                    ),
1494
-                    '<br />',
1495
-                    $wpdb->last_error
1496
-                );
1497
-            } else {
1498
-                $error = esc_html__(
1499
-                    'Registration check in update failed because of an unknown database error',
1500
-                    'event_espresso'
1501
-                );
1502
-            }
1503
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1504
-            return false;
1505
-        }
1506
-        return $status_to;
1507
-    }
1508
-
1509
-
1510
-    /**
1511
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1512
-     * "Latest" is defined by the `DTT_EVT_start` column.
1513
-     *
1514
-     * @return EE_Datetime|null
1515
-     * @throws \EE_Error
1516
-     */
1517
-    public function get_latest_related_datetime()
1518
-    {
1519
-        return EEM_Datetime::instance()->get_one(
1520
-            array(
1521
-                array(
1522
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1523
-                ),
1524
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1525
-            )
1526
-        );
1527
-    }
1528
-
1529
-
1530
-    /**
1531
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1532
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1533
-     *
1534
-     * @throws \EE_Error
1535
-     */
1536
-    public function get_earliest_related_datetime()
1537
-    {
1538
-        return EEM_Datetime::instance()->get_one(
1539
-            array(
1540
-                array(
1541
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1542
-                ),
1543
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1544
-            )
1545
-        );
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     * This method simply returns the check-in status for this registration and the given datetime.
1551
-     * If neither the datetime nor the checkin values are provided as arguments,
1552
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1553
-     *
1554
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1555
-     *                            (if empty we'll get the primary datetime for
1556
-     *                            this registration (via event) and use it's ID);
1557
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1558
-     * @return int                Integer representing Check-in status.
1559
-     * @throws \EE_Error
1560
-     */
1561
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1562
-    {
1563
-        $checkin_query_params = array(
1564
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1565
-        );
1566
-
1567
-        if ($DTT_ID > 0) {
1568
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1569
-        }
1570
-
1571
-        //get checkin object (if exists)
1572
-        $checkin = $checkin instanceof EE_Checkin
1573
-            ? $checkin
1574
-            : $this->get_first_related('Checkin', $checkin_query_params);
1575
-        if ($checkin instanceof EE_Checkin) {
1576
-            if ($checkin->get('CHK_in')) {
1577
-                return EE_Checkin::status_checked_in; //checked in
1578
-            }
1579
-            return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1580
-        }
1581
-        return EE_Checkin::status_checked_never; //never been checked in
1582
-    }
1583
-
1584
-
1585
-    /**
1586
-     * This method returns a localized message for the toggled Check-in message.
1587
-     *
1588
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1589
-     *                     then it is assumed Check-in for primary datetime was toggled.
1590
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1591
-     *                     message can be customized with the attendee name.
1592
-     * @return string internationalized message
1593
-     * @throws EE_Error
1594
-     */
1595
-    public function get_checkin_msg($DTT_ID, $error = false)
1596
-    {
1597
-        //let's get the attendee first so we can include the name of the attendee
1598
-        $attendee = $this->get_first_related('Attendee');
1599
-        if ($attendee instanceof EE_Attendee) {
1600
-            if ($error) {
1601
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1602
-            }
1603
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1604
-            //what is the status message going to be?
1605
-            switch ($cur_status) {
1606
-                case EE_Checkin::status_checked_never:
1607
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1608
-                        $attendee->full_name());
1609
-                    break;
1610
-                case EE_Checkin::status_checked_in:
1611
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1612
-                    break;
1613
-                case EE_Checkin::status_checked_out:
1614
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1615
-                    break;
1616
-            }
1617
-        }
1618
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1619
-    }
1620
-
1621
-
1622
-    /**
1623
-     * Returns the related EE_Transaction to this registration
1624
-     *
1625
-     * @return EE_Transaction
1626
-     * @throws EE_Error
1627
-     * @throws EntityNotFoundException
1628
-     */
1629
-    public function transaction()
1630
-    {
1631
-        $transaction = $this->get_first_related('Transaction');
1632
-        if (! $transaction instanceof \EE_Transaction) {
1633
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634
-        }
1635
-        return $transaction;
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     *        get Registration Code
1641
-     */
1642
-    public function reg_code()
1643
-    {
1644
-        return $this->get('REG_code');
1645
-    }
1646
-
1647
-
1648
-    /**
1649
-     *        get Transaction ID
1650
-     */
1651
-    public function transaction_ID()
1652
-    {
1653
-        return $this->get('TXN_ID');
1654
-    }
1655
-
1656
-
1657
-    /**
1658
-     * @return int
1659
-     * @throws EE_Error
1660
-     */
1661
-    public function ticket_ID()
1662
-    {
1663
-        return $this->get('TKT_ID');
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     *        Set Registration Code
1669
-     *
1670
-     * @access    public
1671
-     * @param    string  $REG_code Registration Code
1672
-     * @param    boolean $use_default
1673
-     * @throws EE_Error
1674
-     */
1675
-    public function set_reg_code($REG_code, $use_default = false)
1676
-    {
1677
-        if (empty($REG_code)) {
1678
-            EE_Error::add_error(
1679
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1680
-                __FILE__,
1681
-                __FUNCTION__,
1682
-                __LINE__
1683
-            );
1684
-            return;
1685
-        }
1686
-        if (! $this->reg_code()) {
1687
-            parent::set('REG_code', $REG_code, $use_default);
1688
-        } else {
1689
-            EE_Error::doing_it_wrong(
1690
-                __CLASS__ . '::' . __FUNCTION__,
1691
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692
-                '4.6.0'
1693
-            );
1694
-        }
1695
-    }
1696
-
1697
-
1698
-    /**
1699
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1700
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1701
-     *    $registration->transaction()->registrations();
1702
-     *
1703
-     * @since 4.5.0
1704
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1705
-     * @throws EE_Error
1706
-     */
1707
-    public function get_all_other_registrations_in_group()
1708
-    {
1709
-        if ($this->group_size() < 2) {
1710
-            return array();
1711
-        }
1712
-
1713
-        $query[0] = array(
1714
-            'TXN_ID' => $this->transaction_ID(),
1715
-            'REG_ID' => array('!=', $this->ID()),
1716
-            'TKT_ID' => $this->ticket_ID(),
1717
-        );
1718
-        /** @var EE_Registration[] $registrations */
1719
-        $registrations = $this->get_model()->get_all($query);
1720
-        return $registrations;
1721
-    }
1722
-
1723
-    /**
1724
-     * Return the link to the admin details for the object.
1725
-     *
1726
-     * @return string
1727
-     * @throws EE_Error
1728
-     */
1729
-    public function get_admin_details_link()
1730
-    {
1731
-        EE_Registry::instance()->load_helper('URL');
1732
-        return EEH_URL::add_query_args_and_nonce(
1733
-            array(
1734
-                'page'    => 'espresso_registrations',
1735
-                'action'  => 'view_registration',
1736
-                '_REG_ID' => $this->ID(),
1737
-            ),
1738
-            admin_url('admin.php')
1739
-        );
1740
-    }
1741
-
1742
-    /**
1743
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1744
-     *
1745
-     * @return string
1746
-     * @throws EE_Error
1747
-     */
1748
-    public function get_admin_edit_link()
1749
-    {
1750
-        return $this->get_admin_details_link();
1751
-    }
1752
-
1753
-    /**
1754
-     * Returns the link to a settings page for the object.
1755
-     *
1756
-     * @return string
1757
-     * @throws EE_Error
1758
-     */
1759
-    public function get_admin_settings_link()
1760
-    {
1761
-        return $this->get_admin_details_link();
1762
-    }
1763
-
1764
-    /**
1765
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1766
-     *
1767
-     * @return string
1768
-     */
1769
-    public function get_admin_overview_link()
1770
-    {
1771
-        EE_Registry::instance()->load_helper('URL');
1772
-        return EEH_URL::add_query_args_and_nonce(
1773
-            array(
1774
-                'page' => 'espresso_registrations',
1775
-            ),
1776
-            admin_url('admin.php')
1777
-        );
1778
-    }
1779
-
1780
-
1781
-    /**
1782
-     * @param array $query_params
1783
-     * @return \EE_Registration[]
1784
-     * @throws \EE_Error
1785
-     */
1786
-    public function payments($query_params = array())
1787
-    {
1788
-        return $this->get_many_related('Payment', $query_params);
1789
-    }
1790
-
1791
-
1792
-    /**
1793
-     * @param array $query_params
1794
-     * @return \EE_Registration_Payment[]
1795
-     * @throws \EE_Error
1796
-     */
1797
-    public function registration_payments($query_params = array())
1798
-    {
1799
-        return $this->get_many_related('Registration_Payment', $query_params);
1800
-    }
1801
-
1802
-
1803
-    /**
1804
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1805
-     * Note: if there are no payments on the registration there will be no payment method returned.
1806
-     *
1807
-     * @return EE_Payment_Method|null
1808
-     */
1809
-    public function payment_method()
1810
-    {
1811
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1812
-    }
1813
-
1814
-
1815
-    /**
1816
-     * @return \EE_Line_Item
1817
-     * @throws EntityNotFoundException
1818
-     * @throws \EE_Error
1819
-     */
1820
-    public function ticket_line_item()
1821
-    {
1822
-        $ticket            = $this->ticket();
1823
-        $transaction       = $this->transaction();
1824
-        $line_item         = null;
1825
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1826
-            $transaction->total_line_item(),
1827
-            'Ticket',
1828
-            array($ticket->ID())
1829
-        );
1830
-        foreach ($ticket_line_items as $ticket_line_item) {
1831
-            if (
1832
-                $ticket_line_item instanceof \EE_Line_Item
1833
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1834
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1835
-            ) {
1836
-                $line_item = $ticket_line_item;
1837
-                break;
1838
-            }
1839
-        }
1840
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842
-        }
1843
-        return $line_item;
1844
-    }
1845
-
1846
-
1847
-    /**
1848
-     * Soft Deletes this model object.
1849
-     *
1850
-     * @return boolean | int
1851
-     * @throws \RuntimeException
1852
-     * @throws \EE_Error
1853
-     */
1854
-    public function delete()
1855
-    {
1856
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1857
-            $this->set_status(EEM_Registration::status_id_cancelled);
1858
-        }
1859
-        return parent::delete();
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1865
-     *
1866
-     * @throws \EE_Error
1867
-     * @throws \RuntimeException
1868
-     */
1869
-    public function restore()
1870
-    {
1871
-        $previous_status = $this->get_extra_meta(
1872
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1873
-            true,
1874
-            EEM_Registration::status_id_cancelled
1875
-        );
1876
-        if ($previous_status) {
1877
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1878
-            $this->set_status($previous_status);
1879
-        }
1880
-        return parent::restore();
1881
-    }
1882
-
1883
-
1884
-
1885
-    /*************************** DEPRECATED ***************************/
1886
-
1887
-
1888
-    /**
1889
-     * @deprecated
1890
-     * @since     4.7.0
1891
-     * @access    public
1892
-     */
1893
-    public function price_paid()
1894
-    {
1895
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1896
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1897
-            '4.7.0');
1898
-        return $this->final_price();
1899
-    }
1900
-
1901
-
1902
-    /**
1903
-     * @deprecated
1904
-     * @since     4.7.0
1905
-     * @access    public
1906
-     * @param    float $REG_final_price
1907
-     * @throws EE_Error
1908
-     * @throws RuntimeException
1909
-     */
1910
-    public function set_price_paid($REG_final_price = 0.00)
1911
-    {
1912
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1913
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1914
-            '4.7.0');
1915
-        $this->set_final_price($REG_final_price);
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * @deprecated
1921
-     * @since 4.7.0
1922
-     * @return string
1923
-     * @throws EE_Error
1924
-     */
1925
-    public function pretty_price_paid()
1926
-    {
1927
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1928
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1929
-                'event_espresso'), '4.7.0');
1930
-        return $this->pretty_final_price();
1931
-    }
1932
-
1933
-
1934
-    /**
1935
-     * Gets the primary datetime related to this registration via the related Event to this registration
1936
-     *
1937
-     * @deprecated 4.9.17
1938
-     * @return EE_Datetime
1939
-     * @throws EE_Error
1940
-     * @throws EntityNotFoundException
1941
-     */
1942
-    public function get_related_primary_datetime()
1943
-    {
1944
-        EE_Error::doing_it_wrong(
1945
-            __METHOD__,
1946
-            esc_html__(
1947
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1948
-                'event_espresso'
1949
-            ),
1950
-            '4.9.17',
1951
-            '5.0.0'
1952
-        );
1953
-        return $this->event()->primary_datetime();
1954
-    }
21
+	/**
22
+	 * Used to reference when a registration has never been checked in.
23
+	 *
24
+	 * @deprecated use \EE_Checkin::status_checked_never instead
25
+	 * @type int
26
+	 */
27
+	const checkin_status_never = 2;
28
+
29
+	/**
30
+	 * Used to reference when a registration has been checked in.
31
+	 *
32
+	 * @deprecated use \EE_Checkin::status_checked_in instead
33
+	 * @type int
34
+	 */
35
+	const checkin_status_in = 1;
36
+
37
+
38
+	/**
39
+	 * Used to reference when a registration has been checked out.
40
+	 *
41
+	 * @deprecated use \EE_Checkin::status_checked_out instead
42
+	 * @type int
43
+	 */
44
+	const checkin_status_out = 0;
45
+
46
+
47
+	/**
48
+	 * extra meta key for tracking reg status os trashed registrations
49
+	 *
50
+	 * @type string
51
+	 */
52
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
+
54
+
55
+	/**
56
+	 * extra meta key for tracking if registration has reserved ticket
57
+	 *
58
+	 * @type string
59
+	 */
60
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
+
62
+
63
+	/**
64
+	 * @param array  $props_n_values          incoming values
65
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
+	 *                                        used.)
67
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
+	 *                                        date_format and the second value is the time format
69
+	 * @return EE_Registration
70
+	 * @throws EE_Error
71
+	 */
72
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
+	{
74
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Registration
84
+	 */
85
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
+	{
87
+		return new self($props_n_values, true, $timezone);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Event ID
93
+	 *
94
+	 * @param        int $EVT_ID Event ID
95
+	 * @throws EE_Error
96
+	 * @throws RuntimeException
97
+	 */
98
+	public function set_event($EVT_ID = 0)
99
+	{
100
+		$this->set('EVT_ID', $EVT_ID);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
+	 * be routed to internal methods
107
+	 *
108
+	 * @param string $field_name
109
+	 * @param mixed  $field_value
110
+	 * @param bool   $use_default
111
+	 * @throws EE_Error
112
+	 * @throws EntityNotFoundException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 * @throws ReflectionException
117
+	 * @throws RuntimeException
118
+	 */
119
+	public function set($field_name, $field_value, $use_default = false)
120
+	{
121
+		switch ($field_name) {
122
+			case 'REG_code':
123
+				if (! empty($field_value) && $this->reg_code() === null) {
124
+					$this->set_reg_code($field_value, $use_default);
125
+				}
126
+				break;
127
+			case 'STS_ID':
128
+				$this->set_status($field_value, $use_default);
129
+				break;
130
+			default:
131
+				parent::set($field_name, $field_value, $use_default);
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * Set Status ID
138
+	 * updates the registration status and ALSO...
139
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
+	 *
142
+	 * @param string       $new_STS_ID
143
+	 * @param boolean      $use_default
144
+	 * @param Context|null $context
145
+	 * @return bool
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 * @throws RuntimeException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 */
154
+	public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
155
+	{
156
+		// get current REG_Status
157
+		$old_STS_ID = $this->status_ID();
158
+		// if status has changed
159
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
+			&& ! empty($old_STS_ID) // and that old status is actually set
161
+			&& ! empty($new_STS_ID) // as well as the new status
162
+			&& $this->ID() // ensure registration is in the db
163
+		) {
164
+			// TO approved
165
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
+				// reserve a space by incrementing ticket and datetime sold values
167
+				$this->_reserve_registration_space();
168
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
+				// OR FROM  approved
170
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
+				// release a space by decrementing ticket and datetime sold values
172
+				$this->_release_registration_space();
173
+				do_action(
174
+					'AHEE__EE_Registration__set_status__from_approved',
175
+					$this,
176
+					$old_STS_ID,
177
+					$new_STS_ID,
178
+					$context
179
+				);
180
+			}
181
+			// update status
182
+			parent::set('STS_ID', $new_STS_ID, $use_default);
183
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
+			if($this->statusChangeUpdatesTransaction($context)) {
185
+				$this->updateTransactionAfterStatusChange();
186
+			}
187
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
+			return true;
189
+		}
190
+		//even though the old value matches the new value, it's still good to
191
+		//allow the parent set method to have a say
192
+		parent::set('STS_ID', $new_STS_ID, $use_default);
193
+		return true;
194
+	}
195
+
196
+
197
+	/**
198
+	 * update REGs and TXN when cancelled or declined registrations involved
199
+	 *
200
+	 * @param string       $new_STS_ID
201
+	 * @param string       $old_STS_ID
202
+	 * @param Context|null $context
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
210
+	{
211
+		// these reg statuses should not be considered in any calculations involving monies owing
212
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
+		// true if registration has been cancelled or declined
214
+		$this->updateIfCanceled(
215
+			$closed_reg_statuses,
216
+			$new_STS_ID,
217
+			$old_STS_ID,
218
+			$context
219
+		);
220
+		$this->updateIfDeclined(
221
+			$closed_reg_statuses,
222
+			$new_STS_ID,
223
+			$old_STS_ID,
224
+			$context
225
+		);
226
+	}
227
+
228
+
229
+	/**
230
+	 * update REGs and TXN when cancelled or declined registrations involved
231
+	 *
232
+	 * @param array        $closed_reg_statuses
233
+	 * @param string       $new_STS_ID
234
+	 * @param string       $old_STS_ID
235
+	 * @param Context|null $context
236
+	 * @throws EE_Error
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 * @throws ReflectionException
241
+	 */
242
+	private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
243
+	{
244
+		// true if registration has been cancelled or declined
245
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
+		) {
248
+			/** @type EE_Registration_Processor $registration_processor */
249
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
+			/** @type EE_Transaction_Processor $transaction_processor */
251
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
+			// cancelled or declined registration
253
+			$registration_processor->update_registration_after_being_canceled_or_declined(
254
+				$this,
255
+				$closed_reg_statuses
256
+			);
257
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
+				$this,
259
+				$closed_reg_statuses,
260
+				false
261
+			);
262
+			do_action(
263
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
264
+				$this,
265
+				$old_STS_ID,
266
+				$new_STS_ID,
267
+				$context
268
+			);
269
+			return;
270
+		}
271
+	}
272
+
273
+
274
+	/**
275
+	 * update REGs and TXN when cancelled or declined registrations involved
276
+	 *
277
+	 * @param array        $closed_reg_statuses
278
+	 * @param string       $new_STS_ID
279
+	 * @param string       $old_STS_ID
280
+	 * @param Context|null $context
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
288
+	{
289
+		// true if reinstating cancelled or declined registration
290
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
+		) {
293
+			/** @type EE_Registration_Processor $registration_processor */
294
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
+			/** @type EE_Transaction_Processor $transaction_processor */
296
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
+			// reinstating cancelled or declined registration
298
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
+				$this,
300
+				$closed_reg_statuses
301
+			);
302
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
+				$this,
304
+				$closed_reg_statuses,
305
+				false
306
+			);
307
+			do_action(
308
+				'AHEE__EE_Registration__set_status__after_reinstated',
309
+				$this,
310
+				$old_STS_ID,
311
+				$new_STS_ID,
312
+				$context
313
+			);
314
+		}
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param Context|null $context
320
+	 * @return bool
321
+	 */
322
+	private function statusChangeUpdatesTransaction(Context $context = null)
323
+	{
324
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
325
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
+			array('spco_reg_step_attendee_information_process_registrations'),
327
+			$context,
328
+			$this
329
+		);
330
+		return ! (
331
+			$context instanceof Context
332
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
+		);
334
+	}
335
+
336
+
337
+	/**
338
+	 * @throws EE_Error
339
+	 * @throws EntityNotFoundException
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 * @throws RuntimeException
345
+	 */
346
+	private function updateTransactionAfterStatusChange()
347
+	{
348
+		/** @type EE_Transaction_Payments $transaction_payments */
349
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
+		$this->transaction()->update_status_based_on_total_paid(true);
352
+	}
353
+
354
+
355
+	/**
356
+	 *        get Status ID
357
+	 */
358
+	public function status_ID()
359
+	{
360
+		return $this->get('STS_ID');
361
+	}
362
+
363
+
364
+	/**
365
+	 * increments this registration's related ticket sold and corresponding datetime sold values
366
+	 *
367
+	 * @return void
368
+	 * @throws EE_Error
369
+	 * @throws EntityNotFoundException
370
+	 */
371
+	private function _reserve_registration_space()
372
+	{
373
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
374
+		// so stop tracking that this reg has a ticket reserved
375
+		$this->release_reserved_ticket();
376
+		$ticket = $this->ticket();
377
+		$ticket->increase_sold();
378
+		$ticket->save();
379
+		// possibly set event status to sold out
380
+		$this->event()->perform_sold_out_status_check();
381
+	}
382
+
383
+
384
+	/**
385
+	 * Gets the ticket this registration is for
386
+	 *
387
+	 * @param boolean $include_archived whether to include archived tickets or not.
388
+	 * @return EE_Ticket|EE_Base_Class
389
+	 * @throws \EE_Error
390
+	 */
391
+	public function ticket($include_archived = true)
392
+	{
393
+		$query_params = array();
394
+		if ($include_archived) {
395
+			$query_params['default_where_conditions'] = 'none';
396
+		}
397
+		return $this->get_first_related('Ticket', $query_params);
398
+	}
399
+
400
+
401
+	/**
402
+	 * Gets the event this registration is for
403
+	 *
404
+	 * @return EE_Event
405
+	 * @throws EE_Error
406
+	 * @throws EntityNotFoundException
407
+	 */
408
+	public function event()
409
+	{
410
+		$event = $this->get_first_related('Event');
411
+		if (! $event instanceof \EE_Event) {
412
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
413
+		}
414
+		return $event;
415
+	}
416
+
417
+
418
+	/**
419
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
420
+	 * with the author of the event this registration is for.
421
+	 *
422
+	 * @since 4.5.0
423
+	 * @return int
424
+	 * @throws EE_Error
425
+	 * @throws EntityNotFoundException
426
+	 */
427
+	public function wp_user()
428
+	{
429
+		$event = $this->event();
430
+		if ($event instanceof EE_Event) {
431
+			return $event->wp_user();
432
+		}
433
+		return 0;
434
+	}
435
+
436
+
437
+	/**
438
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
439
+	 *
440
+	 * @return void
441
+	 * @throws \EE_Error
442
+	 */
443
+	private function _release_registration_space()
444
+	{
445
+		$ticket = $this->ticket();
446
+		$ticket->decrease_sold();
447
+		$ticket->save();
448
+	}
449
+
450
+
451
+	/**
452
+	 * tracks this registration's ticket reservation in extra meta
453
+	 * and can increment related ticket reserved and corresponding datetime reserved values
454
+	 *
455
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
456
+	 * @return void
457
+	 * @throws \EE_Error
458
+	 */
459
+	public function reserve_ticket($update_ticket = false)
460
+	{
461
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
462
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
463
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
464
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
465
+				$ticket = $this->ticket();
466
+				$ticket->increase_reserved();
467
+				$ticket->save();
468
+			}
469
+		}
470
+	}
471
+
472
+
473
+	/**
474
+	 * stops tracking this registration's ticket reservation in extra meta
475
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
476
+	 *
477
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
478
+	 * @return void
479
+	 * @throws \EE_Error
480
+	 */
481
+	public function release_reserved_ticket($update_ticket = false)
482
+	{
483
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
484
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
485
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
486
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
487
+				$ticket = $this->ticket();
488
+				$ticket->decrease_reserved();
489
+				$ticket->save();
490
+			}
491
+		}
492
+	}
493
+
494
+
495
+	/**
496
+	 * Set Attendee ID
497
+	 *
498
+	 * @param        int $ATT_ID Attendee ID
499
+	 * @throws EE_Error
500
+	 * @throws RuntimeException
501
+	 */
502
+	public function set_attendee_id($ATT_ID = 0)
503
+	{
504
+		$this->set('ATT_ID', $ATT_ID);
505
+	}
506
+
507
+
508
+	/**
509
+	 *        Set Transaction ID
510
+	 *
511
+	 * @param        int $TXN_ID Transaction ID
512
+	 * @throws EE_Error
513
+	 * @throws RuntimeException
514
+	 */
515
+	public function set_transaction_id($TXN_ID = 0)
516
+	{
517
+		$this->set('TXN_ID', $TXN_ID);
518
+	}
519
+
520
+
521
+	/**
522
+	 *        Set Session
523
+	 *
524
+	 * @param    string $REG_session PHP Session ID
525
+	 * @throws EE_Error
526
+	 * @throws RuntimeException
527
+	 */
528
+	public function set_session($REG_session = '')
529
+	{
530
+		$this->set('REG_session', $REG_session);
531
+	}
532
+
533
+
534
+	/**
535
+	 *        Set Registration URL Link
536
+	 *
537
+	 * @param    string $REG_url_link Registration URL Link
538
+	 * @throws EE_Error
539
+	 * @throws RuntimeException
540
+	 */
541
+	public function set_reg_url_link($REG_url_link = '')
542
+	{
543
+		$this->set('REG_url_link', $REG_url_link);
544
+	}
545
+
546
+
547
+	/**
548
+	 *        Set Attendee Counter
549
+	 *
550
+	 * @param        int $REG_count Primary Attendee
551
+	 * @throws EE_Error
552
+	 * @throws RuntimeException
553
+	 */
554
+	public function set_count($REG_count = 1)
555
+	{
556
+		$this->set('REG_count', $REG_count);
557
+	}
558
+
559
+
560
+	/**
561
+	 *        Set Group Size
562
+	 *
563
+	 * @param        boolean $REG_group_size Group Registration
564
+	 * @throws EE_Error
565
+	 * @throws RuntimeException
566
+	 */
567
+	public function set_group_size($REG_group_size = false)
568
+	{
569
+		$this->set('REG_group_size', $REG_group_size);
570
+	}
571
+
572
+
573
+	/**
574
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
575
+	 *    EEM_Registration::status_id_not_approved
576
+	 *
577
+	 * @return        boolean
578
+	 */
579
+	public function is_not_approved()
580
+	{
581
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
582
+	}
583
+
584
+
585
+	/**
586
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
587
+	 *    EEM_Registration::status_id_pending_payment
588
+	 *
589
+	 * @return        boolean
590
+	 */
591
+	public function is_pending_payment()
592
+	{
593
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
594
+	}
595
+
596
+
597
+	/**
598
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
599
+	 *
600
+	 * @return        boolean
601
+	 */
602
+	public function is_approved()
603
+	{
604
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
605
+	}
606
+
607
+
608
+	/**
609
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
610
+	 *
611
+	 * @return        boolean
612
+	 */
613
+	public function is_cancelled()
614
+	{
615
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
616
+	}
617
+
618
+
619
+	/**
620
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
621
+	 *
622
+	 * @return        boolean
623
+	 */
624
+	public function is_declined()
625
+	{
626
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
627
+	}
628
+
629
+
630
+	/**
631
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
632
+	 *    EEM_Registration::status_id_incomplete
633
+	 *
634
+	 * @return        boolean
635
+	 */
636
+	public function is_incomplete()
637
+	{
638
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
639
+	}
640
+
641
+
642
+	/**
643
+	 *        Set Registration Date
644
+	 *
645
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
646
+	 *                                                 Date
647
+	 * @throws EE_Error
648
+	 * @throws RuntimeException
649
+	 */
650
+	public function set_reg_date($REG_date = false)
651
+	{
652
+		$this->set('REG_date', $REG_date);
653
+	}
654
+
655
+
656
+	/**
657
+	 *    Set final price owing for this registration after all ticket/price modifications
658
+	 *
659
+	 * @access    public
660
+	 * @param    float $REG_final_price
661
+	 * @throws EE_Error
662
+	 * @throws RuntimeException
663
+	 */
664
+	public function set_final_price($REG_final_price = 0.00)
665
+	{
666
+		$this->set('REG_final_price', $REG_final_price);
667
+	}
668
+
669
+
670
+	/**
671
+	 *    Set amount paid towards this registration's final price
672
+	 *
673
+	 * @access    public
674
+	 * @param    float $REG_paid
675
+	 * @throws EE_Error
676
+	 * @throws RuntimeException
677
+	 */
678
+	public function set_paid($REG_paid = 0.00)
679
+	{
680
+		$this->set('REG_paid', $REG_paid);
681
+	}
682
+
683
+
684
+	/**
685
+	 *        Attendee Is Going
686
+	 *
687
+	 * @param        boolean $REG_att_is_going Attendee Is Going
688
+	 * @throws EE_Error
689
+	 * @throws RuntimeException
690
+	 */
691
+	public function set_att_is_going($REG_att_is_going = false)
692
+	{
693
+		$this->set('REG_att_is_going', $REG_att_is_going);
694
+	}
695
+
696
+
697
+	/**
698
+	 * Gets the related attendee
699
+	 *
700
+	 * @return EE_Attendee
701
+	 * @throws EE_Error
702
+	 */
703
+	public function attendee()
704
+	{
705
+		return $this->get_first_related('Attendee');
706
+	}
707
+
708
+
709
+	/**
710
+	 *        get Event ID
711
+	 */
712
+	public function event_ID()
713
+	{
714
+		return $this->get('EVT_ID');
715
+	}
716
+
717
+
718
+	/**
719
+	 *        get Event ID
720
+	 */
721
+	public function event_name()
722
+	{
723
+		$event = $this->event_obj();
724
+		if ($event) {
725
+			return $event->name();
726
+		} else {
727
+			return null;
728
+		}
729
+	}
730
+
731
+
732
+	/**
733
+	 * Fetches the event this registration is for
734
+	 *
735
+	 * @return EE_Event
736
+	 * @throws EE_Error
737
+	 */
738
+	public function event_obj()
739
+	{
740
+		return $this->get_first_related('Event');
741
+	}
742
+
743
+
744
+	/**
745
+	 *        get Attendee ID
746
+	 */
747
+	public function attendee_ID()
748
+	{
749
+		return $this->get('ATT_ID');
750
+	}
751
+
752
+
753
+	/**
754
+	 *        get PHP Session ID
755
+	 */
756
+	public function session_ID()
757
+	{
758
+		return $this->get('REG_session');
759
+	}
760
+
761
+
762
+	/**
763
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
764
+	 *
765
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
766
+	 * @return string
767
+	 */
768
+	public function receipt_url($messenger = 'html')
769
+	{
770
+
771
+		/**
772
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
773
+		 * already in use on old system.  If there is then we just return the standard url for it.
774
+		 *
775
+		 * @since 4.5.0
776
+		 */
777
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
778
+		$has_custom             = EEH_Template::locate_template(
779
+			$template_relative_path,
780
+			array(),
781
+			true,
782
+			true,
783
+			true
784
+		);
785
+
786
+		if ($has_custom) {
787
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
788
+		}
789
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
790
+	}
791
+
792
+
793
+	/**
794
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
795
+	 *
796
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
797
+	 * @return string
798
+	 * @throws EE_Error
799
+	 */
800
+	public function invoice_url($messenger = 'html')
801
+	{
802
+		/**
803
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
804
+		 * already in use on old system.  If there is then we just return the standard url for it.
805
+		 *
806
+		 * @since 4.5.0
807
+		 */
808
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
809
+		$has_custom             = EEH_Template::locate_template(
810
+			$template_relative_path,
811
+			array(),
812
+			true,
813
+			true,
814
+			true
815
+		);
816
+
817
+		if ($has_custom) {
818
+			if ($messenger == 'html') {
819
+				return $this->invoice_url('launch');
820
+			}
821
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
822
+
823
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
824
+			if ($messenger == 'html') {
825
+				$query_args['html'] = true;
826
+			}
827
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
828
+		}
829
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
830
+	}
831
+
832
+
833
+	/**
834
+	 * get Registration URL Link
835
+	 *
836
+	 * @access public
837
+	 * @return string
838
+	 * @throws \EE_Error
839
+	 */
840
+	public function reg_url_link()
841
+	{
842
+		return (string) $this->get('REG_url_link');
843
+	}
844
+
845
+
846
+	/**
847
+	 * Echoes out invoice_url()
848
+	 *
849
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
850
+	 * @return void
851
+	 * @throws EE_Error
852
+	 */
853
+	public function e_invoice_url($type = 'launch')
854
+	{
855
+		echo $this->invoice_url($type);
856
+	}
857
+
858
+
859
+	/**
860
+	 * Echoes out payment_overview_url
861
+	 */
862
+	public function e_payment_overview_url()
863
+	{
864
+		echo $this->payment_overview_url();
865
+	}
866
+
867
+
868
+	/**
869
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
870
+	 * a query parameter
871
+	 *
872
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
873
+	 *                            payment overview url.
874
+	 * @return string
875
+	 * @throws EE_Error
876
+	 */
877
+	public function payment_overview_url($clear_session = false)
878
+	{
879
+		return add_query_arg(array(
880
+			'e_reg_url_link' => $this->reg_url_link(),
881
+			'step'           => 'payment_options',
882
+			'revisit'        => true,
883
+			'clear_session' => (bool) $clear_session
884
+		), EE_Registry::instance()->CFG->core->reg_page_url());
885
+	}
886
+
887
+
888
+	/**
889
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
890
+	 * a query parameter
891
+	 *
892
+	 * @return string
893
+	 * @throws EE_Error
894
+	 */
895
+	public function edit_attendee_information_url()
896
+	{
897
+		return add_query_arg(array(
898
+			'e_reg_url_link' => $this->reg_url_link(),
899
+			'step'           => 'attendee_information',
900
+			'revisit'        => true,
901
+		), EE_Registry::instance()->CFG->core->reg_page_url());
902
+	}
903
+
904
+
905
+	/**
906
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
907
+	 *
908
+	 * @return string
909
+	 * @throws EE_Error
910
+	 */
911
+	public function get_admin_edit_url()
912
+	{
913
+		return EEH_URL::add_query_args_and_nonce(array(
914
+			'page'    => 'espresso_registrations',
915
+			'action'  => 'view_registration',
916
+			'_REG_ID' => $this->ID(),
917
+		), admin_url('admin.php'));
918
+	}
919
+
920
+
921
+	/**
922
+	 *    is_primary_registrant?
923
+	 */
924
+	public function is_primary_registrant()
925
+	{
926
+		return $this->get('REG_count') == 1 ? true : false;
927
+	}
928
+
929
+
930
+	/**
931
+	 * This returns the primary registration object for this registration group (which may be this object).
932
+	 *
933
+	 * @return EE_Registration
934
+	 * @throws EE_Error
935
+	 */
936
+	public function get_primary_registration()
937
+	{
938
+		if ($this->is_primary_registrant()) {
939
+			return $this;
940
+		}
941
+
942
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
943
+		/** @var EE_Registration $primary_registrant */
944
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
945
+			array(
946
+				'TXN_ID'    => $this->transaction_ID(),
947
+				'REG_count' => 1,
948
+			),
949
+		));
950
+		return $primary_registrant;
951
+	}
952
+
953
+
954
+	/**
955
+	 *        get  Attendee Number
956
+	 *
957
+	 * @access        public
958
+	 */
959
+	public function count()
960
+	{
961
+		return $this->get('REG_count');
962
+	}
963
+
964
+
965
+	/**
966
+	 *        get Group Size
967
+	 */
968
+	public function group_size()
969
+	{
970
+		return $this->get('REG_group_size');
971
+	}
972
+
973
+
974
+	/**
975
+	 *        get Registration Date
976
+	 */
977
+	public function date()
978
+	{
979
+		return $this->get('REG_date');
980
+	}
981
+
982
+
983
+	/**
984
+	 * gets a pretty date
985
+	 *
986
+	 * @param string $date_format
987
+	 * @param string $time_format
988
+	 * @return string
989
+	 * @throws EE_Error
990
+	 */
991
+	public function pretty_date($date_format = null, $time_format = null)
992
+	{
993
+		return $this->get_datetime('REG_date', $date_format, $time_format);
994
+	}
995
+
996
+
997
+	/**
998
+	 * final_price
999
+	 * the registration's share of the transaction total, so that the
1000
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1001
+	 *
1002
+	 * @return float
1003
+	 * @throws EE_Error
1004
+	 */
1005
+	public function final_price()
1006
+	{
1007
+		return $this->get('REG_final_price');
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * pretty_final_price
1013
+	 *  final price as formatted string, with correct decimal places and currency symbol
1014
+	 *
1015
+	 * @return string
1016
+	 * @throws EE_Error
1017
+	 */
1018
+	public function pretty_final_price()
1019
+	{
1020
+		return $this->get_pretty('REG_final_price');
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * get paid (yeah)
1026
+	 *
1027
+	 * @return float
1028
+	 * @throws EE_Error
1029
+	 */
1030
+	public function paid()
1031
+	{
1032
+		return $this->get('REG_paid');
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * pretty_paid
1038
+	 *
1039
+	 * @return float
1040
+	 * @throws EE_Error
1041
+	 */
1042
+	public function pretty_paid()
1043
+	{
1044
+		return $this->get_pretty('REG_paid');
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * owes_monies_and_can_pay
1050
+	 * whether or not this registration has monies owing and it's' status allows payment
1051
+	 *
1052
+	 * @param array $requires_payment
1053
+	 * @return bool
1054
+	 * @throws EE_Error
1055
+	 */
1056
+	public function owes_monies_and_can_pay($requires_payment = array())
1057
+	{
1058
+		// these reg statuses require payment (if event is not free)
1059
+		$requires_payment = ! empty($requires_payment)
1060
+			? $requires_payment
1061
+			: EEM_Registration::reg_statuses_that_allow_payment();
1062
+		if (in_array($this->status_ID(), $requires_payment) &&
1063
+			$this->final_price() != 0 &&
1064
+			$this->final_price() != $this->paid()
1065
+		) {
1066
+			return true;
1067
+		} else {
1068
+			return false;
1069
+		}
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 * Prints out the return value of $this->pretty_status()
1075
+	 *
1076
+	 * @param bool $show_icons
1077
+	 * @return void
1078
+	 * @throws EE_Error
1079
+	 */
1080
+	public function e_pretty_status($show_icons = false)
1081
+	{
1082
+		echo $this->pretty_status($show_icons);
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 * Returns a nice version of the status for displaying to customers
1088
+	 *
1089
+	 * @param bool $show_icons
1090
+	 * @return string
1091
+	 * @throws EE_Error
1092
+	 */
1093
+	public function pretty_status($show_icons = false)
1094
+	{
1095
+		$status = EEM_Status::instance()->localized_status(
1096
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1097
+			false,
1098
+			'sentence'
1099
+		);
1100
+		$icon   = '';
1101
+		switch ($this->status_ID()) {
1102
+			case EEM_Registration::status_id_approved:
1103
+				$icon = $show_icons
1104
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1105
+					: '';
1106
+				break;
1107
+			case EEM_Registration::status_id_pending_payment:
1108
+				$icon = $show_icons
1109
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1110
+					: '';
1111
+				break;
1112
+			case EEM_Registration::status_id_not_approved:
1113
+				$icon = $show_icons
1114
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1115
+					: '';
1116
+				break;
1117
+			case EEM_Registration::status_id_cancelled:
1118
+				$icon = $show_icons
1119
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1120
+					: '';
1121
+				break;
1122
+			case EEM_Registration::status_id_incomplete:
1123
+				$icon = $show_icons
1124
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1125
+					: '';
1126
+				break;
1127
+			case EEM_Registration::status_id_declined:
1128
+				$icon = $show_icons
1129
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1130
+					: '';
1131
+				break;
1132
+			case EEM_Registration::status_id_wait_list:
1133
+				$icon = $show_icons
1134
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1135
+					: '';
1136
+				break;
1137
+		}
1138
+		return $icon . $status[$this->status_ID()];
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 *        get Attendee Is Going
1144
+	 */
1145
+	public function att_is_going()
1146
+	{
1147
+		return $this->get('REG_att_is_going');
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * Gets related answers
1153
+	 *
1154
+	 * @param array $query_params like EEM_Base::get_all
1155
+	 * @return EE_Answer[]
1156
+	 * @throws EE_Error
1157
+	 */
1158
+	public function answers($query_params = null)
1159
+	{
1160
+		return $this->get_many_related('Answer', $query_params);
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets the registration's answer value to the specified question
1166
+	 * (either the question's ID or a question object)
1167
+	 *
1168
+	 * @param EE_Question|int $question
1169
+	 * @param bool            $pretty_value
1170
+	 * @return array|string if pretty_value= true, the result will always be a string
1171
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1172
+	 * will convert it into some kind of string)
1173
+	 * @throws EE_Error
1174
+	 */
1175
+	public function answer_value_to_question($question, $pretty_value = true)
1176
+	{
1177
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1178
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1179
+	}
1180
+
1181
+
1182
+	/**
1183
+	 * question_groups
1184
+	 * returns an array of EE_Question_Group objects for this registration
1185
+	 *
1186
+	 * @return EE_Question_Group[]
1187
+	 * @throws EE_Error
1188
+	 * @throws EntityNotFoundException
1189
+	 */
1190
+	public function question_groups()
1191
+	{
1192
+		$question_groups = array();
1193
+		if ($this->event() instanceof EE_Event) {
1194
+			$question_groups = $this->event()->question_groups(
1195
+				array(
1196
+					array(
1197
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1198
+					),
1199
+					'order_by' => array('QSG_order' => 'ASC'),
1200
+				)
1201
+			);
1202
+		}
1203
+		return $question_groups;
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * count_question_groups
1209
+	 * returns a count of the number of EE_Question_Group objects for this registration
1210
+	 *
1211
+	 * @return int
1212
+	 * @throws EE_Error
1213
+	 * @throws EntityNotFoundException
1214
+	 */
1215
+	public function count_question_groups()
1216
+	{
1217
+		$qg_count = 0;
1218
+		if ($this->event() instanceof EE_Event) {
1219
+			$qg_count = $this->event()->count_related(
1220
+				'Question_Group',
1221
+				array(
1222
+					array(
1223
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1224
+					),
1225
+				)
1226
+			);
1227
+		}
1228
+		return $qg_count;
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Returns the registration date in the 'standard' string format
1234
+	 * (function may be improved in the future to allow for different formats and timezones)
1235
+	 *
1236
+	 * @return string
1237
+	 * @throws EE_Error
1238
+	 */
1239
+	public function reg_date()
1240
+	{
1241
+		return $this->get_datetime('REG_date');
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1247
+	 * the ticket this registration purchased, or the datetime they have registered
1248
+	 * to attend)
1249
+	 *
1250
+	 * @return EE_Datetime_Ticket
1251
+	 * @throws EE_Error
1252
+	 */
1253
+	public function datetime_ticket()
1254
+	{
1255
+		return $this->get_first_related('Datetime_Ticket');
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * Sets the registration's datetime_ticket.
1261
+	 *
1262
+	 * @param EE_Datetime_Ticket $datetime_ticket
1263
+	 * @return EE_Datetime_Ticket
1264
+	 * @throws EE_Error
1265
+	 */
1266
+	public function set_datetime_ticket($datetime_ticket)
1267
+	{
1268
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1269
+	}
1270
+
1271
+	/**
1272
+	 * Gets deleted
1273
+	 *
1274
+	 * @return bool
1275
+	 * @throws EE_Error
1276
+	 */
1277
+	public function deleted()
1278
+	{
1279
+		return $this->get('REG_deleted');
1280
+	}
1281
+
1282
+	/**
1283
+	 * Sets deleted
1284
+	 *
1285
+	 * @param boolean $deleted
1286
+	 * @return bool
1287
+	 * @throws EE_Error
1288
+	 * @throws RuntimeException
1289
+	 */
1290
+	public function set_deleted($deleted)
1291
+	{
1292
+		if ($deleted) {
1293
+			$this->delete();
1294
+		} else {
1295
+			$this->restore();
1296
+		}
1297
+	}
1298
+
1299
+
1300
+	/**
1301
+	 * Get the status object of this object
1302
+	 *
1303
+	 * @return EE_Status
1304
+	 * @throws EE_Error
1305
+	 */
1306
+	public function status_obj()
1307
+	{
1308
+		return $this->get_first_related('Status');
1309
+	}
1310
+
1311
+
1312
+	/**
1313
+	 * Returns the number of times this registration has checked into any of the datetimes
1314
+	 * its available for
1315
+	 *
1316
+	 * @return int
1317
+	 * @throws EE_Error
1318
+	 */
1319
+	public function count_checkins()
1320
+	{
1321
+		return $this->get_model()->count_related($this, 'Checkin');
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1327
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1328
+	 *
1329
+	 * @return int
1330
+	 * @throws EE_Error
1331
+	 */
1332
+	public function count_checkins_not_checkedout()
1333
+	{
1334
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1340
+	 *
1341
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1342
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1343
+	 *                                          consider registration status as well as datetime access.
1344
+	 * @return bool
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1348
+	{
1349
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1350
+
1351
+		//first check registration status
1352
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1353
+			return false;
1354
+		}
1355
+		//is there a datetime ticket that matches this dtt_ID?
1356
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1357
+			array(
1358
+				'TKT_ID' => $this->get('TKT_ID'),
1359
+				'DTT_ID' => $DTT_ID,
1360
+			),
1361
+		)))
1362
+		) {
1363
+			return false;
1364
+		}
1365
+
1366
+		//final check is against TKT_uses
1367
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1368
+	}
1369
+
1370
+
1371
+	/**
1372
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1373
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1374
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1375
+	 * then return false.  Otherwise return true.
1376
+	 *
1377
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1378
+	 * @return bool true means can checkin.  false means cannot checkin.
1379
+	 * @throws EE_Error
1380
+	 */
1381
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1382
+	{
1383
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384
+
1385
+		if (! $DTT_ID) {
1386
+			return false;
1387
+		}
1388
+
1389
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1390
+
1391
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392
+		// check-in or not.
1393
+		if (! $max_uses || $max_uses === EE_INF) {
1394
+			return true;
1395
+		}
1396
+
1397
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1398
+		//go ahead and toggle.
1399
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1400
+			return true;
1401
+		}
1402
+
1403
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1404
+		//disallows further check-ins.
1405
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1406
+			array(
1407
+				'REG_ID' => $this->ID(),
1408
+				'CHK_in' => true,
1409
+			),
1410
+		), 'DTT_ID', true);
1411
+		// checkins have already reached their max number of uses
1412
+		// so registrant can NOT checkin
1413
+		if ($count_unique_dtt_checkins >= $max_uses) {
1414
+			EE_Error::add_error(
1415
+				esc_html__(
1416
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1417
+					'event_espresso'
1418
+				),
1419
+				__FILE__,
1420
+				__FUNCTION__,
1421
+				__LINE__
1422
+			);
1423
+			return false;
1424
+		}
1425
+		return true;
1426
+	}
1427
+
1428
+
1429
+	/**
1430
+	 * toggle Check-in status for this registration
1431
+	 * Check-ins are toggled in the following order:
1432
+	 * never checked in -> checked in
1433
+	 * checked in -> checked out
1434
+	 * checked out -> checked in
1435
+	 *
1436
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1437
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1438
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1439
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1440
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1441
+	 * @throws EE_Error
1442
+	 */
1443
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1444
+	{
1445
+		if (empty($DTT_ID)) {
1446
+			$datetime = $this->get_latest_related_datetime();
1447
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448
+			// verify the registration can checkin for the given DTT_ID
1449
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1450
+			EE_Error::add_error(
1451
+				sprintf(
1452
+					esc_html__(
1453
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1454
+						'event_espresso'
1455
+					),
1456
+					$this->ID(),
1457
+					$DTT_ID
1458
+				),
1459
+				__FILE__,
1460
+				__FUNCTION__,
1461
+				__LINE__
1462
+			);
1463
+			return false;
1464
+		}
1465
+		$status_paths = array(
1466
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1467
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1468
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1469
+		);
1470
+		//start by getting the current status so we know what status we'll be changing to.
1471
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1472
+		$status_to  = $status_paths[$cur_status];
1473
+		// database only records true for checked IN or false for checked OUT
1474
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1475
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1476
+		// add relation - note Check-ins are always creating new rows
1477
+		// because we are keeping track of Check-ins over time.
1478
+		// Eventually we'll probably want to show a list table
1479
+		// for the individual Check-ins so that they can be managed.
1480
+		$checkin = EE_Checkin::new_instance(array(
1481
+			'REG_ID' => $this->ID(),
1482
+			'DTT_ID' => $DTT_ID,
1483
+			'CHK_in' => $new_status,
1484
+		));
1485
+		// if the record could not be saved then return false
1486
+		if ($checkin->save() === 0) {
1487
+			if (WP_DEBUG) {
1488
+				global $wpdb;
1489
+				$error = sprintf(
1490
+					esc_html__(
1491
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1492
+						'event_espresso'
1493
+					),
1494
+					'<br />',
1495
+					$wpdb->last_error
1496
+				);
1497
+			} else {
1498
+				$error = esc_html__(
1499
+					'Registration check in update failed because of an unknown database error',
1500
+					'event_espresso'
1501
+				);
1502
+			}
1503
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1504
+			return false;
1505
+		}
1506
+		return $status_to;
1507
+	}
1508
+
1509
+
1510
+	/**
1511
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1512
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1513
+	 *
1514
+	 * @return EE_Datetime|null
1515
+	 * @throws \EE_Error
1516
+	 */
1517
+	public function get_latest_related_datetime()
1518
+	{
1519
+		return EEM_Datetime::instance()->get_one(
1520
+			array(
1521
+				array(
1522
+					'Ticket.Registration.REG_ID' => $this->ID(),
1523
+				),
1524
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1525
+			)
1526
+		);
1527
+	}
1528
+
1529
+
1530
+	/**
1531
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1532
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1533
+	 *
1534
+	 * @throws \EE_Error
1535
+	 */
1536
+	public function get_earliest_related_datetime()
1537
+	{
1538
+		return EEM_Datetime::instance()->get_one(
1539
+			array(
1540
+				array(
1541
+					'Ticket.Registration.REG_ID' => $this->ID(),
1542
+				),
1543
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1544
+			)
1545
+		);
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 * This method simply returns the check-in status for this registration and the given datetime.
1551
+	 * If neither the datetime nor the checkin values are provided as arguments,
1552
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1553
+	 *
1554
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1555
+	 *                            (if empty we'll get the primary datetime for
1556
+	 *                            this registration (via event) and use it's ID);
1557
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1558
+	 * @return int                Integer representing Check-in status.
1559
+	 * @throws \EE_Error
1560
+	 */
1561
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1562
+	{
1563
+		$checkin_query_params = array(
1564
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1565
+		);
1566
+
1567
+		if ($DTT_ID > 0) {
1568
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1569
+		}
1570
+
1571
+		//get checkin object (if exists)
1572
+		$checkin = $checkin instanceof EE_Checkin
1573
+			? $checkin
1574
+			: $this->get_first_related('Checkin', $checkin_query_params);
1575
+		if ($checkin instanceof EE_Checkin) {
1576
+			if ($checkin->get('CHK_in')) {
1577
+				return EE_Checkin::status_checked_in; //checked in
1578
+			}
1579
+			return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1580
+		}
1581
+		return EE_Checkin::status_checked_never; //never been checked in
1582
+	}
1583
+
1584
+
1585
+	/**
1586
+	 * This method returns a localized message for the toggled Check-in message.
1587
+	 *
1588
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1589
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1590
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1591
+	 *                     message can be customized with the attendee name.
1592
+	 * @return string internationalized message
1593
+	 * @throws EE_Error
1594
+	 */
1595
+	public function get_checkin_msg($DTT_ID, $error = false)
1596
+	{
1597
+		//let's get the attendee first so we can include the name of the attendee
1598
+		$attendee = $this->get_first_related('Attendee');
1599
+		if ($attendee instanceof EE_Attendee) {
1600
+			if ($error) {
1601
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1602
+			}
1603
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1604
+			//what is the status message going to be?
1605
+			switch ($cur_status) {
1606
+				case EE_Checkin::status_checked_never:
1607
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1608
+						$attendee->full_name());
1609
+					break;
1610
+				case EE_Checkin::status_checked_in:
1611
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1612
+					break;
1613
+				case EE_Checkin::status_checked_out:
1614
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1615
+					break;
1616
+			}
1617
+		}
1618
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1619
+	}
1620
+
1621
+
1622
+	/**
1623
+	 * Returns the related EE_Transaction to this registration
1624
+	 *
1625
+	 * @return EE_Transaction
1626
+	 * @throws EE_Error
1627
+	 * @throws EntityNotFoundException
1628
+	 */
1629
+	public function transaction()
1630
+	{
1631
+		$transaction = $this->get_first_related('Transaction');
1632
+		if (! $transaction instanceof \EE_Transaction) {
1633
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634
+		}
1635
+		return $transaction;
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 *        get Registration Code
1641
+	 */
1642
+	public function reg_code()
1643
+	{
1644
+		return $this->get('REG_code');
1645
+	}
1646
+
1647
+
1648
+	/**
1649
+	 *        get Transaction ID
1650
+	 */
1651
+	public function transaction_ID()
1652
+	{
1653
+		return $this->get('TXN_ID');
1654
+	}
1655
+
1656
+
1657
+	/**
1658
+	 * @return int
1659
+	 * @throws EE_Error
1660
+	 */
1661
+	public function ticket_ID()
1662
+	{
1663
+		return $this->get('TKT_ID');
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 *        Set Registration Code
1669
+	 *
1670
+	 * @access    public
1671
+	 * @param    string  $REG_code Registration Code
1672
+	 * @param    boolean $use_default
1673
+	 * @throws EE_Error
1674
+	 */
1675
+	public function set_reg_code($REG_code, $use_default = false)
1676
+	{
1677
+		if (empty($REG_code)) {
1678
+			EE_Error::add_error(
1679
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1680
+				__FILE__,
1681
+				__FUNCTION__,
1682
+				__LINE__
1683
+			);
1684
+			return;
1685
+		}
1686
+		if (! $this->reg_code()) {
1687
+			parent::set('REG_code', $REG_code, $use_default);
1688
+		} else {
1689
+			EE_Error::doing_it_wrong(
1690
+				__CLASS__ . '::' . __FUNCTION__,
1691
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692
+				'4.6.0'
1693
+			);
1694
+		}
1695
+	}
1696
+
1697
+
1698
+	/**
1699
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1700
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1701
+	 *    $registration->transaction()->registrations();
1702
+	 *
1703
+	 * @since 4.5.0
1704
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1705
+	 * @throws EE_Error
1706
+	 */
1707
+	public function get_all_other_registrations_in_group()
1708
+	{
1709
+		if ($this->group_size() < 2) {
1710
+			return array();
1711
+		}
1712
+
1713
+		$query[0] = array(
1714
+			'TXN_ID' => $this->transaction_ID(),
1715
+			'REG_ID' => array('!=', $this->ID()),
1716
+			'TKT_ID' => $this->ticket_ID(),
1717
+		);
1718
+		/** @var EE_Registration[] $registrations */
1719
+		$registrations = $this->get_model()->get_all($query);
1720
+		return $registrations;
1721
+	}
1722
+
1723
+	/**
1724
+	 * Return the link to the admin details for the object.
1725
+	 *
1726
+	 * @return string
1727
+	 * @throws EE_Error
1728
+	 */
1729
+	public function get_admin_details_link()
1730
+	{
1731
+		EE_Registry::instance()->load_helper('URL');
1732
+		return EEH_URL::add_query_args_and_nonce(
1733
+			array(
1734
+				'page'    => 'espresso_registrations',
1735
+				'action'  => 'view_registration',
1736
+				'_REG_ID' => $this->ID(),
1737
+			),
1738
+			admin_url('admin.php')
1739
+		);
1740
+	}
1741
+
1742
+	/**
1743
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1744
+	 *
1745
+	 * @return string
1746
+	 * @throws EE_Error
1747
+	 */
1748
+	public function get_admin_edit_link()
1749
+	{
1750
+		return $this->get_admin_details_link();
1751
+	}
1752
+
1753
+	/**
1754
+	 * Returns the link to a settings page for the object.
1755
+	 *
1756
+	 * @return string
1757
+	 * @throws EE_Error
1758
+	 */
1759
+	public function get_admin_settings_link()
1760
+	{
1761
+		return $this->get_admin_details_link();
1762
+	}
1763
+
1764
+	/**
1765
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1766
+	 *
1767
+	 * @return string
1768
+	 */
1769
+	public function get_admin_overview_link()
1770
+	{
1771
+		EE_Registry::instance()->load_helper('URL');
1772
+		return EEH_URL::add_query_args_and_nonce(
1773
+			array(
1774
+				'page' => 'espresso_registrations',
1775
+			),
1776
+			admin_url('admin.php')
1777
+		);
1778
+	}
1779
+
1780
+
1781
+	/**
1782
+	 * @param array $query_params
1783
+	 * @return \EE_Registration[]
1784
+	 * @throws \EE_Error
1785
+	 */
1786
+	public function payments($query_params = array())
1787
+	{
1788
+		return $this->get_many_related('Payment', $query_params);
1789
+	}
1790
+
1791
+
1792
+	/**
1793
+	 * @param array $query_params
1794
+	 * @return \EE_Registration_Payment[]
1795
+	 * @throws \EE_Error
1796
+	 */
1797
+	public function registration_payments($query_params = array())
1798
+	{
1799
+		return $this->get_many_related('Registration_Payment', $query_params);
1800
+	}
1801
+
1802
+
1803
+	/**
1804
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1805
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1806
+	 *
1807
+	 * @return EE_Payment_Method|null
1808
+	 */
1809
+	public function payment_method()
1810
+	{
1811
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1812
+	}
1813
+
1814
+
1815
+	/**
1816
+	 * @return \EE_Line_Item
1817
+	 * @throws EntityNotFoundException
1818
+	 * @throws \EE_Error
1819
+	 */
1820
+	public function ticket_line_item()
1821
+	{
1822
+		$ticket            = $this->ticket();
1823
+		$transaction       = $this->transaction();
1824
+		$line_item         = null;
1825
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1826
+			$transaction->total_line_item(),
1827
+			'Ticket',
1828
+			array($ticket->ID())
1829
+		);
1830
+		foreach ($ticket_line_items as $ticket_line_item) {
1831
+			if (
1832
+				$ticket_line_item instanceof \EE_Line_Item
1833
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1834
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1835
+			) {
1836
+				$line_item = $ticket_line_item;
1837
+				break;
1838
+			}
1839
+		}
1840
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842
+		}
1843
+		return $line_item;
1844
+	}
1845
+
1846
+
1847
+	/**
1848
+	 * Soft Deletes this model object.
1849
+	 *
1850
+	 * @return boolean | int
1851
+	 * @throws \RuntimeException
1852
+	 * @throws \EE_Error
1853
+	 */
1854
+	public function delete()
1855
+	{
1856
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1857
+			$this->set_status(EEM_Registration::status_id_cancelled);
1858
+		}
1859
+		return parent::delete();
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1865
+	 *
1866
+	 * @throws \EE_Error
1867
+	 * @throws \RuntimeException
1868
+	 */
1869
+	public function restore()
1870
+	{
1871
+		$previous_status = $this->get_extra_meta(
1872
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1873
+			true,
1874
+			EEM_Registration::status_id_cancelled
1875
+		);
1876
+		if ($previous_status) {
1877
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1878
+			$this->set_status($previous_status);
1879
+		}
1880
+		return parent::restore();
1881
+	}
1882
+
1883
+
1884
+
1885
+	/*************************** DEPRECATED ***************************/
1886
+
1887
+
1888
+	/**
1889
+	 * @deprecated
1890
+	 * @since     4.7.0
1891
+	 * @access    public
1892
+	 */
1893
+	public function price_paid()
1894
+	{
1895
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1896
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1897
+			'4.7.0');
1898
+		return $this->final_price();
1899
+	}
1900
+
1901
+
1902
+	/**
1903
+	 * @deprecated
1904
+	 * @since     4.7.0
1905
+	 * @access    public
1906
+	 * @param    float $REG_final_price
1907
+	 * @throws EE_Error
1908
+	 * @throws RuntimeException
1909
+	 */
1910
+	public function set_price_paid($REG_final_price = 0.00)
1911
+	{
1912
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1913
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1914
+			'4.7.0');
1915
+		$this->set_final_price($REG_final_price);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * @deprecated
1921
+	 * @since 4.7.0
1922
+	 * @return string
1923
+	 * @throws EE_Error
1924
+	 */
1925
+	public function pretty_price_paid()
1926
+	{
1927
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1928
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1929
+				'event_espresso'), '4.7.0');
1930
+		return $this->pretty_final_price();
1931
+	}
1932
+
1933
+
1934
+	/**
1935
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1936
+	 *
1937
+	 * @deprecated 4.9.17
1938
+	 * @return EE_Datetime
1939
+	 * @throws EE_Error
1940
+	 * @throws EntityNotFoundException
1941
+	 */
1942
+	public function get_related_primary_datetime()
1943
+	{
1944
+		EE_Error::doing_it_wrong(
1945
+			__METHOD__,
1946
+			esc_html__(
1947
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1948
+				'event_espresso'
1949
+			),
1950
+			'4.9.17',
1951
+			'5.0.0'
1952
+		);
1953
+		return $this->event()->primary_datetime();
1954
+	}
1955 1955
 
1956 1956
 
1957 1957
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
     {
121 121
         switch ($field_name) {
122 122
             case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
123
+                if ( ! empty($field_value) && $this->reg_code() === null) {
124 124
                     $this->set_reg_code($field_value, $use_default);
125 125
                 }
126 126
                 break;
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
             // update status
182 182
             parent::set('STS_ID', $new_STS_ID, $use_default);
183 183
             $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
184
+            if ($this->statusChangeUpdatesTransaction($context)) {
185 185
                 $this->updateTransactionAfterStatusChange();
186 186
             }
187 187
             do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
     public function event()
409 409
     {
410 410
         $event = $this->get_first_related('Event');
411
-        if (! $event instanceof \EE_Event) {
411
+        if ( ! $event instanceof \EE_Event) {
412 412
             throw new EntityNotFoundException('Event ID', $this->event_ID());
413 413
         }
414 414
         return $event;
@@ -1097,7 +1097,7 @@  discard block
 block discarded – undo
1097 1097
             false,
1098 1098
             'sentence'
1099 1099
         );
1100
-        $icon   = '';
1100
+        $icon = '';
1101 1101
         switch ($this->status_ID()) {
1102 1102
             case EEM_Registration::status_id_approved:
1103 1103
                 $icon = $show_icons
@@ -1135,7 +1135,7 @@  discard block
 block discarded – undo
1135 1135
                     : '';
1136 1136
                 break;
1137 1137
         }
1138
-        return $icon . $status[$this->status_ID()];
1138
+        return $icon.$status[$this->status_ID()];
1139 1139
     }
1140 1140
 
1141 1141
 
@@ -1353,7 +1353,7 @@  discard block
 block discarded – undo
1353 1353
             return false;
1354 1354
         }
1355 1355
         //is there a datetime ticket that matches this dtt_ID?
1356
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1356
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(array(
1357 1357
             array(
1358 1358
                 'TKT_ID' => $this->get('TKT_ID'),
1359 1359
                 'DTT_ID' => $DTT_ID,
@@ -1382,7 +1382,7 @@  discard block
 block discarded – undo
1382 1382
     {
1383 1383
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384 1384
 
1385
-        if (! $DTT_ID) {
1385
+        if ( ! $DTT_ID) {
1386 1386
             return false;
1387 1387
         }
1388 1388
 
@@ -1390,7 +1390,7 @@  discard block
 block discarded – undo
1390 1390
 
1391 1391
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392 1392
         // check-in or not.
1393
-        if (! $max_uses || $max_uses === EE_INF) {
1393
+        if ( ! $max_uses || $max_uses === EE_INF) {
1394 1394
             return true;
1395 1395
         }
1396 1396
 
@@ -1446,7 +1446,7 @@  discard block
 block discarded – undo
1446 1446
             $datetime = $this->get_latest_related_datetime();
1447 1447
             $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448 1448
             // verify the registration can checkin for the given DTT_ID
1449
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1449
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1450 1450
             EE_Error::add_error(
1451 1451
                 sprintf(
1452 1452
                     esc_html__(
@@ -1629,7 +1629,7 @@  discard block
 block discarded – undo
1629 1629
     public function transaction()
1630 1630
     {
1631 1631
         $transaction = $this->get_first_related('Transaction');
1632
-        if (! $transaction instanceof \EE_Transaction) {
1632
+        if ( ! $transaction instanceof \EE_Transaction) {
1633 1633
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634 1634
         }
1635 1635
         return $transaction;
@@ -1683,11 +1683,11 @@  discard block
 block discarded – undo
1683 1683
             );
1684 1684
             return;
1685 1685
         }
1686
-        if (! $this->reg_code()) {
1686
+        if ( ! $this->reg_code()) {
1687 1687
             parent::set('REG_code', $REG_code, $use_default);
1688 1688
         } else {
1689 1689
             EE_Error::doing_it_wrong(
1690
-                __CLASS__ . '::' . __FUNCTION__,
1690
+                __CLASS__.'::'.__FUNCTION__,
1691 1691
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692 1692
                 '4.6.0'
1693 1693
             );
@@ -1837,7 +1837,7 @@  discard block
 block discarded – undo
1837 1837
                 break;
1838 1838
             }
1839 1839
         }
1840
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1840
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841 1841
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842 1842
         }
1843 1843
         return $line_item;
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 1 patch
Indentation   +1327 added lines, -1327 removed lines patch added patch discarded remove patch
@@ -17,1335 +17,1335 @@
 block discarded – undo
17 17
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
18 18
 {
19 19
 
20
-    /**
21
-     * @type bool $_print_copy_info
22
-     */
23
-    private $_print_copy_info = false;
24
-
25
-    /**
26
-     * @type array $_attendee_data
27
-     */
28
-    private $_attendee_data = array();
29
-
30
-    /**
31
-     * @type array $_required_questions
32
-     */
33
-    private $_required_questions = array();
34
-
35
-    /**
36
-     * @type array $_registration_answers
37
-     */
38
-    private $_registration_answers = array();
39
-
40
-
41
-    /**
42
-     *    class constructor
43
-     *
44
-     * @access    public
45
-     * @param    EE_Checkout $checkout
46
-     */
47
-    public function __construct(EE_Checkout $checkout)
48
-    {
49
-        $this->_slug     = 'attendee_information';
50
-        $this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
-        $this->checkout  = $checkout;
53
-        $this->_reset_success_message();
54
-        $this->set_instructions(
55
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
-        );
57
-    }
58
-
59
-
60
-    public function translate_js_strings()
61
-    {
62
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
-            ' is a required question.',
64
-            'event_espresso'
65
-        );
66
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
-            ' is a required question. Please enter a value for at least one of the options.',
68
-            'event_espresso'
69
-        );
70
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
-            'Please answer all required questions correctly before proceeding.',
72
-            'event_espresso'
73
-        );
74
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
-            esc_html__(
76
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
-                'event_espresso'
78
-            ),
79
-            '<br/>'
80
-        );
81
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
-            'event_espresso'
84
-        );
85
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
-            'You must enter a valid email address.',
87
-            'event_espresso'
88
-        );
89
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
91
-            'event_espresso'
92
-        );
93
-    }
94
-
95
-
96
-    public function enqueue_styles_and_scripts()
97
-    {
98
-    }
99
-
100
-
101
-    /**
102
-     * @return boolean
103
-     */
104
-    public function initialize_reg_step()
105
-    {
106
-        return true;
107
-    }
108
-
109
-
110
-    /**
111
-     * @return EE_Form_Section_Proper
112
-     * @throws EE_Error
113
-     * @throws InvalidArgumentException
114
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
-     */
118
-    public function generate_reg_form()
119
-    {
120
-        $this->_print_copy_info = false;
121
-        $primary_registrant     = null;
122
-        // autoload Line_Item_Display classes
123
-        EEH_Autoloader::register_line_item_display_autoloaders();
124
-        $Line_Item_Display = new EE_Line_Item_Display();
125
-        // calculate taxes
126
-        $Line_Item_Display->display_line_item(
127
-            $this->checkout->cart->get_grand_total(),
128
-            array('set_tax_rate' => true)
129
-        );
130
-        /** @var $subsections EE_Form_Section_Proper[] */
131
-        $subsections   = array(
132
-            'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
-        );
134
-        $template_args = array(
135
-            'revisit'       => $this->checkout->revisit,
136
-            'registrations' => array(),
137
-            'ticket_count'  => array(),
138
-        );
139
-        // grab the saved registrations from the transaction
140
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
-        if ($registrations) {
142
-            foreach ($registrations as $registration) {
143
-                // can this registration be processed during this visit ?
144
-                if ($registration instanceof EE_Registration
145
-                    && $this->checkout->visit_allows_processing_of_this_registration($registration)
146
-                ) {
147
-                    $subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
-                    if (! $this->checkout->admin_request) {
149
-                        $template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
-                        $template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
-                            $template_args['ticket_count'][$registration->ticket()->ID()]
152
-                        )
153
-                            ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
-                            : 1;
155
-                        $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
-                            $this->checkout->cart->get_grand_total(),
157
-                            'Ticket',
158
-                            array($registration->ticket()->ID())
159
-                        );
160
-                        $ticket_line_item = is_array($ticket_line_item)
161
-                            ? reset($ticket_line_item)
162
-                            : $ticket_line_item;
163
-                        $template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
-                            $Line_Item_Display->display_line_item($ticket_line_item);
165
-                    }
166
-                    if ($registration->is_primary_registrant()) {
167
-                        $primary_registrant = $registration->reg_url_link();
168
-                    }
169
-                }
170
-            }
171
-            // print_copy_info ?
172
-            if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
-                // TODO: add admin option for toggling copy attendee info,
174
-                // then use that value to change $this->_print_copy_info
175
-                $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
-                    ? $this->_copy_attendee_info_form()
177
-                    : $this->_auto_copy_attendee_info();
178
-                // generate hidden input
179
-                if (isset($subsections[$primary_registrant])
180
-                    && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
-                ) {
182
-                    $subsections[$primary_registrant]->add_subsections(
183
-                        $copy_options,
184
-                        'primary_registrant',
185
-                        false
186
-                    );
187
-                }
188
-            }
189
-        }
190
-
191
-        return new EE_Form_Section_Proper(
192
-            array(
193
-                'name'            => $this->reg_form_name(),
194
-                'html_id'         => $this->reg_form_name(),
195
-                'subsections'     => $subsections,
196
-                'layout_strategy' => $this->checkout->admin_request ?
197
-                    new EE_Div_Per_Section_Layout() :
198
-                    new EE_Template_Layout(
199
-                        array(
200
-                            'layout_template_file' => $this->_template, // layout_template
201
-                            'template_args'        => $template_args,
202
-                        )
203
-                    ),
204
-            )
205
-        );
206
-    }
207
-
208
-
209
-    /**
210
-     * @param EE_Registration $registration
211
-     * @return EE_Form_Section_Base
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
-     */
218
-    private function _registrations_reg_form(EE_Registration $registration)
219
-    {
220
-        static $attendee_nmbr = 1;
221
-        $form_args = array();
222
-        // verify that registration has valid event
223
-        if ($registration->event() instanceof EE_Event) {
224
-            $question_groups = $registration->event()->question_groups(
225
-                apply_filters(
226
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
-                    array(
228
-                        array(
229
-                            'Event.EVT_ID'                     => $registration->event()->ID(),
230
-                            'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
-                        ),
232
-                        'order_by' => array('QSG_order' => 'ASC'),
233
-                    ),
234
-                    $registration,
235
-                    $this
236
-                )
237
-            );
238
-            if ($question_groups) {
239
-                // array of params to pass to parent constructor
240
-                $form_args = array(
241
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
-                    'html_class'      => 'ee-reg-form-attendee-dv',
243
-                    'html_style'      => $this->checkout->admin_request
244
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
-                        : '',
246
-                    'subsections'     => array(),
247
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
248
-                        array(
249
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
-                            'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
-                        )
252
-                    ),
253
-                );
254
-                foreach ($question_groups as $question_group) {
255
-                    if ($question_group instanceof EE_Question_Group) {
256
-                        $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
-                            $registration,
258
-                            $question_group
259
-                        );
260
-                    }
261
-                }
262
-                // add hidden input
263
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
-                    $registration
265
-                );
266
-                // if we have question groups for additional attendees, then display the copy options
267
-                $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
-                if ($registration->is_primary_registrant()) {
269
-                    // generate hidden input
270
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
-                        $registration
272
-                    );
273
-                }
274
-            }
275
-        }
276
-        $attendee_nmbr++;
277
-        return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
-    }
279
-
280
-
281
-    /**
282
-     * _additional_attendee_reg_info_input
283
-     *
284
-     * @access public
285
-     * @param EE_Registration $registration
286
-     * @param bool            $additional_attendee_reg_info
287
-     * @return    EE_Form_Input_Base
288
-     * @throws \EE_Error
289
-     */
290
-    private function _additional_attendee_reg_info_input(
291
-        EE_Registration $registration,
292
-        $additional_attendee_reg_info = true
293
-    ) {
294
-        // generate hidden input
295
-        return new EE_Hidden_Input(
296
-            array(
297
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
-                'default' => $additional_attendee_reg_info,
299
-            )
300
-        );
301
-    }
302
-
303
-
304
-    /**
305
-     * @param EE_Registration   $registration
306
-     * @param EE_Question_Group $question_group
307
-     * @return EE_Form_Section_Proper
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
-     */
313
-    private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
-    {
315
-        // array of params to pass to parent constructor
316
-        $form_args = array(
317
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
318
-            'html_class'      => $this->checkout->admin_request
319
-                ? 'form-table ee-reg-form-qstn-grp-dv'
320
-                : 'ee-reg-form-qstn-grp-dv',
321
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
322
-            'subsections'     => array(
323
-                'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
-            ),
325
-            'layout_strategy' => $this->checkout->admin_request
326
-                ? new EE_Admin_Two_Column_Layout()
327
-                : new EE_Div_Per_Section_Layout(),
328
-        );
329
-        // where params
330
-        $query_params = array('QST_deleted' => 0);
331
-        // don't load admin only questions on the frontend
332
-        if (! $this->checkout->admin_request) {
333
-            $query_params['QST_admin_only'] = array('!=', true);
334
-        }
335
-        $questions = $question_group->get_many_related(
336
-            'Question',
337
-            apply_filters(
338
-                'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
-                array(
340
-                    $query_params,
341
-                    'order_by' => array(
342
-                        'Question_Group_Question.QGQ_order' => 'ASC',
343
-                    ),
344
-                ),
345
-                $question_group,
346
-                $registration,
347
-                $this
348
-            )
349
-        );
350
-        // filter for additional content before questions
351
-        $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
-            apply_filters(
353
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
-                '',
355
-                $registration,
356
-                $question_group,
357
-                $this
358
-            )
359
-        );
360
-        // loop thru questions
361
-        foreach ($questions as $question) {
362
-            if ($question instanceof EE_Question) {
363
-                $identifier                            = $question->is_system_question()
364
-                    ? $question->system_ID()
365
-                    : $question->ID();
366
-                $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
-            }
368
-        }
369
-        $form_args['subsections'] = apply_filters(
370
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
-            $form_args['subsections'],
372
-            $registration,
373
-            $question_group,
374
-            $this
375
-        );
376
-        // filter for additional content after questions
377
-        $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
-            apply_filters(
379
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
-                '',
381
-                $registration,
382
-                $question_group,
383
-                $this
384
-            )
385
-        );
20
+	/**
21
+	 * @type bool $_print_copy_info
22
+	 */
23
+	private $_print_copy_info = false;
24
+
25
+	/**
26
+	 * @type array $_attendee_data
27
+	 */
28
+	private $_attendee_data = array();
29
+
30
+	/**
31
+	 * @type array $_required_questions
32
+	 */
33
+	private $_required_questions = array();
34
+
35
+	/**
36
+	 * @type array $_registration_answers
37
+	 */
38
+	private $_registration_answers = array();
39
+
40
+
41
+	/**
42
+	 *    class constructor
43
+	 *
44
+	 * @access    public
45
+	 * @param    EE_Checkout $checkout
46
+	 */
47
+	public function __construct(EE_Checkout $checkout)
48
+	{
49
+		$this->_slug     = 'attendee_information';
50
+		$this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
+		$this->checkout  = $checkout;
53
+		$this->_reset_success_message();
54
+		$this->set_instructions(
55
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
+		);
57
+	}
58
+
59
+
60
+	public function translate_js_strings()
61
+	{
62
+		EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
+			' is a required question.',
64
+			'event_espresso'
65
+		);
66
+		EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
+			' is a required question. Please enter a value for at least one of the options.',
68
+			'event_espresso'
69
+		);
70
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
+			'Please answer all required questions correctly before proceeding.',
72
+			'event_espresso'
73
+		);
74
+		EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
+			esc_html__(
76
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
+				'event_espresso'
78
+			),
79
+			'<br/>'
80
+		);
81
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
+			'event_espresso'
84
+		);
85
+		EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
+			'You must enter a valid email address.',
87
+			'event_espresso'
88
+		);
89
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
91
+			'event_espresso'
92
+		);
93
+	}
94
+
95
+
96
+	public function enqueue_styles_and_scripts()
97
+	{
98
+	}
99
+
100
+
101
+	/**
102
+	 * @return boolean
103
+	 */
104
+	public function initialize_reg_step()
105
+	{
106
+		return true;
107
+	}
108
+
109
+
110
+	/**
111
+	 * @return EE_Form_Section_Proper
112
+	 * @throws EE_Error
113
+	 * @throws InvalidArgumentException
114
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
+	 */
118
+	public function generate_reg_form()
119
+	{
120
+		$this->_print_copy_info = false;
121
+		$primary_registrant     = null;
122
+		// autoload Line_Item_Display classes
123
+		EEH_Autoloader::register_line_item_display_autoloaders();
124
+		$Line_Item_Display = new EE_Line_Item_Display();
125
+		// calculate taxes
126
+		$Line_Item_Display->display_line_item(
127
+			$this->checkout->cart->get_grand_total(),
128
+			array('set_tax_rate' => true)
129
+		);
130
+		/** @var $subsections EE_Form_Section_Proper[] */
131
+		$subsections   = array(
132
+			'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
+		);
134
+		$template_args = array(
135
+			'revisit'       => $this->checkout->revisit,
136
+			'registrations' => array(),
137
+			'ticket_count'  => array(),
138
+		);
139
+		// grab the saved registrations from the transaction
140
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
+		if ($registrations) {
142
+			foreach ($registrations as $registration) {
143
+				// can this registration be processed during this visit ?
144
+				if ($registration instanceof EE_Registration
145
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
146
+				) {
147
+					$subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
+					if (! $this->checkout->admin_request) {
149
+						$template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
+						$template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
+							$template_args['ticket_count'][$registration->ticket()->ID()]
152
+						)
153
+							? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
+							: 1;
155
+						$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
+							$this->checkout->cart->get_grand_total(),
157
+							'Ticket',
158
+							array($registration->ticket()->ID())
159
+						);
160
+						$ticket_line_item = is_array($ticket_line_item)
161
+							? reset($ticket_line_item)
162
+							: $ticket_line_item;
163
+						$template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
+							$Line_Item_Display->display_line_item($ticket_line_item);
165
+					}
166
+					if ($registration->is_primary_registrant()) {
167
+						$primary_registrant = $registration->reg_url_link();
168
+					}
169
+				}
170
+			}
171
+			// print_copy_info ?
172
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
+				// TODO: add admin option for toggling copy attendee info,
174
+				// then use that value to change $this->_print_copy_info
175
+				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
+					? $this->_copy_attendee_info_form()
177
+					: $this->_auto_copy_attendee_info();
178
+				// generate hidden input
179
+				if (isset($subsections[$primary_registrant])
180
+					&& $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
+				) {
182
+					$subsections[$primary_registrant]->add_subsections(
183
+						$copy_options,
184
+						'primary_registrant',
185
+						false
186
+					);
187
+				}
188
+			}
189
+		}
190
+
191
+		return new EE_Form_Section_Proper(
192
+			array(
193
+				'name'            => $this->reg_form_name(),
194
+				'html_id'         => $this->reg_form_name(),
195
+				'subsections'     => $subsections,
196
+				'layout_strategy' => $this->checkout->admin_request ?
197
+					new EE_Div_Per_Section_Layout() :
198
+					new EE_Template_Layout(
199
+						array(
200
+							'layout_template_file' => $this->_template, // layout_template
201
+							'template_args'        => $template_args,
202
+						)
203
+					),
204
+			)
205
+		);
206
+	}
207
+
208
+
209
+	/**
210
+	 * @param EE_Registration $registration
211
+	 * @return EE_Form_Section_Base
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
+	 */
218
+	private function _registrations_reg_form(EE_Registration $registration)
219
+	{
220
+		static $attendee_nmbr = 1;
221
+		$form_args = array();
222
+		// verify that registration has valid event
223
+		if ($registration->event() instanceof EE_Event) {
224
+			$question_groups = $registration->event()->question_groups(
225
+				apply_filters(
226
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
+					array(
228
+						array(
229
+							'Event.EVT_ID'                     => $registration->event()->ID(),
230
+							'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
+						),
232
+						'order_by' => array('QSG_order' => 'ASC'),
233
+					),
234
+					$registration,
235
+					$this
236
+				)
237
+			);
238
+			if ($question_groups) {
239
+				// array of params to pass to parent constructor
240
+				$form_args = array(
241
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
+					'html_class'      => 'ee-reg-form-attendee-dv',
243
+					'html_style'      => $this->checkout->admin_request
244
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
+						: '',
246
+					'subsections'     => array(),
247
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
248
+						array(
249
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
+							'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
+						)
252
+					),
253
+				);
254
+				foreach ($question_groups as $question_group) {
255
+					if ($question_group instanceof EE_Question_Group) {
256
+						$form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
+							$registration,
258
+							$question_group
259
+						);
260
+					}
261
+				}
262
+				// add hidden input
263
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
+					$registration
265
+				);
266
+				// if we have question groups for additional attendees, then display the copy options
267
+				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
+				if ($registration->is_primary_registrant()) {
269
+					// generate hidden input
270
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
+						$registration
272
+					);
273
+				}
274
+			}
275
+		}
276
+		$attendee_nmbr++;
277
+		return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
+	}
279
+
280
+
281
+	/**
282
+	 * _additional_attendee_reg_info_input
283
+	 *
284
+	 * @access public
285
+	 * @param EE_Registration $registration
286
+	 * @param bool            $additional_attendee_reg_info
287
+	 * @return    EE_Form_Input_Base
288
+	 * @throws \EE_Error
289
+	 */
290
+	private function _additional_attendee_reg_info_input(
291
+		EE_Registration $registration,
292
+		$additional_attendee_reg_info = true
293
+	) {
294
+		// generate hidden input
295
+		return new EE_Hidden_Input(
296
+			array(
297
+				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
+				'default' => $additional_attendee_reg_info,
299
+			)
300
+		);
301
+	}
302
+
303
+
304
+	/**
305
+	 * @param EE_Registration   $registration
306
+	 * @param EE_Question_Group $question_group
307
+	 * @return EE_Form_Section_Proper
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
+	 */
313
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
+	{
315
+		// array of params to pass to parent constructor
316
+		$form_args = array(
317
+			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
318
+			'html_class'      => $this->checkout->admin_request
319
+				? 'form-table ee-reg-form-qstn-grp-dv'
320
+				: 'ee-reg-form-qstn-grp-dv',
321
+			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
322
+			'subsections'     => array(
323
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
+			),
325
+			'layout_strategy' => $this->checkout->admin_request
326
+				? new EE_Admin_Two_Column_Layout()
327
+				: new EE_Div_Per_Section_Layout(),
328
+		);
329
+		// where params
330
+		$query_params = array('QST_deleted' => 0);
331
+		// don't load admin only questions on the frontend
332
+		if (! $this->checkout->admin_request) {
333
+			$query_params['QST_admin_only'] = array('!=', true);
334
+		}
335
+		$questions = $question_group->get_many_related(
336
+			'Question',
337
+			apply_filters(
338
+				'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
+				array(
340
+					$query_params,
341
+					'order_by' => array(
342
+						'Question_Group_Question.QGQ_order' => 'ASC',
343
+					),
344
+				),
345
+				$question_group,
346
+				$registration,
347
+				$this
348
+			)
349
+		);
350
+		// filter for additional content before questions
351
+		$form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
+			apply_filters(
353
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
+				'',
355
+				$registration,
356
+				$question_group,
357
+				$this
358
+			)
359
+		);
360
+		// loop thru questions
361
+		foreach ($questions as $question) {
362
+			if ($question instanceof EE_Question) {
363
+				$identifier                            = $question->is_system_question()
364
+					? $question->system_ID()
365
+					: $question->ID();
366
+				$form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
+			}
368
+		}
369
+		$form_args['subsections'] = apply_filters(
370
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
+			$form_args['subsections'],
372
+			$registration,
373
+			$question_group,
374
+			$this
375
+		);
376
+		// filter for additional content after questions
377
+		$form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
+			apply_filters(
379
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
+				'',
381
+				$registration,
382
+				$question_group,
383
+				$this
384
+			)
385
+		);
386 386
 //		d( $form_args );
387
-        $question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
-        return apply_filters(
389
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
-            $question_group_reg_form,
391
-            $registration,
392
-            $question_group,
393
-            $this
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * @access public
400
-     * @param EE_Question_Group $question_group
401
-     * @return    EE_Form_Section_HTML
402
-     */
403
-    private function _question_group_header(EE_Question_Group $question_group)
404
-    {
405
-        $html = '';
406
-        // group_name
407
-        if ($question_group->show_group_name() && $question_group->name() !== '') {
408
-            if ($this->checkout->admin_request) {
409
-                $html .= EEH_HTML::br();
410
-                $html .= EEH_HTML::h3(
411
-                    $question_group->name(),
412
-                    '',
413
-                    'ee-reg-form-qstn-grp-title title',
414
-                    'font-size: 1.3em; padding-left:0;'
415
-                );
416
-            } else {
417
-                $html .= EEH_HTML::h4(
418
-                    $question_group->name(),
419
-                    '',
420
-                    'ee-reg-form-qstn-grp-title section-title'
421
-                );
422
-            }
423
-        }
424
-        // group_desc
425
-        if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
-            $html .= EEH_HTML::p(
427
-                $question_group->desc(),
428
-                '',
429
-                $this->checkout->admin_request
430
-                    ? 'ee-reg-form-qstn-grp-desc-pg'
431
-                    : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
-            );
433
-        }
434
-        return new EE_Form_Section_HTML($html);
435
-    }
436
-
437
-
438
-    /**
439
-     * @access public
440
-     * @return    EE_Form_Section_Proper
441
-     * @throws \EE_Error
442
-     */
443
-    private function _copy_attendee_info_form()
444
-    {
445
-        // array of params to pass to parent constructor
446
-        return new EE_Form_Section_Proper(
447
-            array(
448
-                'subsections'     => $this->_copy_attendee_info_inputs(),
449
-                'layout_strategy' => new EE_Template_Layout(
450
-                    array(
451
-                        'layout_template_file'     => SPCO_REG_STEPS_PATH
452
-                                                      . $this->_slug
453
-                                                      . DS
454
-                                                      . 'copy_attendee_info.template.php',
455
-                        'begin_template_file'      => null,
456
-                        'input_template_file'      => null,
457
-                        'subsection_template_file' => null,
458
-                        'end_template_file'        => null,
459
-                    )
460
-                ),
461
-            )
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * _auto_copy_attendee_info
468
-     *
469
-     * @access public
470
-     * @return EE_Form_Section_HTML
471
-     */
472
-    private function _auto_copy_attendee_info()
473
-    {
474
-        return new EE_Form_Section_HTML(
475
-            EEH_Template::locate_template(
476
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
-                apply_filters(
478
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
-                    array()
480
-                ),
481
-                true,
482
-                true
483
-            )
484
-        );
485
-    }
486
-
487
-
488
-    /**
489
-     * _copy_attendee_info_inputs
490
-     *
491
-     * @access public
492
-     * @return array
493
-     * @throws \EE_Error
494
-     */
495
-    private function _copy_attendee_info_inputs()
496
-    {
497
-        $copy_attendee_info_inputs = array();
498
-        $prev_ticket               = null;
499
-        // grab the saved registrations from the transaction
500
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
-        foreach ($registrations as $registration) {
502
-            // for all  attendees other than the primary attendee
503
-            if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
-                // if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
-                if ($registration->ticket()->ID() !== $prev_ticket) {
506
-                    $item_name = $registration->ticket()->name();
507
-                    $item_name .= $registration->ticket()->description() !== ''
508
-                        ? ' - ' . $registration->ticket()->description()
509
-                        : '';
510
-                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
-                        new EE_Form_Section_HTML(
512
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
-                        );
514
-                    $prev_ticket = $registration->ticket()->ID();
515
-                }
516
-
517
-                $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
-                    new EE_Checkbox_Multi_Input(
519
-                        array(
520
-                            $registration->ID() => sprintf(
521
-                                esc_html__('Attendee #%s', 'event_espresso'),
522
-                                $registration->count()
523
-                            ),
524
-                        ),
525
-                        array(
526
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
-                            'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
-                            'display_html_label_text' => false,
529
-                        )
530
-                    );
531
-            }
532
-        }
533
-        return $copy_attendee_info_inputs;
534
-    }
535
-
536
-
537
-    /**
538
-     * _additional_primary_registrant_inputs
539
-     *
540
-     * @access public
541
-     * @param EE_Registration $registration
542
-     * @return    EE_Form_Input_Base
543
-     * @throws \EE_Error
544
-     */
545
-    private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
-    {
547
-        // generate hidden input
548
-        return new EE_Hidden_Input(
549
-            array(
550
-                'html_id' => 'primary_registrant',
551
-                'default' => $registration->reg_url_link(),
552
-            )
553
-        );
554
-    }
555
-
556
-
557
-    /**
558
-     * @access public
559
-     * @param EE_Registration $registration
560
-     * @param EE_Question     $question
561
-     * @return EE_Form_Input_Base
562
-     * @throws EE_Error
563
-     * @throws InvalidArgumentException
564
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
-     */
567
-    public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
-    {
569
-
570
-        // if this question was for an attendee detail, then check for that answer
571
-        $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
-            $registration,
573
-            $question->system_ID()
574
-        );
575
-        $answer       = $answer_value === null
576
-            ? EEM_Answer::instance()->get_one(
577
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
-            )
579
-            : null;
580
-        // if NOT returning to edit an existing registration
581
-        // OR if this question is for an attendee property
582
-        // OR we still don't have an EE_Answer object
583
-        if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
-            // create an EE_Answer object for storing everything in
585
-            $answer = EE_Answer::new_instance(array(
586
-                'QST_ID' => $question->ID(),
587
-                'REG_ID' => $registration->ID(),
588
-            ));
589
-        }
590
-        // verify instance
591
-        if ($answer instanceof EE_Answer) {
592
-            if (! empty($answer_value)) {
593
-                $answer->set('ANS_value', $answer_value);
594
-            }
595
-            $answer->cache('Question', $question);
596
-            //remember system ID had a bug where sometimes it could be null
597
-            $answer_cache_id = $question->is_system_question()
598
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
599
-                : $question->ID() . '-' . $registration->reg_url_link();
600
-            $registration->cache('Answer', $answer, $answer_cache_id);
601
-        }
602
-        return $this->_generate_question_input($registration, $question, $answer);
603
-    }
604
-
605
-
606
-    /**
607
-     * @param EE_Registration $registration
608
-     * @param EE_Question     $question
609
-     * @param                 mixed EE_Answer|NULL      $answer
610
-     * @return EE_Form_Input_Base
611
-     * @throws \EE_Error
612
-     */
613
-    private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
-    {
615
-        $identifier                             = $question->is_system_question()
616
-            ? $question->system_ID()
617
-            : $question->ID();
618
-        $this->_required_questions[$identifier] = $question->required() ? true : false;
619
-        add_filter(
620
-            'FHEE__EE_Question__generate_form_input__country_options',
621
-            array($this, 'use_cached_countries_for_form_input'),
622
-            10,
623
-            4
624
-        );
625
-        add_filter(
626
-            'FHEE__EE_Question__generate_form_input__state_options',
627
-            array($this, 'use_cached_states_for_form_input'),
628
-            10,
629
-            4
630
-        );
631
-        $input_constructor_args                  = array(
632
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
-            'html_label_class' => 'ee-reg-qstn',
637
-        );
638
-        $input_constructor_args['html_label_id'] .= '-lbl';
639
-        if ($answer instanceof EE_Answer && $answer->ID()) {
640
-            $input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
-            $input_constructor_args['html_id']       .= '-' . $answer->ID();
642
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
-        }
644
-        $form_input = $question->generate_form_input(
645
-            $registration,
646
-            $answer,
647
-            $input_constructor_args
648
-        );
649
-        remove_filter(
650
-            'FHEE__EE_Question__generate_form_input__country_options',
651
-            array($this, 'use_cached_countries_for_form_input')
652
-        );
653
-        remove_filter(
654
-            'FHEE__EE_Question__generate_form_input__state_options',
655
-            array($this, 'use_cached_states_for_form_input')
656
-        );
657
-        return $form_input;
658
-    }
659
-
660
-
661
-    /**
662
-     * Gets the list of countries for the form input
663
-     *
664
-     * @param array|null       $countries_list
665
-     * @param \EE_Question     $question
666
-     * @param \EE_Registration $registration
667
-     * @param \EE_Answer       $answer
668
-     * @return array 2d keys are country IDs, values are their names
669
-     * @throws EE_Error
670
-     * @throws InvalidArgumentException
671
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
-     */
674
-    public function use_cached_countries_for_form_input(
675
-        $countries_list,
676
-        \EE_Question $question = null,
677
-        \EE_Registration $registration = null,
678
-        \EE_Answer $answer = null
679
-    ) {
680
-        $country_options = array('' => '');
681
-        // get possibly cached list of countries
682
-        $countries = $this->checkout->action === 'process_reg_step'
683
-            ? EEM_Country::instance()->get_all_countries()
684
-            : EEM_Country::instance()->get_all_active_countries();
685
-        if (! empty($countries)) {
686
-            foreach ($countries as $country) {
687
-                if ($country instanceof EE_Country) {
688
-                    $country_options[$country->ID()] = $country->name();
689
-                }
690
-            }
691
-        }
692
-        if ($question instanceof EE_Question
693
-            && $registration instanceof EE_Registration) {
694
-            $answer = EEM_Answer::instance()->get_one(
695
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
-            );
697
-        } else {
698
-            $answer = EE_Answer::new_instance();
699
-        }
700
-        $country_options = apply_filters(
701
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
-            $country_options,
703
-            $this,
704
-            $registration,
705
-            $question,
706
-            $answer
707
-        );
708
-        return $country_options;
709
-    }
710
-
711
-
712
-    /**
713
-     * Gets the list of states for the form input
714
-     *
715
-     * @param array|null       $states_list
716
-     * @param \EE_Question     $question
717
-     * @param \EE_Registration $registration
718
-     * @param \EE_Answer       $answer
719
-     * @return array 2d keys are state IDs, values are their names
720
-     * @throws EE_Error
721
-     * @throws InvalidArgumentException
722
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
-     */
725
-    public function use_cached_states_for_form_input(
726
-        $states_list,
727
-        \EE_Question $question = null,
728
-        \EE_Registration $registration = null,
729
-        \EE_Answer $answer = null
730
-    ) {
731
-        $state_options = array('' => array('' => ''));
732
-        $states        = $this->checkout->action === 'process_reg_step'
733
-            ? EEM_State::instance()->get_all_states()
734
-            : EEM_State::instance()->get_all_active_states();
735
-        if (! empty($states)) {
736
-            foreach ($states as $state) {
737
-                if ($state instanceof EE_State) {
738
-                    $state_options[$state->country()->name()][$state->ID()] = $state->name();
739
-                }
740
-            }
741
-        }
742
-        $state_options = apply_filters(
743
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
-            $state_options,
745
-            $this,
746
-            $registration,
747
-            $question,
748
-            $answer
749
-        );
750
-        return $state_options;
751
-    }
752
-
753
-
754
-
755
-
756
-
757
-
758
-    /********************************************************************************************************/
759
-    /****************************************  PROCESS REG STEP  ****************************************/
760
-    /********************************************************************************************************/
761
-    /**
762
-     * @return bool
763
-     * @throws EE_Error
764
-     * @throws InvalidArgumentException
765
-     * @throws ReflectionException
766
-     * @throws RuntimeException
767
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
-     */
770
-    public function process_reg_step()
771
-    {
772
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
-        // grab validated data from form
774
-        $valid_data = $this->checkout->current_step->valid_data();
775
-        // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
-        // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
-        if (empty($valid_data)) {
779
-            EE_Error::add_error(
780
-                esc_html__('No valid question responses were received.', 'event_espresso'),
781
-                __FILE__,
782
-                __FUNCTION__,
783
-                __LINE__
784
-            );
785
-            return false;
786
-        }
787
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
-            EE_Error::add_error(
789
-                esc_html__(
790
-                    'A valid transaction could not be initiated for processing your registrations.',
791
-                    'event_espresso'
792
-                ),
793
-                __FILE__,
794
-                __FUNCTION__,
795
-                __LINE__
796
-            );
797
-            return false;
798
-        }
799
-        // get cached registrations
800
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
-        // verify we got the goods
802
-        if (empty($registrations)) {
803
-            EE_Error::add_error(
804
-                esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
805
-                __FILE__,
806
-                __FUNCTION__,
807
-                __LINE__
808
-            );
809
-            return false;
810
-        }
811
-        // extract attendee info from form data and save to model objects
812
-        $registrations_processed = $this->_process_registrations($registrations, $valid_data);
813
-        // if first pass thru SPCO,
814
-        // then let's check processed registrations against the total number of tickets in the cart
815
-        if ($registrations_processed === false) {
816
-            // but return immediately if the previous step exited early due to errors
817
-            return false;
818
-        } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
819
-            // generate a correctly translated string for all possible singular/plural combinations
820
-            if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
821
-                $error_msg = sprintf(
822
-                    esc_html__(
823
-                        'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
824
-                        'event_espresso'
825
-                    ),
826
-                    $this->checkout->total_ticket_count,
827
-                    $registrations_processed
828
-                );
829
-            } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
-                $error_msg = sprintf(
831
-                    esc_html__(
832
-                        'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
-                        'event_espresso'
834
-                    ),
835
-                    $this->checkout->total_ticket_count,
836
-                    $registrations_processed
837
-                );
838
-            } else {
839
-                $error_msg = sprintf(
840
-                    esc_html__(
841
-                        'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
842
-                        'event_espresso'
843
-                    ),
844
-                    $this->checkout->total_ticket_count,
845
-                    $registrations_processed
846
-                );
847
-            }
848
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
-            return false;
850
-        }
851
-        // mark this reg step as completed
852
-        $this->set_completed();
853
-        $this->_set_success_message(
854
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
855
-        );
856
-        //do action in case a plugin wants to do something with the data submitted in step 1.
857
-        //passes EE_Single_Page_Checkout, and it's posted data
858
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
859
-        return true;
860
-    }
861
-
862
-
863
-    /**
864
-     *    _process_registrations
865
-     *
866
-     * @param EE_Registration[] $registrations
867
-     * @param array             $valid_data
868
-     * @return bool|int
869
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
870
-     * @throws EE_Error
871
-     * @throws InvalidArgumentException
872
-     * @throws ReflectionException
873
-     * @throws RuntimeException
874
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
875
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
876
-     */
877
-    private function _process_registrations($registrations = array(), $valid_data = array())
878
-    {
879
-        // load resources and set some defaults
880
-        EE_Registry::instance()->load_model('Attendee');
881
-        // holder for primary registrant attendee object
882
-        $this->checkout->primary_attendee_obj = null;
883
-        // array for tracking reg form data for the primary registrant
884
-        $primary_registrant = array(
885
-            'line_item_id' => null,
886
-        );
887
-        $copy_primary       = false;
888
-        // reg form sections that do not contain inputs
889
-        $non_input_form_sections = array(
890
-            'primary_registrant',
891
-            'additional_attendee_reg_info',
892
-            'spco_copy_attendee_chk',
893
-        );
894
-        // attendee counter
895
-        $att_nmbr = 0;
896
-        // grab the saved registrations from the transaction
897
-        foreach ($registrations as $registration) {
898
-            // verify EE_Registration object
899
-            if (! $registration instanceof EE_Registration) {
900
-                EE_Error::add_error(
901
-                    esc_html__(
902
-                        'An invalid Registration object was discovered when attempting to process your registration information.',
903
-                        'event_espresso'
904
-                    ),
905
-                    __FILE__,
906
-                    __FUNCTION__,
907
-                    __LINE__
908
-                );
909
-                return false;
910
-            }
911
-            /** @var string $reg_url_link */
912
-            $reg_url_link = $registration->reg_url_link();
913
-            // reg_url_link exists ?
914
-            if (! empty($reg_url_link)) {
915
-                // should this registration be processed during this visit ?
916
-                if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
917
-                    // if NOT revisiting, then let's save the registration now,
918
-                    // so that we have a REG_ID to use when generating other objects
919
-                    if (! $this->checkout->revisit) {
920
-                        $registration->save();
921
-                    }
922
-                    /**
923
-                     * This allows plugins to trigger a fail on processing of a
924
-                     * registration for any conditions they may have for it to pass.
925
-                     *
926
-                     * @var bool   if true is returned by the plugin then the
927
-                     *            registration processing is halted.
928
-                     */
929
-                    if (apply_filters(
930
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
931
-                        false,
932
-                        $att_nmbr,
933
-                        $registration,
934
-                        $registrations,
935
-                        $valid_data,
936
-                        $this
937
-                    )) {
938
-                        return false;
939
-                    }
940
-
941
-                    // Houston, we have a registration!
942
-                    $att_nmbr++;
943
-                    $this->_attendee_data[$reg_url_link] = array();
944
-                    // grab any existing related answer objects
945
-                    $this->_registration_answers = $registration->answers();
946
-                    // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
947
-                    if (isset($valid_data[$reg_url_link])) {
948
-                        // do we need to copy basic info from primary attendee ?
949
-                        $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
950
-                                        && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
951
-                            ? true
952
-                            : false;
953
-                        // filter form input data for this registration
954
-                        $valid_data[$reg_url_link] = (array)apply_filters(
955
-                            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
956
-                            $valid_data[$reg_url_link]
957
-                        );
958
-                        if (isset($valid_data['primary_attendee'])) {
959
-                            $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
960
-                                ? $valid_data['primary_attendee']
961
-                                : false;
962
-                            unset($valid_data['primary_attendee']);
963
-                        }
964
-                        // now loop through our array of valid post data && process attendee reg forms
965
-                        foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
966
-                            if (! in_array($form_section, $non_input_form_sections)) {
967
-                                foreach ($form_inputs as $form_input => $input_value) {
968
-                                    // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
969
-                                    // check for critical inputs
970
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
971
-                                        $form_input,
972
-                                        $input_value
973
-                                    )
974
-                                    ) {
975
-                                        return false;
976
-                                    }
977
-                                    // store a bit of data about the primary attendee
978
-                                    if ($att_nmbr === 1
979
-                                        && ! empty($input_value)
980
-                                        && $reg_url_link === $primary_registrant['line_item_id']
981
-                                    ) {
982
-                                        $primary_registrant[$form_input] = $input_value;
983
-                                    } elseif ($copy_primary
984
-                                        && $input_value === null
985
-                                        && isset($primary_registrant[$form_input])
986
-                                    ) {
987
-                                        $input_value = $primary_registrant[$form_input];
988
-                                    }
989
-                                    // now attempt to save the input data
990
-                                    if (! $this->_save_registration_form_input(
991
-                                        $registration,
992
-                                        $form_input,
993
-                                        $input_value
994
-                                    )
995
-                                    ) {
996
-                                        EE_Error::add_error(
997
-                                            sprintf(
998
-                                                esc_html__(
999
-                                                    'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1000
-                                                    'event_espresso'
1001
-                                                ),
1002
-                                                $form_input,
1003
-                                                $input_value
1004
-                                            ),
1005
-                                            __FILE__,
1006
-                                            __FUNCTION__,
1007
-                                            __LINE__
1008
-                                        );
1009
-                                        return false;
1010
-                                    }
1011
-                                }
1012
-                            }
1013
-                        }  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1014
-                    }
1015
-                    //EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1016
-                    // this registration does not require additional attendee information ?
1017
-                    if ($copy_primary
1018
-                        && $att_nmbr > 1
1019
-                        && $this->checkout->primary_attendee_obj instanceof EE_Attendee
1020
-                    ) {
1021
-                        // just copy the primary registrant
1022
-                        $attendee = $this->checkout->primary_attendee_obj;
1023
-                    } else {
1024
-                        // ensure critical details are set for additional attendees
1025
-                        $this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1026
-                            ? $this->_copy_critical_attendee_details_from_primary_registrant(
1027
-                                $this->_attendee_data[$reg_url_link]
1028
-                            )
1029
-                            : $this->_attendee_data[$reg_url_link];
1030
-                        // execute create attendee command (which may return an existing attendee)
1031
-                        $attendee = EE_Registry::instance()->BUS->execute(
1032
-                            new CreateAttendeeCommand(
1033
-                                $this->_attendee_data[$reg_url_link],
1034
-                                $registration
1035
-                            )
1036
-                        );
1037
-                        // who's #1 ?
1038
-                        if ($att_nmbr === 1) {
1039
-                            $this->checkout->primary_attendee_obj = $attendee;
1040
-                        }
1041
-                    }
1042
-                    // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1043
-                    // add relation to registration, set attendee ID, and cache attendee
1044
-                    $this->_associate_attendee_with_registration($registration, $attendee);
1045
-                    // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1046
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1047
-                        EE_Error::add_error(
1048
-                            sprintf(
1049
-                                esc_html__(
1050
-                                    'Registration %s has an invalid or missing Attendee object.',
1051
-                                    'event_espresso'
1052
-                                ),
1053
-                                $reg_url_link
1054
-                            ),
1055
-                            __FILE__,
1056
-                            __FUNCTION__,
1057
-                            __LINE__
1058
-                        );
1059
-                        return false;
1060
-                    }
1061
-                    /** @type EE_Registration_Processor $registration_processor */
1062
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1063
-                    // at this point, we should have enough details about the registrant to consider the registration
1064
-                    // NOT incomplete
1065
-                    $registration_processor->toggle_incomplete_registration_status_to_default(
1066
-                        $registration,
1067
-                        false,
1068
-                        new Context(
1069
-                            'spco_reg_step_attendee_information_process_registrations',
1070
-                            esc_html__(
1071
-                                'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1072
-                                'event_espresso'
1073
-                            )
1074
-                        )
1075
-                    );
1076
-                    // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1077
-                    // abandoned
1078
-                    $this->checkout->transaction->toggle_failed_transaction_status();
1079
-                    // if we've gotten this far, then let's save what we have
1080
-                    $registration->save();
1081
-                    // add relation between TXN and registration
1082
-                    $this->_associate_registration_with_transaction($registration);
1083
-                }
1084
-            } else {
1085
-                EE_Error::add_error(
1086
-                    esc_html__(
1087
-                        'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1088
-                        'event_espresso'
1089
-                    ),
1090
-                    __FILE__,
1091
-                    __FUNCTION__,
1092
-                    __LINE__
1093
-                );
1094
-                // remove malformed data
1095
-                unset($valid_data[$reg_url_link]);
1096
-                return false;
1097
-            }
1098
-
1099
-        } // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1100
-        return $att_nmbr;
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     *    _save_registration_form_input
1106
-     *
1107
-     * @param EE_Registration $registration
1108
-     * @param string          $form_input
1109
-     * @param string          $input_value
1110
-     * @return bool
1111
-     * @throws EE_Error
1112
-     * @throws InvalidArgumentException
1113
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1114
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1115
-     */
1116
-    private function _save_registration_form_input(
1117
-        EE_Registration $registration,
1118
-        $form_input = '',
1119
-        $input_value = ''
1120
-    ) {
1121
-        // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1122
-        // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1123
-        // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1124
-        // allow for plugins to hook in and do their own processing of the form input.
1125
-        // For plugins to bypass normal processing here, they just need to return a boolean value.
1126
-        if (apply_filters(
1127
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1128
-            false,
1129
-            $registration,
1130
-            $form_input,
1131
-            $input_value,
1132
-            $this
1133
-        )) {
1134
-            return true;
1135
-        }
1136
-        /*
387
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
+		return apply_filters(
389
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
+			$question_group_reg_form,
391
+			$registration,
392
+			$question_group,
393
+			$this
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * @access public
400
+	 * @param EE_Question_Group $question_group
401
+	 * @return    EE_Form_Section_HTML
402
+	 */
403
+	private function _question_group_header(EE_Question_Group $question_group)
404
+	{
405
+		$html = '';
406
+		// group_name
407
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
408
+			if ($this->checkout->admin_request) {
409
+				$html .= EEH_HTML::br();
410
+				$html .= EEH_HTML::h3(
411
+					$question_group->name(),
412
+					'',
413
+					'ee-reg-form-qstn-grp-title title',
414
+					'font-size: 1.3em; padding-left:0;'
415
+				);
416
+			} else {
417
+				$html .= EEH_HTML::h4(
418
+					$question_group->name(),
419
+					'',
420
+					'ee-reg-form-qstn-grp-title section-title'
421
+				);
422
+			}
423
+		}
424
+		// group_desc
425
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
+			$html .= EEH_HTML::p(
427
+				$question_group->desc(),
428
+				'',
429
+				$this->checkout->admin_request
430
+					? 'ee-reg-form-qstn-grp-desc-pg'
431
+					: 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
+			);
433
+		}
434
+		return new EE_Form_Section_HTML($html);
435
+	}
436
+
437
+
438
+	/**
439
+	 * @access public
440
+	 * @return    EE_Form_Section_Proper
441
+	 * @throws \EE_Error
442
+	 */
443
+	private function _copy_attendee_info_form()
444
+	{
445
+		// array of params to pass to parent constructor
446
+		return new EE_Form_Section_Proper(
447
+			array(
448
+				'subsections'     => $this->_copy_attendee_info_inputs(),
449
+				'layout_strategy' => new EE_Template_Layout(
450
+					array(
451
+						'layout_template_file'     => SPCO_REG_STEPS_PATH
452
+													  . $this->_slug
453
+													  . DS
454
+													  . 'copy_attendee_info.template.php',
455
+						'begin_template_file'      => null,
456
+						'input_template_file'      => null,
457
+						'subsection_template_file' => null,
458
+						'end_template_file'        => null,
459
+					)
460
+				),
461
+			)
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * _auto_copy_attendee_info
468
+	 *
469
+	 * @access public
470
+	 * @return EE_Form_Section_HTML
471
+	 */
472
+	private function _auto_copy_attendee_info()
473
+	{
474
+		return new EE_Form_Section_HTML(
475
+			EEH_Template::locate_template(
476
+				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
+				apply_filters(
478
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
+					array()
480
+				),
481
+				true,
482
+				true
483
+			)
484
+		);
485
+	}
486
+
487
+
488
+	/**
489
+	 * _copy_attendee_info_inputs
490
+	 *
491
+	 * @access public
492
+	 * @return array
493
+	 * @throws \EE_Error
494
+	 */
495
+	private function _copy_attendee_info_inputs()
496
+	{
497
+		$copy_attendee_info_inputs = array();
498
+		$prev_ticket               = null;
499
+		// grab the saved registrations from the transaction
500
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
+		foreach ($registrations as $registration) {
502
+			// for all  attendees other than the primary attendee
503
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
+				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
+				if ($registration->ticket()->ID() !== $prev_ticket) {
506
+					$item_name = $registration->ticket()->name();
507
+					$item_name .= $registration->ticket()->description() !== ''
508
+						? ' - ' . $registration->ticket()->description()
509
+						: '';
510
+					$copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
+						new EE_Form_Section_HTML(
512
+							'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
+						);
514
+					$prev_ticket = $registration->ticket()->ID();
515
+				}
516
+
517
+				$copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
+					new EE_Checkbox_Multi_Input(
519
+						array(
520
+							$registration->ID() => sprintf(
521
+								esc_html__('Attendee #%s', 'event_espresso'),
522
+								$registration->count()
523
+							),
524
+						),
525
+						array(
526
+							'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
+							'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
+							'display_html_label_text' => false,
529
+						)
530
+					);
531
+			}
532
+		}
533
+		return $copy_attendee_info_inputs;
534
+	}
535
+
536
+
537
+	/**
538
+	 * _additional_primary_registrant_inputs
539
+	 *
540
+	 * @access public
541
+	 * @param EE_Registration $registration
542
+	 * @return    EE_Form_Input_Base
543
+	 * @throws \EE_Error
544
+	 */
545
+	private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
+	{
547
+		// generate hidden input
548
+		return new EE_Hidden_Input(
549
+			array(
550
+				'html_id' => 'primary_registrant',
551
+				'default' => $registration->reg_url_link(),
552
+			)
553
+		);
554
+	}
555
+
556
+
557
+	/**
558
+	 * @access public
559
+	 * @param EE_Registration $registration
560
+	 * @param EE_Question     $question
561
+	 * @return EE_Form_Input_Base
562
+	 * @throws EE_Error
563
+	 * @throws InvalidArgumentException
564
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
+	 */
567
+	public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
+	{
569
+
570
+		// if this question was for an attendee detail, then check for that answer
571
+		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
+			$registration,
573
+			$question->system_ID()
574
+		);
575
+		$answer       = $answer_value === null
576
+			? EEM_Answer::instance()->get_one(
577
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
+			)
579
+			: null;
580
+		// if NOT returning to edit an existing registration
581
+		// OR if this question is for an attendee property
582
+		// OR we still don't have an EE_Answer object
583
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
+			// create an EE_Answer object for storing everything in
585
+			$answer = EE_Answer::new_instance(array(
586
+				'QST_ID' => $question->ID(),
587
+				'REG_ID' => $registration->ID(),
588
+			));
589
+		}
590
+		// verify instance
591
+		if ($answer instanceof EE_Answer) {
592
+			if (! empty($answer_value)) {
593
+				$answer->set('ANS_value', $answer_value);
594
+			}
595
+			$answer->cache('Question', $question);
596
+			//remember system ID had a bug where sometimes it could be null
597
+			$answer_cache_id = $question->is_system_question()
598
+				? $question->system_ID() . '-' . $registration->reg_url_link()
599
+				: $question->ID() . '-' . $registration->reg_url_link();
600
+			$registration->cache('Answer', $answer, $answer_cache_id);
601
+		}
602
+		return $this->_generate_question_input($registration, $question, $answer);
603
+	}
604
+
605
+
606
+	/**
607
+	 * @param EE_Registration $registration
608
+	 * @param EE_Question     $question
609
+	 * @param                 mixed EE_Answer|NULL      $answer
610
+	 * @return EE_Form_Input_Base
611
+	 * @throws \EE_Error
612
+	 */
613
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
+	{
615
+		$identifier                             = $question->is_system_question()
616
+			? $question->system_ID()
617
+			: $question->ID();
618
+		$this->_required_questions[$identifier] = $question->required() ? true : false;
619
+		add_filter(
620
+			'FHEE__EE_Question__generate_form_input__country_options',
621
+			array($this, 'use_cached_countries_for_form_input'),
622
+			10,
623
+			4
624
+		);
625
+		add_filter(
626
+			'FHEE__EE_Question__generate_form_input__state_options',
627
+			array($this, 'use_cached_states_for_form_input'),
628
+			10,
629
+			4
630
+		);
631
+		$input_constructor_args                  = array(
632
+			'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
+			'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
+			'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
+			'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
+			'html_label_class' => 'ee-reg-qstn',
637
+		);
638
+		$input_constructor_args['html_label_id'] .= '-lbl';
639
+		if ($answer instanceof EE_Answer && $answer->ID()) {
640
+			$input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
+			$input_constructor_args['html_id']       .= '-' . $answer->ID();
642
+			$input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
+		}
644
+		$form_input = $question->generate_form_input(
645
+			$registration,
646
+			$answer,
647
+			$input_constructor_args
648
+		);
649
+		remove_filter(
650
+			'FHEE__EE_Question__generate_form_input__country_options',
651
+			array($this, 'use_cached_countries_for_form_input')
652
+		);
653
+		remove_filter(
654
+			'FHEE__EE_Question__generate_form_input__state_options',
655
+			array($this, 'use_cached_states_for_form_input')
656
+		);
657
+		return $form_input;
658
+	}
659
+
660
+
661
+	/**
662
+	 * Gets the list of countries for the form input
663
+	 *
664
+	 * @param array|null       $countries_list
665
+	 * @param \EE_Question     $question
666
+	 * @param \EE_Registration $registration
667
+	 * @param \EE_Answer       $answer
668
+	 * @return array 2d keys are country IDs, values are their names
669
+	 * @throws EE_Error
670
+	 * @throws InvalidArgumentException
671
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
+	 */
674
+	public function use_cached_countries_for_form_input(
675
+		$countries_list,
676
+		\EE_Question $question = null,
677
+		\EE_Registration $registration = null,
678
+		\EE_Answer $answer = null
679
+	) {
680
+		$country_options = array('' => '');
681
+		// get possibly cached list of countries
682
+		$countries = $this->checkout->action === 'process_reg_step'
683
+			? EEM_Country::instance()->get_all_countries()
684
+			: EEM_Country::instance()->get_all_active_countries();
685
+		if (! empty($countries)) {
686
+			foreach ($countries as $country) {
687
+				if ($country instanceof EE_Country) {
688
+					$country_options[$country->ID()] = $country->name();
689
+				}
690
+			}
691
+		}
692
+		if ($question instanceof EE_Question
693
+			&& $registration instanceof EE_Registration) {
694
+			$answer = EEM_Answer::instance()->get_one(
695
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
+			);
697
+		} else {
698
+			$answer = EE_Answer::new_instance();
699
+		}
700
+		$country_options = apply_filters(
701
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
+			$country_options,
703
+			$this,
704
+			$registration,
705
+			$question,
706
+			$answer
707
+		);
708
+		return $country_options;
709
+	}
710
+
711
+
712
+	/**
713
+	 * Gets the list of states for the form input
714
+	 *
715
+	 * @param array|null       $states_list
716
+	 * @param \EE_Question     $question
717
+	 * @param \EE_Registration $registration
718
+	 * @param \EE_Answer       $answer
719
+	 * @return array 2d keys are state IDs, values are their names
720
+	 * @throws EE_Error
721
+	 * @throws InvalidArgumentException
722
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
+	 */
725
+	public function use_cached_states_for_form_input(
726
+		$states_list,
727
+		\EE_Question $question = null,
728
+		\EE_Registration $registration = null,
729
+		\EE_Answer $answer = null
730
+	) {
731
+		$state_options = array('' => array('' => ''));
732
+		$states        = $this->checkout->action === 'process_reg_step'
733
+			? EEM_State::instance()->get_all_states()
734
+			: EEM_State::instance()->get_all_active_states();
735
+		if (! empty($states)) {
736
+			foreach ($states as $state) {
737
+				if ($state instanceof EE_State) {
738
+					$state_options[$state->country()->name()][$state->ID()] = $state->name();
739
+				}
740
+			}
741
+		}
742
+		$state_options = apply_filters(
743
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
+			$state_options,
745
+			$this,
746
+			$registration,
747
+			$question,
748
+			$answer
749
+		);
750
+		return $state_options;
751
+	}
752
+
753
+
754
+
755
+
756
+
757
+
758
+	/********************************************************************************************************/
759
+	/****************************************  PROCESS REG STEP  ****************************************/
760
+	/********************************************************************************************************/
761
+	/**
762
+	 * @return bool
763
+	 * @throws EE_Error
764
+	 * @throws InvalidArgumentException
765
+	 * @throws ReflectionException
766
+	 * @throws RuntimeException
767
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
+	 */
770
+	public function process_reg_step()
771
+	{
772
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
+		// grab validated data from form
774
+		$valid_data = $this->checkout->current_step->valid_data();
775
+		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
+		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
+		if (empty($valid_data)) {
779
+			EE_Error::add_error(
780
+				esc_html__('No valid question responses were received.', 'event_espresso'),
781
+				__FILE__,
782
+				__FUNCTION__,
783
+				__LINE__
784
+			);
785
+			return false;
786
+		}
787
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
+			EE_Error::add_error(
789
+				esc_html__(
790
+					'A valid transaction could not be initiated for processing your registrations.',
791
+					'event_espresso'
792
+				),
793
+				__FILE__,
794
+				__FUNCTION__,
795
+				__LINE__
796
+			);
797
+			return false;
798
+		}
799
+		// get cached registrations
800
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
+		// verify we got the goods
802
+		if (empty($registrations)) {
803
+			EE_Error::add_error(
804
+				esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
805
+				__FILE__,
806
+				__FUNCTION__,
807
+				__LINE__
808
+			);
809
+			return false;
810
+		}
811
+		// extract attendee info from form data and save to model objects
812
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
813
+		// if first pass thru SPCO,
814
+		// then let's check processed registrations against the total number of tickets in the cart
815
+		if ($registrations_processed === false) {
816
+			// but return immediately if the previous step exited early due to errors
817
+			return false;
818
+		} elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
819
+			// generate a correctly translated string for all possible singular/plural combinations
820
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
821
+				$error_msg = sprintf(
822
+					esc_html__(
823
+						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
824
+						'event_espresso'
825
+					),
826
+					$this->checkout->total_ticket_count,
827
+					$registrations_processed
828
+				);
829
+			} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
+				$error_msg = sprintf(
831
+					esc_html__(
832
+						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
+						'event_espresso'
834
+					),
835
+					$this->checkout->total_ticket_count,
836
+					$registrations_processed
837
+				);
838
+			} else {
839
+				$error_msg = sprintf(
840
+					esc_html__(
841
+						'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
842
+						'event_espresso'
843
+					),
844
+					$this->checkout->total_ticket_count,
845
+					$registrations_processed
846
+				);
847
+			}
848
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
+			return false;
850
+		}
851
+		// mark this reg step as completed
852
+		$this->set_completed();
853
+		$this->_set_success_message(
854
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
855
+		);
856
+		//do action in case a plugin wants to do something with the data submitted in step 1.
857
+		//passes EE_Single_Page_Checkout, and it's posted data
858
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
859
+		return true;
860
+	}
861
+
862
+
863
+	/**
864
+	 *    _process_registrations
865
+	 *
866
+	 * @param EE_Registration[] $registrations
867
+	 * @param array             $valid_data
868
+	 * @return bool|int
869
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
870
+	 * @throws EE_Error
871
+	 * @throws InvalidArgumentException
872
+	 * @throws ReflectionException
873
+	 * @throws RuntimeException
874
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
875
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
876
+	 */
877
+	private function _process_registrations($registrations = array(), $valid_data = array())
878
+	{
879
+		// load resources and set some defaults
880
+		EE_Registry::instance()->load_model('Attendee');
881
+		// holder for primary registrant attendee object
882
+		$this->checkout->primary_attendee_obj = null;
883
+		// array for tracking reg form data for the primary registrant
884
+		$primary_registrant = array(
885
+			'line_item_id' => null,
886
+		);
887
+		$copy_primary       = false;
888
+		// reg form sections that do not contain inputs
889
+		$non_input_form_sections = array(
890
+			'primary_registrant',
891
+			'additional_attendee_reg_info',
892
+			'spco_copy_attendee_chk',
893
+		);
894
+		// attendee counter
895
+		$att_nmbr = 0;
896
+		// grab the saved registrations from the transaction
897
+		foreach ($registrations as $registration) {
898
+			// verify EE_Registration object
899
+			if (! $registration instanceof EE_Registration) {
900
+				EE_Error::add_error(
901
+					esc_html__(
902
+						'An invalid Registration object was discovered when attempting to process your registration information.',
903
+						'event_espresso'
904
+					),
905
+					__FILE__,
906
+					__FUNCTION__,
907
+					__LINE__
908
+				);
909
+				return false;
910
+			}
911
+			/** @var string $reg_url_link */
912
+			$reg_url_link = $registration->reg_url_link();
913
+			// reg_url_link exists ?
914
+			if (! empty($reg_url_link)) {
915
+				// should this registration be processed during this visit ?
916
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
917
+					// if NOT revisiting, then let's save the registration now,
918
+					// so that we have a REG_ID to use when generating other objects
919
+					if (! $this->checkout->revisit) {
920
+						$registration->save();
921
+					}
922
+					/**
923
+					 * This allows plugins to trigger a fail on processing of a
924
+					 * registration for any conditions they may have for it to pass.
925
+					 *
926
+					 * @var bool   if true is returned by the plugin then the
927
+					 *            registration processing is halted.
928
+					 */
929
+					if (apply_filters(
930
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
931
+						false,
932
+						$att_nmbr,
933
+						$registration,
934
+						$registrations,
935
+						$valid_data,
936
+						$this
937
+					)) {
938
+						return false;
939
+					}
940
+
941
+					// Houston, we have a registration!
942
+					$att_nmbr++;
943
+					$this->_attendee_data[$reg_url_link] = array();
944
+					// grab any existing related answer objects
945
+					$this->_registration_answers = $registration->answers();
946
+					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
947
+					if (isset($valid_data[$reg_url_link])) {
948
+						// do we need to copy basic info from primary attendee ?
949
+						$copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
950
+										&& absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
951
+							? true
952
+							: false;
953
+						// filter form input data for this registration
954
+						$valid_data[$reg_url_link] = (array)apply_filters(
955
+							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
956
+							$valid_data[$reg_url_link]
957
+						);
958
+						if (isset($valid_data['primary_attendee'])) {
959
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
960
+								? $valid_data['primary_attendee']
961
+								: false;
962
+							unset($valid_data['primary_attendee']);
963
+						}
964
+						// now loop through our array of valid post data && process attendee reg forms
965
+						foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
966
+							if (! in_array($form_section, $non_input_form_sections)) {
967
+								foreach ($form_inputs as $form_input => $input_value) {
968
+									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
969
+									// check for critical inputs
970
+									if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
971
+										$form_input,
972
+										$input_value
973
+									)
974
+									) {
975
+										return false;
976
+									}
977
+									// store a bit of data about the primary attendee
978
+									if ($att_nmbr === 1
979
+										&& ! empty($input_value)
980
+										&& $reg_url_link === $primary_registrant['line_item_id']
981
+									) {
982
+										$primary_registrant[$form_input] = $input_value;
983
+									} elseif ($copy_primary
984
+										&& $input_value === null
985
+										&& isset($primary_registrant[$form_input])
986
+									) {
987
+										$input_value = $primary_registrant[$form_input];
988
+									}
989
+									// now attempt to save the input data
990
+									if (! $this->_save_registration_form_input(
991
+										$registration,
992
+										$form_input,
993
+										$input_value
994
+									)
995
+									) {
996
+										EE_Error::add_error(
997
+											sprintf(
998
+												esc_html__(
999
+													'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1000
+													'event_espresso'
1001
+												),
1002
+												$form_input,
1003
+												$input_value
1004
+											),
1005
+											__FILE__,
1006
+											__FUNCTION__,
1007
+											__LINE__
1008
+										);
1009
+										return false;
1010
+									}
1011
+								}
1012
+							}
1013
+						}  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1014
+					}
1015
+					//EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1016
+					// this registration does not require additional attendee information ?
1017
+					if ($copy_primary
1018
+						&& $att_nmbr > 1
1019
+						&& $this->checkout->primary_attendee_obj instanceof EE_Attendee
1020
+					) {
1021
+						// just copy the primary registrant
1022
+						$attendee = $this->checkout->primary_attendee_obj;
1023
+					} else {
1024
+						// ensure critical details are set for additional attendees
1025
+						$this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1026
+							? $this->_copy_critical_attendee_details_from_primary_registrant(
1027
+								$this->_attendee_data[$reg_url_link]
1028
+							)
1029
+							: $this->_attendee_data[$reg_url_link];
1030
+						// execute create attendee command (which may return an existing attendee)
1031
+						$attendee = EE_Registry::instance()->BUS->execute(
1032
+							new CreateAttendeeCommand(
1033
+								$this->_attendee_data[$reg_url_link],
1034
+								$registration
1035
+							)
1036
+						);
1037
+						// who's #1 ?
1038
+						if ($att_nmbr === 1) {
1039
+							$this->checkout->primary_attendee_obj = $attendee;
1040
+						}
1041
+					}
1042
+					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1043
+					// add relation to registration, set attendee ID, and cache attendee
1044
+					$this->_associate_attendee_with_registration($registration, $attendee);
1045
+					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1046
+					if (! $registration->attendee() instanceof EE_Attendee) {
1047
+						EE_Error::add_error(
1048
+							sprintf(
1049
+								esc_html__(
1050
+									'Registration %s has an invalid or missing Attendee object.',
1051
+									'event_espresso'
1052
+								),
1053
+								$reg_url_link
1054
+							),
1055
+							__FILE__,
1056
+							__FUNCTION__,
1057
+							__LINE__
1058
+						);
1059
+						return false;
1060
+					}
1061
+					/** @type EE_Registration_Processor $registration_processor */
1062
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1063
+					// at this point, we should have enough details about the registrant to consider the registration
1064
+					// NOT incomplete
1065
+					$registration_processor->toggle_incomplete_registration_status_to_default(
1066
+						$registration,
1067
+						false,
1068
+						new Context(
1069
+							'spco_reg_step_attendee_information_process_registrations',
1070
+							esc_html__(
1071
+								'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1072
+								'event_espresso'
1073
+							)
1074
+						)
1075
+					);
1076
+					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1077
+					// abandoned
1078
+					$this->checkout->transaction->toggle_failed_transaction_status();
1079
+					// if we've gotten this far, then let's save what we have
1080
+					$registration->save();
1081
+					// add relation between TXN and registration
1082
+					$this->_associate_registration_with_transaction($registration);
1083
+				}
1084
+			} else {
1085
+				EE_Error::add_error(
1086
+					esc_html__(
1087
+						'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1088
+						'event_espresso'
1089
+					),
1090
+					__FILE__,
1091
+					__FUNCTION__,
1092
+					__LINE__
1093
+				);
1094
+				// remove malformed data
1095
+				unset($valid_data[$reg_url_link]);
1096
+				return false;
1097
+			}
1098
+
1099
+		} // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1100
+		return $att_nmbr;
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 *    _save_registration_form_input
1106
+	 *
1107
+	 * @param EE_Registration $registration
1108
+	 * @param string          $form_input
1109
+	 * @param string          $input_value
1110
+	 * @return bool
1111
+	 * @throws EE_Error
1112
+	 * @throws InvalidArgumentException
1113
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1114
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1115
+	 */
1116
+	private function _save_registration_form_input(
1117
+		EE_Registration $registration,
1118
+		$form_input = '',
1119
+		$input_value = ''
1120
+	) {
1121
+		// \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1122
+		// \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1123
+		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1124
+		// allow for plugins to hook in and do their own processing of the form input.
1125
+		// For plugins to bypass normal processing here, they just need to return a boolean value.
1126
+		if (apply_filters(
1127
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1128
+			false,
1129
+			$registration,
1130
+			$form_input,
1131
+			$input_value,
1132
+			$this
1133
+		)) {
1134
+			return true;
1135
+		}
1136
+		/*
1137 1137
          * $answer_cache_id is the key used to find the EE_Answer we want
1138 1138
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1139 1139
          */
1140
-        $answer_cache_id = $this->checkout->reg_url_link
1141
-            ? $form_input . '-' . $registration->reg_url_link()
1142
-            : $form_input;
1143
-        $answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1144
-                           && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1145
-            ? true
1146
-            : false;
1147
-        //rename form_inputs if they are EE_Attendee properties
1148
-        switch ((string) $form_input) {
1149
-            case 'state':
1150
-            case 'STA_ID':
1151
-                $attendee_property = true;
1152
-                $form_input        = 'STA_ID';
1153
-                break;
1154
-
1155
-            case 'country':
1156
-            case 'CNT_ISO':
1157
-                $attendee_property = true;
1158
-                $form_input        = 'CNT_ISO';
1159
-                break;
1160
-
1161
-            default:
1162
-                $ATT_input = 'ATT_' . $form_input;
1163
-                //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1164
-                $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1165
-                $form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1166
-        }
1167
-        // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1168
-        // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1169
-        // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1170
-        // if this form input has a corresponding attendee property
1171
-        if ($attendee_property) {
1172
-            $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1173
-            if ($answer_is_obj) {
1174
-                // and delete the corresponding answer since we won't be storing this data in that object
1175
-                $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1176
-                $this->_registration_answers[$answer_cache_id]->delete_permanently();
1177
-            }
1178
-            return true;
1179
-        } elseif ($answer_is_obj) {
1180
-            // save this data to the answer object
1181
-            $this->_registration_answers[$answer_cache_id]->set_value($input_value);
1182
-            $result = $this->_registration_answers[$answer_cache_id]->save();
1183
-            return $result !== false ? true : false;
1184
-        } else {
1185
-            foreach ($this->_registration_answers as $answer) {
1186
-                if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1187
-                    $answer->set_value($input_value);
1188
-                    $result = $answer->save();
1189
-                    return $result !== false ? true : false;
1190
-                }
1191
-            }
1192
-        }
1193
-        return false;
1194
-    }
1195
-
1196
-
1197
-    /**
1198
-     *    _verify_critical_attendee_details_are_set
1199
-     *
1200
-     * @param string $form_input
1201
-     * @param string $input_value
1202
-     * @return boolean
1203
-     */
1204
-    private function _verify_critical_attendee_details_are_set_and_validate_email(
1205
-        $form_input = '',
1206
-        $input_value = ''
1207
-    ) {
1208
-        if (empty($input_value)) {
1209
-            // if the form input isn't marked as being required, then just return
1210
-            if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1211
-                return true;
1212
-            }
1213
-            switch ($form_input) {
1214
-                case 'fname':
1215
-                    EE_Error::add_error(
1216
-                        esc_html__('First Name is a required value.', 'event_espresso'),
1217
-                        __FILE__,
1218
-                        __FUNCTION__,
1219
-                        __LINE__
1220
-                    );
1221
-                    return false;
1222
-                    break;
1223
-                case 'lname':
1224
-                    EE_Error::add_error(
1225
-                        esc_html__('Last Name is a required value.', 'event_espresso'),
1226
-                        __FILE__,
1227
-                        __FUNCTION__,
1228
-                        __LINE__
1229
-                    );
1230
-                    return false;
1231
-                    break;
1232
-                case 'email':
1233
-                    EE_Error::add_error(
1234
-                        esc_html__('Please enter a valid email address.', 'event_espresso'),
1235
-                        __FILE__,
1236
-                        __FUNCTION__,
1237
-                        __LINE__
1238
-                    );
1239
-                    return false;
1240
-                    break;
1241
-            }
1242
-        }
1243
-        return true;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    _associate_attendee_with_registration
1249
-     *
1250
-     * @param EE_Registration $registration
1251
-     * @param EE_Attendee     $attendee
1252
-     * @return void
1253
-     * @throws EE_Error
1254
-     * @throws RuntimeException
1255
-     */
1256
-    private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1257
-    {
1258
-        // add relation to attendee
1259
-        $registration->_add_relation_to($attendee, 'Attendee');
1260
-        $registration->set_attendee_id($attendee->ID());
1261
-        $registration->update_cache_after_object_save('Attendee', $attendee);
1262
-    }
1263
-
1264
-
1265
-    /**
1266
-     *    _associate_registration_with_transaction
1267
-     *
1268
-     * @param EE_Registration $registration
1269
-     * @return void
1270
-     * @throws \EE_Error
1271
-     */
1272
-    private function _associate_registration_with_transaction(EE_Registration $registration)
1273
-    {
1274
-        // add relation to registration
1275
-        $this->checkout->transaction->_add_relation_to($registration, 'Registration');
1276
-        $this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     *    _copy_critical_attendee_details_from_primary_registrant
1282
-     *    ensures that all attendees at least have data for first name, last name, and email address
1283
-     *
1284
-     * @param array $attendee_data
1285
-     * @return array
1286
-     * @throws \EE_Error
1287
-     */
1288
-    private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1289
-    {
1290
-        // bare minimum critical details include first name, last name, email address
1291
-        $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1292
-        // add address info to critical details?
1293
-        if (apply_filters(
1294
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1295
-            false
1296
-        )) {
1297
-            $address_details           = array(
1298
-                'ATT_address',
1299
-                'ATT_address2',
1300
-                'ATT_city',
1301
-                'STA_ID',
1302
-                'CNT_ISO',
1303
-                'ATT_zip',
1304
-                'ATT_phone',
1305
-            );
1306
-            $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1307
-        }
1308
-        foreach ($critical_attendee_details as $critical_attendee_detail) {
1309
-            if (! isset($attendee_data[$critical_attendee_detail])
1310
-                || empty($attendee_data[$critical_attendee_detail])
1311
-            ) {
1312
-                $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1313
-                    $critical_attendee_detail
1314
-                );
1315
-            }
1316
-        }
1317
-        return $attendee_data;
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     *    update_reg_step
1323
-     *    this is the final step after a user  revisits the site to edit their attendee information
1324
-     *    this gets called AFTER the process_reg_step() method above
1325
-     *
1326
-     * @return bool
1327
-     * @throws EE_Error
1328
-     * @throws InvalidArgumentException
1329
-     * @throws ReflectionException
1330
-     * @throws RuntimeException
1331
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1332
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1333
-     */
1334
-    public function update_reg_step()
1335
-    {
1336
-        // save everything
1337
-        if ($this->process_reg_step()) {
1338
-            $this->checkout->redirect     = true;
1339
-            $this->checkout->redirect_url = add_query_arg(
1340
-                array(
1341
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
1342
-                    'revisit'        => true,
1343
-                ),
1344
-                $this->checkout->thank_you_page_url
1345
-            );
1346
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1347
-            return true;
1348
-        }
1349
-        return false;
1350
-    }
1140
+		$answer_cache_id = $this->checkout->reg_url_link
1141
+			? $form_input . '-' . $registration->reg_url_link()
1142
+			: $form_input;
1143
+		$answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1144
+						   && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1145
+			? true
1146
+			: false;
1147
+		//rename form_inputs if they are EE_Attendee properties
1148
+		switch ((string) $form_input) {
1149
+			case 'state':
1150
+			case 'STA_ID':
1151
+				$attendee_property = true;
1152
+				$form_input        = 'STA_ID';
1153
+				break;
1154
+
1155
+			case 'country':
1156
+			case 'CNT_ISO':
1157
+				$attendee_property = true;
1158
+				$form_input        = 'CNT_ISO';
1159
+				break;
1160
+
1161
+			default:
1162
+				$ATT_input = 'ATT_' . $form_input;
1163
+				//EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1164
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1165
+				$form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1166
+		}
1167
+		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1168
+		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1169
+		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1170
+		// if this form input has a corresponding attendee property
1171
+		if ($attendee_property) {
1172
+			$this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1173
+			if ($answer_is_obj) {
1174
+				// and delete the corresponding answer since we won't be storing this data in that object
1175
+				$registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1176
+				$this->_registration_answers[$answer_cache_id]->delete_permanently();
1177
+			}
1178
+			return true;
1179
+		} elseif ($answer_is_obj) {
1180
+			// save this data to the answer object
1181
+			$this->_registration_answers[$answer_cache_id]->set_value($input_value);
1182
+			$result = $this->_registration_answers[$answer_cache_id]->save();
1183
+			return $result !== false ? true : false;
1184
+		} else {
1185
+			foreach ($this->_registration_answers as $answer) {
1186
+				if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1187
+					$answer->set_value($input_value);
1188
+					$result = $answer->save();
1189
+					return $result !== false ? true : false;
1190
+				}
1191
+			}
1192
+		}
1193
+		return false;
1194
+	}
1195
+
1196
+
1197
+	/**
1198
+	 *    _verify_critical_attendee_details_are_set
1199
+	 *
1200
+	 * @param string $form_input
1201
+	 * @param string $input_value
1202
+	 * @return boolean
1203
+	 */
1204
+	private function _verify_critical_attendee_details_are_set_and_validate_email(
1205
+		$form_input = '',
1206
+		$input_value = ''
1207
+	) {
1208
+		if (empty($input_value)) {
1209
+			// if the form input isn't marked as being required, then just return
1210
+			if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1211
+				return true;
1212
+			}
1213
+			switch ($form_input) {
1214
+				case 'fname':
1215
+					EE_Error::add_error(
1216
+						esc_html__('First Name is a required value.', 'event_espresso'),
1217
+						__FILE__,
1218
+						__FUNCTION__,
1219
+						__LINE__
1220
+					);
1221
+					return false;
1222
+					break;
1223
+				case 'lname':
1224
+					EE_Error::add_error(
1225
+						esc_html__('Last Name is a required value.', 'event_espresso'),
1226
+						__FILE__,
1227
+						__FUNCTION__,
1228
+						__LINE__
1229
+					);
1230
+					return false;
1231
+					break;
1232
+				case 'email':
1233
+					EE_Error::add_error(
1234
+						esc_html__('Please enter a valid email address.', 'event_espresso'),
1235
+						__FILE__,
1236
+						__FUNCTION__,
1237
+						__LINE__
1238
+					);
1239
+					return false;
1240
+					break;
1241
+			}
1242
+		}
1243
+		return true;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    _associate_attendee_with_registration
1249
+	 *
1250
+	 * @param EE_Registration $registration
1251
+	 * @param EE_Attendee     $attendee
1252
+	 * @return void
1253
+	 * @throws EE_Error
1254
+	 * @throws RuntimeException
1255
+	 */
1256
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1257
+	{
1258
+		// add relation to attendee
1259
+		$registration->_add_relation_to($attendee, 'Attendee');
1260
+		$registration->set_attendee_id($attendee->ID());
1261
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1262
+	}
1263
+
1264
+
1265
+	/**
1266
+	 *    _associate_registration_with_transaction
1267
+	 *
1268
+	 * @param EE_Registration $registration
1269
+	 * @return void
1270
+	 * @throws \EE_Error
1271
+	 */
1272
+	private function _associate_registration_with_transaction(EE_Registration $registration)
1273
+	{
1274
+		// add relation to registration
1275
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1276
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 *    _copy_critical_attendee_details_from_primary_registrant
1282
+	 *    ensures that all attendees at least have data for first name, last name, and email address
1283
+	 *
1284
+	 * @param array $attendee_data
1285
+	 * @return array
1286
+	 * @throws \EE_Error
1287
+	 */
1288
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1289
+	{
1290
+		// bare minimum critical details include first name, last name, email address
1291
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1292
+		// add address info to critical details?
1293
+		if (apply_filters(
1294
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1295
+			false
1296
+		)) {
1297
+			$address_details           = array(
1298
+				'ATT_address',
1299
+				'ATT_address2',
1300
+				'ATT_city',
1301
+				'STA_ID',
1302
+				'CNT_ISO',
1303
+				'ATT_zip',
1304
+				'ATT_phone',
1305
+			);
1306
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1307
+		}
1308
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1309
+			if (! isset($attendee_data[$critical_attendee_detail])
1310
+				|| empty($attendee_data[$critical_attendee_detail])
1311
+			) {
1312
+				$attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1313
+					$critical_attendee_detail
1314
+				);
1315
+			}
1316
+		}
1317
+		return $attendee_data;
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 *    update_reg_step
1323
+	 *    this is the final step after a user  revisits the site to edit their attendee information
1324
+	 *    this gets called AFTER the process_reg_step() method above
1325
+	 *
1326
+	 * @return bool
1327
+	 * @throws EE_Error
1328
+	 * @throws InvalidArgumentException
1329
+	 * @throws ReflectionException
1330
+	 * @throws RuntimeException
1331
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1332
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1333
+	 */
1334
+	public function update_reg_step()
1335
+	{
1336
+		// save everything
1337
+		if ($this->process_reg_step()) {
1338
+			$this->checkout->redirect     = true;
1339
+			$this->checkout->redirect_url = add_query_arg(
1340
+				array(
1341
+					'e_reg_url_link' => $this->checkout->reg_url_link,
1342
+					'revisit'        => true,
1343
+				),
1344
+				$this->checkout->thank_you_page_url
1345
+			);
1346
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1347
+			return true;
1348
+		}
1349
+		return false;
1350
+	}
1351 1351
 }
Please login to merge, or discard this patch.