Completed
Branch FET-3959-event-schema (45cb52)
by
unknown
122:31 queued 110:36
created
payment_methods/Paypal_Express/EEG_Paypal_Express.gateway.php 1 patch
Spacing   +112 added lines, -112 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if ( ! defined( 'EVENT_ESPRESSO_VERSION' )) { exit('NO direct script access allowed'); }
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('NO direct script access allowed'); }
2 2
 
3 3
 /**
4 4
  * ----------------------------------------------
@@ -82,10 +82,10 @@  discard block
 block discarded – undo
82 82
 	 *
83 83
 	 *  @param type $settings_array
84 84
 	 */
85
-	public function set_settings( $settings_array ) {
85
+	public function set_settings($settings_array) {
86 86
 		parent::set_settings($settings_array);
87 87
 		// Redirect URL.
88
-		if ( $this->_debug_mode ) {
88
+		if ($this->_debug_mode) {
89 89
 			$this->_base_gateway_url = 'https://api-3t.sandbox.paypal.com/nvp';
90 90
 		} else {
91 91
 			$this->_base_gateway_url = 'https://api-3t.paypal.com/nvp';
@@ -100,19 +100,19 @@  discard block
 block discarded – undo
100 100
 	 *  @param type $return_url
101 101
 	 *  @param type $cancel_url
102 102
 	 */
103
-	public function set_redirection_info( $payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL ) {
104
-		if ( ! $payment instanceof EEI_Payment ) {
105
-			$payment->set_gateway_response( __( 'Error. No associated payment was found.', 'event_espresso' ) );
106
-			$payment->set_status( $this->_pay_model->failed_status() );
103
+	public function set_redirection_info($payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL) {
104
+		if ( ! $payment instanceof EEI_Payment) {
105
+			$payment->set_gateway_response(__('Error. No associated payment was found.', 'event_espresso'));
106
+			$payment->set_status($this->_pay_model->failed_status());
107 107
 			return $payment;
108 108
 		}
109 109
 		$transaction = $payment->transaction();
110
-		if ( ! $transaction instanceof EEI_Transaction ) {
111
-			$payment->set_gateway_response( __( 'Could not process this payment because it has no associated transaction.', 'event_espresso' ) );
112
-			$payment->set_status( $this->_pay_model->failed_status() );
110
+		if ( ! $transaction instanceof EEI_Transaction) {
111
+			$payment->set_gateway_response(__('Could not process this payment because it has no associated transaction.', 'event_espresso'));
112
+			$payment->set_status($this->_pay_model->failed_status());
113 113
 			return $payment;
114 114
 		}
115
-		$order_description = substr( $this->_format_order_description($payment), 0, 127 );
115
+		$order_description = substr($this->_format_order_description($payment), 0, 127);
116 116
 		$primary_registration = $transaction->primary_registration();
117 117
 		$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : false;
118 118
 		$locale = explode('-', get_bloginfo('language'));
@@ -126,37 +126,37 @@  discard block
 block discarded – undo
126 126
 			'RETURNURL' => $return_url,
127 127
 			'CANCELURL' => $cancel_url,
128 128
 			'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
129
-			'SOLUTIONTYPE' => 'Sole',	// Buyer does not need to create a PayPal account to check out. This is referred to as PayPal Account Optional. 
130
-			'BUTTONSOURCE' => 'EventEspresso_SP',//EE will blow up if you change this
129
+			'SOLUTIONTYPE' => 'Sole', // Buyer does not need to create a PayPal account to check out. This is referred to as PayPal Account Optional. 
130
+			'BUTTONSOURCE' => 'EventEspresso_SP', //EE will blow up if you change this
131 131
 			'LOCALECODE' => $locale[1]	// Locale of the pages displayed by PayPal during Express Checkout.
132 132
 		);
133 133
 
134 134
 		// Show itemized list.
135
-		if ( EEH_Money::compare_floats( $payment->amount(), $transaction->total(), '==' ) ) {
135
+		if (EEH_Money::compare_floats($payment->amount(), $transaction->total(), '==')) {
136 136
 			$item_num = 0;
137 137
 			$itemized_sum = 0;
138 138
 			$total_line_items = $transaction->total_line_item();
139 139
 			// Go through each item in the list.
140
-			foreach ( $total_line_items->get_items() as $line_item ) {
141
-				if ( $line_item instanceof EE_Line_Item ) {
140
+			foreach ($total_line_items->get_items() as $line_item) {
141
+				if ($line_item instanceof EE_Line_Item) {
142 142
 					// PayPal doesn't like line items with 0.00 amount, so we may skip those.
143
-					if ( EEH_Money::compare_floats( $line_item->total(), '0.00', '==' ) ) {
143
+					if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
144 144
 						continue;
145 145
 					}
146 146
 
147 147
 					$unit_price = $line_item->unit_price();
148 148
 					$line_item_quantity = $line_item->quantity();
149 149
 					// This is a discount.
150
-					if ( $line_item->is_percent() ) {
150
+					if ($line_item->is_percent()) {
151 151
 						$unit_price = $line_item->total();
152 152
 						$line_item_quantity = 1;
153 153
 					}
154 154
 					// Item Name.
155
-					$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr($this->_format_line_item_name( $line_item, $payment), 0, 127);
155
+					$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr($this->_format_line_item_name($line_item, $payment), 0, 127);
156 156
 					// Item description.
157
-					$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr($this->_format_line_item_desc( $line_item, $payment), 0, 127);
157
+					$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr($this->_format_line_item_desc($line_item, $payment), 0, 127);
158 158
 					// Cost of individual item.
159
-					$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency( $unit_price );
159
+					$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency($unit_price);
160 160
 					// Item Number.
161 161
 					$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
162 162
 					// Item quantity.
@@ -173,16 +173,16 @@  discard block
 block discarded – undo
173 173
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
174 174
 			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
175 175
 
176
-			$itemized_sum_diff_from_txn_total = round( $transaction->total() - $itemized_sum - $total_line_items->get_total_tax(), 2 );
176
+			$itemized_sum_diff_from_txn_total = round($transaction->total() - $itemized_sum - $total_line_items->get_total_tax(), 2);
177 177
 			// If we were not able to recognize some item like promotion, surcharge or cancellation, 
178 178
 			// add the difference as an extra line item.
179
-			if ( $itemized_sum_diff_from_txn_total != 0 ) {
179
+			if ($itemized_sum_diff_from_txn_total != 0) {
180 180
 				// Item Name.
181
-				$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr( __( 'Other (promotion/surcharge/cancellation)', 'event_espresso' ), 0, 127 );
181
+				$token_request_dtls['L_PAYMENTREQUEST_0_NAME'.$item_num] = substr(__('Other (promotion/surcharge/cancellation)', 'event_espresso'), 0, 127);
182 182
 				// Item description.
183
-				$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr( $this->_format_line_item_desc($line_item,$payment), 0, 127 );
183
+				$token_request_dtls['L_PAYMENTREQUEST_0_DESC'.$item_num] = substr($this->_format_line_item_desc($line_item, $payment), 0, 127);
184 184
 				// Cost of individual item.
185
-				$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency( $itemized_sum_diff_from_txn_total );
185
+				$token_request_dtls['L_PAYMENTREQUEST_0_AMT'.$item_num] = $this->format_currency($itemized_sum_diff_from_txn_total);
186 186
 				// Item Number.
187 187
 				$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER'.$item_num] = $item_num + 1;
188 188
 				// Item quantity.
@@ -192,11 +192,11 @@  discard block
 block discarded – undo
192 192
 		} else {
193 193
 			// Just one Item.
194 194
 			// Item Name.
195
-			$token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = substr( $this->_format_partial_payment_line_item_name($payment), 0, 127 );
195
+			$token_request_dtls['L_PAYMENTREQUEST_0_NAME0'] = substr($this->_format_partial_payment_line_item_name($payment), 0, 127);
196 196
 			// Item description.
197
-			$token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = substr( $this->_format_partial_payment_line_item_desc($payment), 0, 127 );
197
+			$token_request_dtls['L_PAYMENTREQUEST_0_DESC0'] = substr($this->_format_partial_payment_line_item_desc($payment), 0, 127);
198 198
 			// Cost of individual item.
199
-			$token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency( $payment->amount() );
199
+			$token_request_dtls['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency($payment->amount());
200 200
 			// Item Number.
201 201
 			$token_request_dtls['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
202 202
 			// Item quantity.
@@ -204,14 +204,14 @@  discard block
 block discarded – undo
204 204
 			// Digital item is sold.
205 205
 			$token_request_dtls['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
206 206
 			// Item's sales S/H and tax amount.
207
-			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency( $payment->amount() );
207
+			$token_request_dtls['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency($payment->amount());
208 208
 			$token_request_dtls['PAYMENTREQUEST_0_TAXAMT'] = '0';
209 209
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
210 210
 			$token_request_dtls['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
211 211
 		}
212 212
 		// Automatically filling out shipping and contact information.
213
-		if ( $this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee ) {
214
-			$token_request_dtls['NOSHIPPING'] = '2';	//  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
213
+		if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
214
+			$token_request_dtls['NOSHIPPING'] = '2'; //  If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
215 215
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
216 216
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
217 217
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
@@ -220,34 +220,34 @@  discard block
 block discarded – undo
220 220
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
221 221
 			$token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
222 222
 			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
223
-		} elseif ( ! $this->_request_shipping_addr ) {
223
+		} elseif ( ! $this->_request_shipping_addr) {
224 224
 			// Do not request shipping details on the PP Checkout page.
225 225
 			$token_request_dtls['NOSHIPPING'] = '1';
226 226
 			$token_request_dtls['REQCONFIRMSHIPPING'] = '0';
227 227
 
228 228
 		}
229 229
 		// Used a business/personal logo on the PayPal page.
230
-		if ( ! empty($this->_image_url) ) {
230
+		if ( ! empty($this->_image_url)) {
231 231
 			$token_request_dtls['LOGOIMG'] = $this->_image_url;
232 232
 		}
233 233
 		// Request PayPal token.
234
-		$token_request_response = $this->_ppExpress_request( $token_request_dtls, 'Payment Token', $payment );
235
-		$token_rstatus = $this->_ppExpress_check_response( $token_request_response );
236
-		$response_args = ( isset($token_rstatus['args']) && is_array($token_rstatus['args']) ) ? $token_rstatus['args'] : array();
237
-		if ( $token_rstatus['status'] ) {
234
+		$token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
235
+		$token_rstatus = $this->_ppExpress_check_response($token_request_response);
236
+		$response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args'])) ? $token_rstatus['args'] : array();
237
+		if ($token_rstatus['status']) {
238 238
 			// We got the Token so we may continue with the payment and redirect the client.
239
-			$payment->set_details( $response_args );
239
+			$payment->set_details($response_args);
240 240
 
241
-			$gateway_url = ( $this->_debug_mode ) ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
242
-			$payment->set_redirect_url( $gateway_url . '/checkoutnow?useraction=commit&cmd=_express-checkout&token=' . $response_args['TOKEN'] );
241
+			$gateway_url = ($this->_debug_mode) ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
242
+			$payment->set_redirect_url($gateway_url.'/checkoutnow?useraction=commit&cmd=_express-checkout&token='.$response_args['TOKEN']);
243 243
 		} else {
244
-			if ( isset($response_args['L_ERRORCODE']) ) {
245
-				$payment->set_gateway_response( $response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE'] );
244
+			if (isset($response_args['L_ERRORCODE'])) {
245
+				$payment->set_gateway_response($response_args['L_ERRORCODE'].'; '.$response_args['L_SHORTMESSAGE']);
246 246
 			} else {
247
-				$payment->set_gateway_response( __( 'Error occurred while trying to setup the Express Checkout.', 'event_espresso' ) );
247
+				$payment->set_gateway_response(__('Error occurred while trying to setup the Express Checkout.', 'event_espresso'));
248 248
 			}
249
-			$payment->set_details( $response_args );
250
-			$payment->set_status( $this->_pay_model->failed_status() );
249
+			$payment->set_details($response_args);
250
+			$payment->set_status($this->_pay_model->failed_status());
251 251
 		}
252 252
 
253 253
 		return $payment;
@@ -263,24 +263,24 @@  discard block
 block discarded – undo
263 263
 	 *  @param type $transaction
264 264
 	 *  @return EEI_Payment
265 265
 	 */
266
-	public function handle_payment_update( $update_info, $transaction ) {
267
-		$payment = ( $transaction instanceof EEI_Transaction ) ? $transaction->last_payment() : null;
266
+	public function handle_payment_update($update_info, $transaction) {
267
+		$payment = ($transaction instanceof EEI_Transaction) ? $transaction->last_payment() : null;
268 268
 
269
-		if ( $payment instanceof EEI_Payment ) {
270
-			$this->log( array( 'Return from Authorization' => $update_info ), $payment );
269
+		if ($payment instanceof EEI_Payment) {
270
+			$this->log(array('Return from Authorization' => $update_info), $payment);
271 271
 
272 272
 			$payment_details = $payment->details();
273 273
 			$transaction = $payment->transaction();
274
-			if ( ! $transaction instanceof EEI_Transaction ) {
275
-				$payment->set_gateway_response( __( 'Could not process this payment because it has no associated transaction.', 'event_espresso' ) );
276
-				$payment->set_status( $this->_pay_model->failed_status() );
274
+			if ( ! $transaction instanceof EEI_Transaction) {
275
+				$payment->set_gateway_response(__('Could not process this payment because it has no associated transaction.', 'event_espresso'));
276
+				$payment->set_status($this->_pay_model->failed_status());
277 277
 				return $payment;
278 278
 			}
279 279
 			$primary_registrant = $transaction->primary_registration();
280 280
 
281 281
 			// Check if we still have the token.
282
-			if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN']) ) {
283
-				$payment->set_status( $this->_pay_model->failed_status() );
282
+			if ( ! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
283
+				$payment->set_status($this->_pay_model->failed_status());
284 284
 				return $payment;
285 285
 			}
286 286
 
@@ -289,10 +289,10 @@  discard block
 block discarded – undo
289 289
 				'TOKEN' => $payment_details['TOKEN']
290 290
 			);
291 291
 			// Request Customer Details.
292
-			$cdetails_request_response = $this->_ppExpress_request( $cdetails_request_dtls, 'Customer Details', $payment );
293
-			$cdetails_rstatus = $this->_ppExpress_check_response( $cdetails_request_response );
294
-			$cdata_response_args = ( isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']) ) ? $cdetails_rstatus['args'] : array();
295
-			if ( $cdetails_rstatus['status'] ) {
292
+			$cdetails_request_response = $this->_ppExpress_request($cdetails_request_dtls, 'Customer Details', $payment);
293
+			$cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
294
+			$cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args'])) ? $cdetails_rstatus['args'] : array();
295
+			if ($cdetails_rstatus['status']) {
296 296
 				// We got the PayerID so now we can Complete the transaction.
297 297
 				$docheckout_request_dtls = array(
298 298
 					'METHOD' => 'DoExpressCheckoutPayment',
@@ -303,39 +303,39 @@  discard block
 block discarded – undo
303 303
 					'PAYMENTREQUEST_0_CURRENCYCODE' => $payment->currency_code()
304 304
 				);
305 305
 				// Payment Checkout/Capture.
306
-				$docheckout_request_response = $this->_ppExpress_request( $docheckout_request_dtls, 'Do Payment', $payment );
307
-				$docheckout_rstatus = $this->_ppExpress_check_response( $docheckout_request_response );
308
-				$docheckout_response_args = ( isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']) ) ? $docheckout_rstatus['args'] : array();
309
-				if ( $docheckout_rstatus['status'] ) {
306
+				$docheckout_request_response = $this->_ppExpress_request($docheckout_request_dtls, 'Do Payment', $payment);
307
+				$docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
308
+				$docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args'])) ? $docheckout_rstatus['args'] : array();
309
+				if ($docheckout_rstatus['status']) {
310 310
 					// All is well, payment approved.
311 311
 					$primary_registration_code = $primary_registrant instanceof EE_Registration ? $primary_registrant->reg_code() : '';
312
-					$payment->set_extra_accntng( $primary_registration_code );
313
-					$payment->set_amount( isset($docheckout_response_args['PAYMENTINFO_0_AMT']) ? floatval( $docheckout_response_args['PAYMENTINFO_0_AMT'] ) : 0 );
314
-					$payment->set_txn_id_chq_nmbr( isset( $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] ) ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] : null );
315
-					$payment->set_details( $cdata_response_args );
316
-					$payment->set_gateway_response( isset( $docheckout_response_args['PAYMENTINFO_0_ACK'] ) ? $docheckout_response_args['PAYMENTINFO_0_ACK'] : '' );
317
-					$payment->set_status( $this->_pay_model->approved_status() );
312
+					$payment->set_extra_accntng($primary_registration_code);
313
+					$payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT']) ? floatval($docheckout_response_args['PAYMENTINFO_0_AMT']) : 0);
314
+					$payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']) ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] : null);
315
+					$payment->set_details($cdata_response_args);
316
+					$payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK']) ? $docheckout_response_args['PAYMENTINFO_0_ACK'] : '');
317
+					$payment->set_status($this->_pay_model->approved_status());
318 318
 				} else {
319
-					if ( isset($docheckout_response_args['L_ERRORCODE']) ) {
320
-						$payment->set_gateway_response( $docheckout_response_args['L_ERRORCODE'] . '; ' . $docheckout_response_args['L_SHORTMESSAGE'] );
319
+					if (isset($docheckout_response_args['L_ERRORCODE'])) {
320
+						$payment->set_gateway_response($docheckout_response_args['L_ERRORCODE'].'; '.$docheckout_response_args['L_SHORTMESSAGE']);
321 321
 					} else {
322
-						$payment->set_gateway_response( __( 'Error occurred while trying to Capture the funds.', 'event_espresso' ) );
322
+						$payment->set_gateway_response(__('Error occurred while trying to Capture the funds.', 'event_espresso'));
323 323
 					}
324
-					$payment->set_details( $docheckout_response_args );
325
-					$payment->set_status( $this->_pay_model->declined_status() );
324
+					$payment->set_details($docheckout_response_args);
325
+					$payment->set_status($this->_pay_model->declined_status());
326 326
 				}
327 327
 			} else {
328
-				if ( isset($cdata_response_args['L_ERRORCODE']) ) {
329
-					$payment->set_gateway_response( $cdata_response_args['L_ERRORCODE'] . '; ' . $cdata_response_args['L_SHORTMESSAGE'] );
328
+				if (isset($cdata_response_args['L_ERRORCODE'])) {
329
+					$payment->set_gateway_response($cdata_response_args['L_ERRORCODE'].'; '.$cdata_response_args['L_SHORTMESSAGE']);
330 330
 				} else {
331
-					$payment->set_gateway_response( __( 'Error occurred while trying to get payment Details from PayPal.', 'event_espresso' ) );
331
+					$payment->set_gateway_response(__('Error occurred while trying to get payment Details from PayPal.', 'event_espresso'));
332 332
 				}
333
-				$payment->set_details( $cdata_response_args );
334
-				$payment->set_status( $this->_pay_model->failed_status() );
333
+				$payment->set_details($cdata_response_args);
334
+				$payment->set_status($this->_pay_model->failed_status());
335 335
 			}
336 336
 		} else {
337
-			$payment->set_gateway_response( __( 'Error occurred while trying to process the payment.', 'event_espresso' ) );
338
-			$payment->set_status( $this->_pay_model->failed_status() );
337
+			$payment->set_gateway_response(__('Error occurred while trying to process the payment.', 'event_espresso'));
338
+			$payment->set_status($this->_pay_model->failed_status());
339 339
 		}
340 340
 
341 341
 		return $payment;
@@ -350,16 +350,16 @@  discard block
 block discarded – undo
350 350
 	 *  @param EEI_Payment  $payment
351 351
 	 *	@return mixed
352 352
 	 */
353
-	public function _ppExpress_request( $request_params, $request_text, $payment ) {
353
+	public function _ppExpress_request($request_params, $request_text, $payment) {
354 354
 		$request_dtls = array(
355 355
 			'VERSION' => '204.0',
356
-			'USER' => urlencode( $this->_api_username ),
357
-			'PWD' => urlencode( $this->_api_password ),
358
-			'SIGNATURE' => urlencode( $this->_api_signature )
356
+			'USER' => urlencode($this->_api_username),
357
+			'PWD' => urlencode($this->_api_password),
358
+			'SIGNATURE' => urlencode($this->_api_signature)
359 359
 		);
360
-		$dtls = array_merge( $request_dtls, $request_params );
360
+		$dtls = array_merge($request_dtls, $request_params);
361 361
 
362
-		$this->_log_clean_request( $dtls, $payment, $request_text . ' Request' );
362
+		$this->_log_clean_request($dtls, $payment, $request_text.' Request');
363 363
 		// Request Customer Details.
364 364
 		$request_response = wp_remote_post(
365 365
 			$this->_base_gateway_url,
@@ -369,11 +369,11 @@  discard block
 block discarded – undo
369 369
 				'httpversion' => '1.1',
370 370
 				'cookies' => array(),
371 371
 				'headers' => array(),
372
-				'body' => http_build_query( $dtls )
372
+				'body' => http_build_query($dtls)
373 373
 			)
374 374
 		);
375 375
 		// Log the response.
376
-		$this->log( array( $request_text . ' Response' => $request_response), $payment );
376
+		$this->log(array($request_text.' Response' => $request_response), $payment);
377 377
 
378 378
 		return $request_response;
379 379
 	}
@@ -385,31 +385,31 @@  discard block
 block discarded – undo
385 385
 	 *	@param mixed        $request_response
386 386
 	 *	@return array
387 387
 	 */
388
-	public function _ppExpress_check_response( $request_response ) {
389
-		if ( ! is_wp_error( $request_response ) && $request_response['body'] && ! empty($request_response['body'] ) ) {
388
+	public function _ppExpress_check_response($request_response) {
389
+		if ( ! is_wp_error($request_response) && $request_response['body'] && ! empty($request_response['body'])) {
390 390
 			$response_args = array();
391
-			parse_str( urldecode($request_response['body']), $response_args );
392
-			if ( isset($response_args['ACK']) 
391
+			parse_str(urldecode($request_response['body']), $response_args);
392
+			if (isset($response_args['ACK']) 
393 393
 				&& $response_args['ACK'] === 'Success' 
394
-				&& ( isset($response_args['PAYERID']) 
394
+				&& (isset($response_args['PAYERID']) 
395 395
 					|| isset($response_args['PAYMENTINFO_0_TRANSACTIONID']) 
396
-					|| ( isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed' ) 
396
+					|| (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed') 
397 397
 					|| isset($response_args['TOKEN']) 
398 398
 				) 
399 399
 			) {
400 400
 				// Response status OK, return response parameters for further processing.
401 401
 				return array('status' => true, 'args' => $response_args);
402 402
 			} else {
403
-				if ( isset($response_args['ACK']) ) {
403
+				if (isset($response_args['ACK'])) {
404 404
 					$errors = $this->_get_errors($response_args);
405
-					return array( 'status' => false, 'args' => $errors );
405
+					return array('status' => false, 'args' => $errors);
406 406
 				} else {
407
-					return array( 'status' => false, 'args' => $request_response );
407
+					return array('status' => false, 'args' => $request_response);
408 408
 				}
409 409
 			}
410 410
 		} else {
411 411
 			// If we got here then there was an error in this request.
412
-			return array( 'status' => false, 'args' => $request_response );
412
+			return array('status' => false, 'args' => $request_response);
413 413
 		}
414 414
 	}
415 415
 
@@ -422,12 +422,12 @@  discard block
 block discarded – undo
422 422
 	 *	@param string  		$info
423 423
 	 *	@return void
424 424
 	 */
425
-	private function _log_clean_request( $request_prms, $payment, $info ) {
425
+	private function _log_clean_request($request_prms, $payment, $info) {
426 426
 		$cleaned_request_data = $request_prms;
427 427
 		unset($cleaned_request_data['PWD']);
428 428
 		unset($cleaned_request_data['USER']);
429 429
 		unset($cleaned_request_data['SIGNATURE']);
430
-		$this->log( array($info => $cleaned_request_data), $payment );
430
+		$this->log(array($info => $cleaned_request_data), $payment);
431 431
 	}
432 432
 
433 433
 
@@ -437,16 +437,16 @@  discard block
 block discarded – undo
437 437
 	 *  @param array	$data_array
438 438
 	 *  @return array
439 439
 	 */
440
-	private function _get_errors( $data_array ) {
440
+	private function _get_errors($data_array) {
441 441
 		$errors = array();
442 442
 		$n = 0;
443
-		while ( isset($data_array['L_ERRORCODE' . $n . '']) ) {
444
-			$l_error_code = isset($data_array['L_ERRORCODE' . $n . '']) ? $data_array['L_ERRORCODE' . $n . ''] : '';
445
-			$l_severity_code = isset($data_array['L_SEVERITYCODE' . $n . '']) ? $data_array['L_SEVERITYCODE' . $n . ''] : '';
446
-			$l_short_message = isset($data_array['L_SHORTMESSAGE' . $n . '']) ? $data_array['L_SHORTMESSAGE' . $n . ''] : '';
447
-			$l_long_message = isset($data_array['L_LONGMESSAGE' . $n . '']) ? $data_array['L_LONGMESSAGE' . $n . ''] : '';
443
+		while (isset($data_array['L_ERRORCODE'.$n.''])) {
444
+			$l_error_code = isset($data_array['L_ERRORCODE'.$n.'']) ? $data_array['L_ERRORCODE'.$n.''] : '';
445
+			$l_severity_code = isset($data_array['L_SEVERITYCODE'.$n.'']) ? $data_array['L_SEVERITYCODE'.$n.''] : '';
446
+			$l_short_message = isset($data_array['L_SHORTMESSAGE'.$n.'']) ? $data_array['L_SHORTMESSAGE'.$n.''] : '';
447
+			$l_long_message = isset($data_array['L_LONGMESSAGE'.$n.'']) ? $data_array['L_LONGMESSAGE'.$n.''] : '';
448 448
 
449
-			if ( $n == 0 ) {
449
+			if ($n == 0) {
450 450
 				$errors = array(
451 451
 					'L_ERRORCODE' => $l_error_code,
452 452
 					'L_SHORTMESSAGE' => $l_short_message,
@@ -454,10 +454,10 @@  discard block
 block discarded – undo
454 454
 					'L_SEVERITYCODE' => $l_severity_code
455 455
 				);
456 456
 			} else {
457
-				$errors['L_ERRORCODE'] .= ', ' . $l_error_code;
458
-				$errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
459
-				$errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
460
-				$errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
457
+				$errors['L_ERRORCODE'] .= ', '.$l_error_code;
458
+				$errors['L_SHORTMESSAGE'] .= ', '.$l_short_message;
459
+				$errors['L_LONGMESSAGE'] .= ', '.$l_long_message;
460
+				$errors['L_SEVERITYCODE'] .= ', '.$l_severity_code;
461 461
 			}
462 462
 
463 463
 			$n++;
Please login to merge, or discard this patch.
core/services/database/TableManager.php 2 patches
Indentation   +207 added lines, -209 removed lines patch added patch discarded remove patch
@@ -17,216 +17,214 @@
 block discarded – undo
17 17
 class TableManager extends \EE_Base
18 18
 {
19 19
 
20
-    /**
21
-     * @var TableAnalysis $table_analysis
22
-     */
23
-    private $table_analysis;
24
-
25
-
26
-
27
-    /**
28
-     * TableManager constructor.
29
-     *
30
-     * @param TableAnalysis $TableAnalysis
31
-     */
32
-    public function __construct(TableAnalysis $TableAnalysis)
33
-    {
34
-        $this->table_analysis = $TableAnalysis;
35
-    }
36
-
37
-
38
-
39
-    /**
40
-     * Gets the injected table analyzer, or throws an exception
41
-     *
42
-     * @return TableAnalysis
43
-     * @throws \EE_Error
44
-     */
45
-    protected function getTableAnalysis()
46
-    {
47
-        if ($this->table_analysis instanceof TableAnalysis) {
48
-            return $this->table_analysis;
49
-        } else {
50
-            throw new \EE_Error(
51
-                sprintf(
52
-                    __('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
-                    get_class($this)
54
-                )
55
-            );
56
-        }
57
-    }
58
-
59
-
60
-
61
-    /**
62
-     * @param string $table_name which can optionally start with $wpdb->prefix or not
63
-     * @param string $column_name
64
-     * @param string $column_info
65
-     * @return bool|false|int
66
-     */
67
-    public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
-    {
69
-        if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
-            return false;
71
-        }
72
-        global $wpdb;
73
-        $full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
-        $columns = $this->getTableColumns($table_name);
75
-        if ( ! in_array($column_name, $columns)) {
76
-            $alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
-            return $wpdb->query($alter_query);
78
-        }
79
-        return true;
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * Gets the name of all columns on the  table. $table_name can
86
-     * optionally start with $wpdb->prefix or not
87
-     *
88
-     * @global \wpdb $wpdb
89
-     * @param string $table_name
90
-     * @return array
91
-     */
92
-    public function getTableColumns($table_name)
93
-    {
94
-        global $wpdb;
95
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
-        $field_array = array();
97
-        if ( ! empty($table_name)) {
98
-            $columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
-            if ($columns !== false) {
100
-                foreach ($columns as $column) {
101
-                    $field_array[] = $column->Field;
102
-                }
103
-            }
104
-        }
105
-        return $field_array;
106
-    }
107
-
108
-
109
-
110
-    /**
111
-     * Drops the specified table from the database. $table_name can
112
-     * optionally start with $wpdb->prefix or not
113
-     *
114
-     * @global \wpdb $wpdb
115
-     * @param string $table_name
116
-     * @return int
117
-     */
118
-    public function dropTable($table_name)
119
-    {
120
-        global $wpdb;
121
-        if ($this->getTableAnalysis()->tableExists($table_name)) {
122
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
-            return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
-        }
125
-        return 0;
126
-    }
127
-
128
-
129
-
130
-    /**
131
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
-     * each table name provided has a wpdb prefix attached, and that it exists.
133
-     * Returns the list actually deleted
134
-     *
135
-     * @global WPDB $wpdb
136
-     * @param array $table_names
137
-     * @return array of table names which we deleted
138
-     */
139
-    public function dropTables($table_names)
140
-    {
141
-        $tables_to_delete = array();
142
-        foreach ($table_names as $table_name) {
143
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
-            if ($this->getTableAnalysis()->tableExists($table_name)) {
145
-                $tables_to_delete[] = $table_name;
146
-            }
147
-        }
148
-        if( ! empty( $tables_to_delete ) ) {
149
-            global $wpdb;
150
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
151
-        }
152
-        return $tables_to_delete;
153
-    }
154
-
155
-
156
-
157
-    /**
158
-     * Drops the specified index from the specified table. $table_name can
159
-     * optionally start with $wpdb->prefix or not
160
-
161
-     *
20
+	/**
21
+	 * @var TableAnalysis $table_analysis
22
+	 */
23
+	private $table_analysis;
24
+
25
+
26
+
27
+	/**
28
+	 * TableManager constructor.
29
+	 *
30
+	 * @param TableAnalysis $TableAnalysis
31
+	 */
32
+	public function __construct(TableAnalysis $TableAnalysis)
33
+	{
34
+		$this->table_analysis = $TableAnalysis;
35
+	}
36
+
37
+
38
+
39
+	/**
40
+	 * Gets the injected table analyzer, or throws an exception
41
+	 *
42
+	 * @return TableAnalysis
43
+	 * @throws \EE_Error
44
+	 */
45
+	protected function getTableAnalysis()
46
+	{
47
+		if ($this->table_analysis instanceof TableAnalysis) {
48
+			return $this->table_analysis;
49
+		} else {
50
+			throw new \EE_Error(
51
+				sprintf(
52
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
53
+					get_class($this)
54
+				)
55
+			);
56
+		}
57
+	}
58
+
59
+
60
+
61
+	/**
62
+	 * @param string $table_name which can optionally start with $wpdb->prefix or not
63
+	 * @param string $column_name
64
+	 * @param string $column_info
65
+	 * @return bool|false|int
66
+	 */
67
+	public function addColumn($table_name, $column_name, $column_info = 'INT UNSIGNED NOT NULL')
68
+	{
69
+		if (apply_filters('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', false)) {
70
+			return false;
71
+		}
72
+		global $wpdb;
73
+		$full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
74
+		$columns = $this->getTableColumns($table_name);
75
+		if ( ! in_array($column_name, $columns)) {
76
+			$alter_query = "ALTER TABLE {$full_table_name} ADD {$column_name} {$column_info}";
77
+			return $wpdb->query($alter_query);
78
+		}
79
+		return true;
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * Gets the name of all columns on the  table. $table_name can
86
+	 * optionally start with $wpdb->prefix or not
87
+	 *
88
+	 * @global \wpdb $wpdb
89
+	 * @param string $table_name
90
+	 * @return array
91
+	 */
92
+	public function getTableColumns($table_name)
93
+	{
94
+		global $wpdb;
95
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
96
+		$field_array = array();
97
+		if ( ! empty($table_name)) {
98
+			$columns = $wpdb->get_results("SHOW COLUMNS FROM {$table_name} ");
99
+			if ($columns !== false) {
100
+				foreach ($columns as $column) {
101
+					$field_array[] = $column->Field;
102
+				}
103
+			}
104
+		}
105
+		return $field_array;
106
+	}
107
+
108
+
109
+
110
+	/**
111
+	 * Drops the specified table from the database. $table_name can
112
+	 * optionally start with $wpdb->prefix or not
113
+	 *
114
+	 * @global \wpdb $wpdb
115
+	 * @param string $table_name
116
+	 * @return int
117
+	 */
118
+	public function dropTable($table_name)
119
+	{
120
+		global $wpdb;
121
+		if ($this->getTableAnalysis()->tableExists($table_name)) {
122
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
123
+			return $wpdb->query("DROP TABLE IF EXISTS {$table_name}");
124
+		}
125
+		return 0;
126
+	}
127
+
128
+
129
+
130
+	/**
131
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
132
+	 * each table name provided has a wpdb prefix attached, and that it exists.
133
+	 * Returns the list actually deleted
134
+	 *
135
+	 * @global WPDB $wpdb
136
+	 * @param array $table_names
137
+	 * @return array of table names which we deleted
138
+	 */
139
+	public function dropTables($table_names)
140
+	{
141
+		$tables_to_delete = array();
142
+		foreach ($table_names as $table_name) {
143
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
144
+			if ($this->getTableAnalysis()->tableExists($table_name)) {
145
+				$tables_to_delete[] = $table_name;
146
+			}
147
+		}
148
+		if( ! empty( $tables_to_delete ) ) {
149
+			global $wpdb;
150
+			$wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
151
+		}
152
+		return $tables_to_delete;
153
+	}
154
+
155
+
156
+
157
+	/**
158
+	 * Drops the specified index from the specified table. $table_name can
159
+	 * optionally start with $wpdb->prefix or not
160
+	 *
162 161
 *@global \wpdb       $wpdb
163
-     * @param string $table_name
164
-     * @param string $index_name
165
-     * @return int
166
-     */
167
-    public function dropIndex($table_name, $index_name)
168
-    {
169
-        if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
170
-            return false;
171
-        }
172
-        global $wpdb;
173
-        $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
174
-        $index_exists_query = "SHOW INDEX FROM {$table_name} WHERE Key_name = '{$index_name}'";
175
-        if (
176
-            $this->getTableAnalysis()->tableExists($table_name)
177
-            && $wpdb->get_var($index_exists_query)
178
-               === $table_name //using get_var with the $index_exists_query returns the table's name
179
-        ) {
180
-            return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
181
-        }
182
-        return 0;
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * Just creates the requested table. $table_name can
189
-     * optionally start with $wpdb->prefix or not
190
-
191
-     *
162
+	 * @param string $table_name
163
+	 * @param string $index_name
164
+	 * @return int
165
+	 */
166
+	public function dropIndex($table_name, $index_name)
167
+	{
168
+		if (apply_filters('FHEE__EEH_Activation__drop_index__short_circuit', false)) {
169
+			return false;
170
+		}
171
+		global $wpdb;
172
+		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
173
+		$index_exists_query = "SHOW INDEX FROM {$table_name} WHERE Key_name = '{$index_name}'";
174
+		if (
175
+			$this->getTableAnalysis()->tableExists($table_name)
176
+			&& $wpdb->get_var($index_exists_query)
177
+			   === $table_name //using get_var with the $index_exists_query returns the table's name
178
+		) {
179
+			return $wpdb->query("ALTER TABLE {$table_name} DROP INDEX {$index_name}");
180
+		}
181
+		return 0;
182
+	}
183
+
184
+
185
+
186
+	/**
187
+	 * Just creates the requested table. $table_name can
188
+	 * optionally start with $wpdb->prefix or not
189
+	 *
192 190
 *@param string       $table_name
193
-     * @param string $create_sql defining the table's columns and indexes
194
-     * @param string $engine     (no need to specify "ENGINE=", that's implied)
195
-     * @return void
196
-     * @throws \EE_Error
197
-     */
198
-    public function createTable($table_name, $create_sql, $engine = 'MyISAM')
199
-    {
200
-        // does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
201
-        if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
202
-            $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
203
-            /** @var \wpdb $wpdb */
204
-            global $wpdb;
205
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
206
-
207
-            //get $wpdb to echo errors, but buffer them. This way at least WE know an error
208
-            //happened. And then we can choose to tell the end user
209
-            $old_show_errors_policy = $wpdb->show_errors(true);
210
-            $old_error_suppression_policy = $wpdb->suppress_errors(false);
211
-            ob_start();
212
-            dbDelta($SQL);
213
-            $output = ob_get_contents();
214
-            ob_end_clean();
215
-            $wpdb->show_errors($old_show_errors_policy);
216
-            $wpdb->suppress_errors($old_error_suppression_policy);
217
-            if ( ! empty($output)) {
218
-                throw new \EE_Error($output);
219
-            }
220
-        } else {
221
-            throw new \EE_Error(
222
-                sprintf(
223
-                    __('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
224
-                        'event_espresso'),
225
-                    '<br />',
226
-                    $create_sql
227
-                )
228
-            );
229
-        }
230
-    }
191
+	 * @param string $create_sql defining the table's columns and indexes
192
+	 * @param string $engine     (no need to specify "ENGINE=", that's implied)
193
+	 * @return void
194
+	 * @throws \EE_Error
195
+	 */
196
+	public function createTable($table_name, $create_sql, $engine = 'MyISAM')
197
+	{
198
+		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
199
+		if (preg_match('((((.*?))(,\s))+)', $create_sql, $valid_column_data)) {
200
+			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
201
+			/** @var \wpdb $wpdb */
202
+			global $wpdb;
203
+			$SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
204
+
205
+			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
206
+			//happened. And then we can choose to tell the end user
207
+			$old_show_errors_policy = $wpdb->show_errors(true);
208
+			$old_error_suppression_policy = $wpdb->suppress_errors(false);
209
+			ob_start();
210
+			dbDelta($SQL);
211
+			$output = ob_get_contents();
212
+			ob_end_clean();
213
+			$wpdb->show_errors($old_show_errors_policy);
214
+			$wpdb->suppress_errors($old_error_suppression_policy);
215
+			if ( ! empty($output)) {
216
+				throw new \EE_Error($output);
217
+			}
218
+		} else {
219
+			throw new \EE_Error(
220
+				sprintf(
221
+					__('The following table creation SQL does not contain valid information about the table columns: %1$s %2$s',
222
+						'event_espresso'),
223
+					'<br />',
224
+					$create_sql
225
+				)
226
+			);
227
+		}
228
+	}
231 229
 
232 230
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -145,9 +145,9 @@  discard block
 block discarded – undo
145 145
                 $tables_to_delete[] = $table_name;
146 146
             }
147 147
         }
148
-        if( ! empty( $tables_to_delete ) ) {
148
+        if ( ! empty($tables_to_delete)) {
149 149
             global $wpdb;
150
-            $wpdb->query('DROP TABLE ' . implode(', ', $tables_to_delete));
150
+            $wpdb->query('DROP TABLE '.implode(', ', $tables_to_delete));
151 151
         }
152 152
         return $tables_to_delete;
153 153
     }
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
             $table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix($table_name);
203 203
             /** @var \wpdb $wpdb */
204 204
             global $wpdb;
205
-            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} " . $wpdb->get_charset_collate();
205
+            $SQL = "CREATE TABLE {$table_name} ( {$create_sql} ) ENGINE={$engine} ".$wpdb->get_charset_collate();
206 206
 
207 207
             //get $wpdb to echo errors, but buffer them. This way at least WE know an error
208 208
             //happened. And then we can choose to tell the end user
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +541 added lines, -541 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /**
5 5
  *    Datetime Model
@@ -11,546 +11,546 @@  discard block
 block discarded – undo
11 11
 class EEM_Datetime extends EEM_Soft_Delete_Base
12 12
 {
13 13
 
14
-    // private instance of the EEM_Datetime object
15
-    protected static $_instance = null;
16
-
17
-
18
-
19
-    /**
20
-     *        private constructor to prevent direct creation
21
-     *
22
-     * @Constructor
23
-     * @access private
24
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
25
-     *                         incoming timezone data that gets saved).  Note this just sends the timezone info to the
26
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
27
-     *                         timezone in the 'timezone_string' wp option)
28
-     */
29
-    protected function __construct($timezone)
30
-    {
31
-        $this->singular_item = __('Datetime', 'event_espresso');
32
-        $this->plural_item = __('Datetimes', 'event_espresso');
33
-        $this->_tables = array(
34
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
35
-        );
36
-        $this->_fields = array(
37
-            'Datetime' => array(
38
-                'DTT_ID'          => new EE_Primary_Key_Int_Field('DTT_ID', __('Datetime ID', 'event_espresso')),
39
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field('EVT_ID', __('Event ID', 'event_espresso'), false, 0,
40
-                    'Event'),
41
-                'DTT_name'        => new EE_Plain_Text_Field('DTT_name', __('Datetime Name', 'event_espresso'), false,
42
-                    ''),
43
-                'DTT_description' => new EE_Post_Content_Field('DTT_description',
44
-                    __('Description for Datetime', 'event_espresso'), false, ''),
45
-                'DTT_EVT_start'   => new EE_Datetime_Field('DTT_EVT_start',
46
-                    __('Start time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
47
-                'DTT_EVT_end'     => new EE_Datetime_Field('DTT_EVT_end',
48
-                    __('End time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
49
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field('DTT_reg_limit',
50
-                    __('Registration Limit for this time', 'event_espresso'), true, EE_INF),
51
-                'DTT_sold'        => new EE_Integer_Field('DTT_sold',
52
-                    __('How many sales for this Datetime that have occurred', 'event_espresso'), true, 0),
53
-                'DTT_reserved'    => new EE_Integer_Field('DTT_reserved',
54
-                    __('Quantity of tickets that are reserved, but not yet fully purchased', 'event_espresso'), false,
55
-                    0),
56
-                'DTT_is_primary'  => new EE_Boolean_Field('DTT_is_primary',
57
-                    __("Flag indicating datetime is primary one for event", "event_espresso"), false, false),
58
-                'DTT_order'       => new EE_Integer_Field('DTT_order',
59
-                    __('The order in which the Datetime is displayed', 'event_espresso'), false, 0),
60
-                'DTT_parent'      => new EE_Integer_Field('DTT_parent',
61
-                    __('Indicates what DTT_ID is the parent of this DTT_ID'), true, 0),
62
-                'DTT_deleted'     => new EE_Trashed_Flag_Field('DTT_deleted',
63
-                    __('Flag indicating datetime is archived', 'event_espresso'), false, false),
64
-            ),
65
-        );
66
-        $this->_model_relations = array(
67
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
68
-            'Event'   => new EE_Belongs_To_Relation(),
69
-            'Checkin' => new EE_Has_Many_Relation(),
70
-        );
71
-        $this->_model_chain_to_wp_user = 'Event';
72
-        //this model is generally available for reading
73
-        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public('Event');
74
-        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected('Event');
75
-        $this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected('Event');
76
-        $this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected('Event',
77
-            EEM_Base::caps_edit);
78
-        parent::__construct($timezone);
79
-    }
80
-
81
-
82
-
83
-    /**
84
-     *        create new blank datetime
85
-     *
86
-     * @access        public
87
-     * @return        EE_Datetime[]        array on success, FALSE on fail
88
-     */
89
-    public function create_new_blank_datetime()
90
-    {
91
-        //makes sure timezone is always set.
92
-        $timezone_string = $this->get_timezone();
93
-        $blank_datetime = EE_Datetime::new_instance(
94
-            array(
95
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + (60 * 60 * 24 * 30),
96
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + (60 * 60 * 24 * 30),
97
-                'DTT_order'     => 1,
98
-                'DTT_reg_limit' => EE_INF,
99
-            ),
100
-            $timezone_string
101
-        );
102
-        $blank_datetime->set_start_time($this->convert_datetime_for_query('DTT_EVT_start', '8am', 'ga',
103
-            $timezone_string));
104
-        $blank_datetime->set_end_time($this->convert_datetime_for_query('DTT_EVT_end', '5pm', 'ga', $timezone_string));
105
-        return array($blank_datetime);
106
-    }
107
-
108
-
109
-
110
-    /**
111
-     *        get event start date from db
112
-     *
113
-     * @access        public
114
-     * @param        int $EVT_ID
115
-     * @return        EE_Datetime[]        array on success, FALSE on fail
116
-     */
117
-    public function get_all_event_dates($EVT_ID = 0)
118
-    {
119
-        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
120
-            return $this->create_new_blank_datetime();
121
-        }
122
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
123
-        if (empty($results)) {
124
-            return $this->create_new_blank_datetime();
125
-        }
126
-        return $results;
127
-    }
128
-
129
-
130
-
131
-    /**
132
-     * get all datetimes attached to an event ordered by the DTT_order field
133
-     *
134
-     * @public
135
-     * @param  int    $EVT_ID     event id
136
-     * @param boolean $include_expired
137
-     * @param boolean $include_deleted
138
-     * @param  int    $limit      If included then limit the count of results by
139
-     *                            the given number
140
-     * @return EE_Datetime[]
141
-     */
142
-    public function get_datetimes_for_event_ordered_by_DTT_order(
143
-        $EVT_ID,
144
-        $include_expired = true,
145
-        $include_deleted = true,
146
-        $limit = null
147
-    ) {
148
-        //sanitize EVT_ID
149
-        $EVT_ID = intval($EVT_ID);
150
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
151
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
152
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
153
-        $query_params = ! empty($limit) ? array(
154
-            $where_params,
155
-            'limit'                    => $limit,
156
-            'order_by'                 => array('DTT_order' => 'ASC'),
157
-            'default_where_conditions' => 'none',
158
-        ) : array($where_params, 'order_by' => array('DTT_order' => 'ASC'), 'default_where_conditions' => 'none');
159
-        if ( ! $include_expired) {
160
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
161
-        }
162
-        if ($include_deleted) {
163
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
164
-        }
165
-        $result = $this->get_all($query_params);
166
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
167
-        return $result;
168
-    }
169
-
170
-
171
-
172
-    /**
173
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance". By importance, we mean
174
-     * that the primary datetimes are most important (DEPRECATED FOR NOW), and then the earlier datetimes are the most
175
-     * important. Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
176
-     *
177
-     * @param int $EVT_ID
178
-     * @param int $limit
179
-     * @return EE_Datetime[]
180
-     */
181
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
182
-    {
183
-        return $this->get_all(array(
184
-            array('Event.EVT_ID' => $EVT_ID),
185
-            'limit'                    => $limit,
186
-            'order_by'                 => array('DTT_EVT_start' => 'ASC'),
187
-            'default_where_conditions' => 'none',
188
-        ));
189
-    }
190
-
191
-
192
-
193
-    /**
194
-     * @param int     $EVT_ID
195
-     * @param boolean $include_expired
196
-     * @param boolean $include_deleted
197
-     * @return EE_Datetime
198
-     */
199
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
200
-    {
201
-        $results = $this->get_datetimes_for_event_ordered_by_start_time($EVT_ID, $include_expired, $include_deleted, 1);
202
-        if ($results) {
203
-            return array_shift($results);
204
-        } else {
205
-            return null;
206
-        }
207
-    }
208
-
209
-
210
-
211
-    /**
212
-     * Gets the 'primary' datetime for an event.
213
-     *
214
-     * @param int  $EVT_ID
215
-     * @param bool $try_to_exclude_expired
216
-     * @param bool $try_to_exclude_deleted
217
-     * @return \EE_Datetime
218
-     */
219
-    public function get_primary_datetime_for_event(
220
-        $EVT_ID,
221
-        $try_to_exclude_expired = true,
222
-        $try_to_exclude_deleted = true
223
-    ) {
224
-        if ($try_to_exclude_expired) {
225
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
226
-            if ($non_expired) {
227
-                return $non_expired;
228
-            }
229
-        }
230
-        if ($try_to_exclude_deleted) {
231
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
232
-            if ($expired_even) {
233
-                return $expired_even;
234
-            }
235
-        }
236
-        $deleted_even = $this->get_oldest_datetime_for_event($EVT_ID, true, true);
237
-        return $deleted_even;
238
-    }
239
-
240
-
241
-
242
-    /**
243
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
244
-     * only by start date
245
-     *
246
-     * @param int     $EVT_ID
247
-     * @param boolean $include_expired
248
-     * @param boolean $include_deleted
249
-     * @param int     $limit
250
-     * @return EE_Datetime[]
251
-     */
252
-    public function get_datetimes_for_event_ordered_by_start_time(
253
-        $EVT_ID,
254
-        $include_expired = true,
255
-        $include_deleted = true,
256
-        $limit = null
257
-    ) {
258
-        //sanitize EVT_ID
259
-        $EVT_ID = intval($EVT_ID);
260
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
261
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
262
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
263
-        if ( ! $include_expired) {
264
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
265
-        }
266
-        if ($include_deleted) {
267
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
268
-        }
269
-        if ($limit) {
270
-            $query_params['limit'] = $limit;
271
-        }
272
-        $result = $this->get_all($query_params);
273
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
274
-        return $result;
275
-    }
276
-
277
-
278
-
279
-    /**
280
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
281
-     * only by start date
282
-     *
283
-     * @param int     $TKT_ID
284
-     * @param boolean $include_expired
285
-     * @param boolean $include_deleted
286
-     * @param int     $limit
287
-     * @return EE_Datetime[]
288
-     */
289
-    public function get_datetimes_for_ticket_ordered_by_start_time(
290
-        $TKT_ID,
291
-        $include_expired = true,
292
-        $include_deleted = true,
293
-        $limit = null
294
-    ) {
295
-        //sanitize TKT_ID
296
-        $TKT_ID = intval($TKT_ID);
297
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
298
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
299
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
300
-        if ( ! $include_expired) {
301
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
302
-        }
303
-        if ($include_deleted) {
304
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
305
-        }
306
-        if ($limit) {
307
-            $query_params['limit'] = $limit;
308
-        }
309
-        $result = $this->get_all($query_params);
310
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
311
-        return $result;
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
318
-     * datetimes.
319
-     *
320
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
321
-     * @param  boolean  $include_expired whether to include expired datetimes or not
322
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
323
-     * @param  int|null $limit           if null, no limit, if int then limit results by
324
-     *                                   that number
325
-     * @return EE_Datetime[]
326
-     */
327
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
328
-        $TKT_ID,
329
-        $include_expired = true,
330
-        $include_deleted = true,
331
-        $limit = null
332
-    ) {
333
-        //sanitize id.
334
-        $TKT_ID = intval($TKT_ID);
335
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
336
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
337
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
338
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
339
-        if ( ! $include_expired) {
340
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
341
-        }
342
-        if ($include_deleted) {
343
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
344
-        }
345
-        if ($limit) {
346
-            $query_params['limit'] = $limit;
347
-        }
348
-        $result = $this->get_all($query_params);
349
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
350
-        return $result;
351
-    }
352
-
353
-
354
-
355
-    /**
356
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
357
-     * reason it doesn't exist, we consider the earliest event the most important)
358
-     *
359
-     * @param int $EVT_ID
360
-     * @return EE_Datetime
361
-     */
362
-    public function get_most_important_datetime_for_event($EVT_ID)
363
-    {
364
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
365
-        if ($results) {
366
-            return array_shift($results);
367
-        } else {
368
-            return null;
369
-        }
370
-    }
371
-
372
-
373
-
374
-    /**
375
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
376
-     * grouped by month and year.
377
-     *
378
-     * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
379
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
380
-     *                                   Can be:
381
-     *                                   - '' = no filter
382
-     *                                   - upcoming = Published events with at least one upcoming datetime.
383
-     *                                   - expired = Events with all datetimes expired.
384
-     *                                   - active = Events that are published and have at least one datetime that
385
-     *                                   starts before now and ends after now.
386
-     *                                   - inactive = Events that are either not published.
387
-     * @return wpdb results array
388
-     */
389
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
390
-    {
391
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
392
-        $current_time_for_DTT_EVT_end = $this->current_time_for_query('DTT_EVT_end');
393
-        switch ($evt_active_status) {
394
-            case 'upcoming' :
395
-                $where_params['Event.status'] = 'publish';
396
-                //if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
397
-                if (isset($where_params['DTT_EVT_start'])) {
398
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
399
-                }
400
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
401
-                break;
402
-            case 'expired' :
403
-                if (isset($where_params['Event.status'])) {
404
-                    unset($where_params['Event.status']);
405
-                }
406
-                //get events to exclude
407
-                $exclude_query[0] = array_merge($where_params,
408
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
409
-                //first get all events that have datetimes where its not expired.
410
-                $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Datetime.EVT_ID');
411
-                $event_ids = array_keys($event_ids);
412
-                if (isset($where_params['DTT_EVT_end'])) {
413
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
414
-                }
415
-                $where_params['DTT_EVT_end'] = array('<', $current_time_for_DTT_EVT_end);
416
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
417
-                break;
418
-            case 'active' :
419
-                $where_params['Event.status'] = 'publish';
420
-                if (isset($where_params['DTT_EVT_start'])) {
421
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
422
-                }
423
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
424
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
425
-                }
426
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
427
-                $where_params['DTT_EVT_end'] = array('>', $current_time_for_DTT_EVT_end);
428
-                break;
429
-            case 'inactive' :
430
-                if (isset($where_params['Event.status'])) {
431
-                    unset($where_params['Event.status']);
432
-                }
433
-                if (isset($where_params['OR'])) {
434
-                    $where_params['AND']['OR'] = $where_params['OR'];
435
-                }
436
-                if (isset($where_params['DTT_EVT_end'])) {
437
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
438
-                    unset($where_params['DTT_EVT_end']);
439
-                }
440
-                if (isset($where_params['DTT_EVT_start'])) {
441
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
442
-                    unset($where_params['DTT_EVT_start']);
443
-                }
444
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
445
-                break;
446
-        }
447
-        $query_params[0] = $where_params;
448
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
449
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
450
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'DTT_EVT_start');
451
-        $columns_to_select = array(
452
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
453
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
454
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
455
-        );
456
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
457
-    }
458
-
459
-
460
-
461
-    /**
462
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
463
-     * for the tickets for each datetime)
464
-     *
465
-     * @param EE_Datetime[] $datetimes
466
-     */
467
-    public function update_sold($datetimes)
468
-    {
469
-        foreach ($datetimes as $datetime) {
470
-            $datetime->update_sold();
471
-        }
472
-    }
473
-
474
-
475
-
476
-    /**
477
-     *    Gets the total number of tickets available at a particular datetime
478
-     *    (does NOT take into account the datetime's spaces available)
479
-     *
480
-     * @param int   $DTT_ID
481
-     * @param array $query_params
482
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
483
-     *             tickets attached to datetime then FALSE is returned.
484
-     */
485
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, $query_params = array())
486
-    {
487
-        $datetime = $this->get_one_by_ID($DTT_ID);
488
-        if ($datetime instanceof EE_Datetime) {
489
-            return $datetime->tickets_remaining($query_params);
490
-        }
491
-        return 0;
492
-    }
493
-
494
-
495
-
496
-    /**
497
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
498
-     *
499
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
500
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
501
-     *                                 for all valid stati.
502
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
503
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
504
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
505
-     *                stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming EE_Datetime::expired
506
-     */
507
-    public function get_datetime_counts_by_status($stati_to_include = array(), $query_params = array())
508
-    {
509
-        //only accept where conditions for this query.
510
-        $_where = isset($query_params[0]) ? $query_params[0] : array();
511
-        $status_query_args = array(
512
-            EE_Datetime::active   => array_merge(
513
-                $_where,
514
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
515
-            ),
516
-            EE_Datetime::upcoming => array_merge(
517
-                $_where,
518
-                array('DTT_EVT_start' => array('>', time()))
519
-            ),
520
-            EE_Datetime::expired  => array_merge(
521
-                $_where,
522
-                array('DTT_EVT_end' => array('<', time()))
523
-            ),
524
-        );
525
-        if ( ! empty($stati_to_include)) {
526
-            foreach (array_keys($status_query_args) as $status) {
527
-                if ( ! in_array($status, $stati_to_include)) {
528
-                    unset($status_query_args[$status]);
529
-                }
530
-            }
531
-        }
532
-        //loop through and query counts for each stati.
533
-        $status_query_results = array();
534
-        foreach ($status_query_args as $status => $status_where_conditions) {
535
-            $status_query_results[$status] = EEM_Datetime::count(array($status_where_conditions), 'DTT_ID', true);
536
-        }
537
-        return $status_query_results;
538
-    }
539
-
540
-
541
-
542
-    /**
543
-     * Returns the specific count for a given Datetime status matching any given query_params.
544
-     *
545
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
546
-     * @param array  $query_params
547
-     * @return int
548
-     */
549
-    public function get_datetime_count_for_status($status = EE_Datetime::active, $query_params = array())
550
-    {
551
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
552
-        return ! empty($count[$status]) ? $count[$status] : 0;
553
-    }
14
+	// private instance of the EEM_Datetime object
15
+	protected static $_instance = null;
16
+
17
+
18
+
19
+	/**
20
+	 *        private constructor to prevent direct creation
21
+	 *
22
+	 * @Constructor
23
+	 * @access private
24
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
25
+	 *                         incoming timezone data that gets saved).  Note this just sends the timezone info to the
26
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
27
+	 *                         timezone in the 'timezone_string' wp option)
28
+	 */
29
+	protected function __construct($timezone)
30
+	{
31
+		$this->singular_item = __('Datetime', 'event_espresso');
32
+		$this->plural_item = __('Datetimes', 'event_espresso');
33
+		$this->_tables = array(
34
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
35
+		);
36
+		$this->_fields = array(
37
+			'Datetime' => array(
38
+				'DTT_ID'          => new EE_Primary_Key_Int_Field('DTT_ID', __('Datetime ID', 'event_espresso')),
39
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field('EVT_ID', __('Event ID', 'event_espresso'), false, 0,
40
+					'Event'),
41
+				'DTT_name'        => new EE_Plain_Text_Field('DTT_name', __('Datetime Name', 'event_espresso'), false,
42
+					''),
43
+				'DTT_description' => new EE_Post_Content_Field('DTT_description',
44
+					__('Description for Datetime', 'event_espresso'), false, ''),
45
+				'DTT_EVT_start'   => new EE_Datetime_Field('DTT_EVT_start',
46
+					__('Start time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
47
+				'DTT_EVT_end'     => new EE_Datetime_Field('DTT_EVT_end',
48
+					__('End time/date of Event', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
49
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field('DTT_reg_limit',
50
+					__('Registration Limit for this time', 'event_espresso'), true, EE_INF),
51
+				'DTT_sold'        => new EE_Integer_Field('DTT_sold',
52
+					__('How many sales for this Datetime that have occurred', 'event_espresso'), true, 0),
53
+				'DTT_reserved'    => new EE_Integer_Field('DTT_reserved',
54
+					__('Quantity of tickets that are reserved, but not yet fully purchased', 'event_espresso'), false,
55
+					0),
56
+				'DTT_is_primary'  => new EE_Boolean_Field('DTT_is_primary',
57
+					__("Flag indicating datetime is primary one for event", "event_espresso"), false, false),
58
+				'DTT_order'       => new EE_Integer_Field('DTT_order',
59
+					__('The order in which the Datetime is displayed', 'event_espresso'), false, 0),
60
+				'DTT_parent'      => new EE_Integer_Field('DTT_parent',
61
+					__('Indicates what DTT_ID is the parent of this DTT_ID'), true, 0),
62
+				'DTT_deleted'     => new EE_Trashed_Flag_Field('DTT_deleted',
63
+					__('Flag indicating datetime is archived', 'event_espresso'), false, false),
64
+			),
65
+		);
66
+		$this->_model_relations = array(
67
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
68
+			'Event'   => new EE_Belongs_To_Relation(),
69
+			'Checkin' => new EE_Has_Many_Relation(),
70
+		);
71
+		$this->_model_chain_to_wp_user = 'Event';
72
+		//this model is generally available for reading
73
+		$this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public('Event');
74
+		$this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected('Event');
75
+		$this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected('Event');
76
+		$this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected('Event',
77
+			EEM_Base::caps_edit);
78
+		parent::__construct($timezone);
79
+	}
80
+
81
+
82
+
83
+	/**
84
+	 *        create new blank datetime
85
+	 *
86
+	 * @access        public
87
+	 * @return        EE_Datetime[]        array on success, FALSE on fail
88
+	 */
89
+	public function create_new_blank_datetime()
90
+	{
91
+		//makes sure timezone is always set.
92
+		$timezone_string = $this->get_timezone();
93
+		$blank_datetime = EE_Datetime::new_instance(
94
+			array(
95
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + (60 * 60 * 24 * 30),
96
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + (60 * 60 * 24 * 30),
97
+				'DTT_order'     => 1,
98
+				'DTT_reg_limit' => EE_INF,
99
+			),
100
+			$timezone_string
101
+		);
102
+		$blank_datetime->set_start_time($this->convert_datetime_for_query('DTT_EVT_start', '8am', 'ga',
103
+			$timezone_string));
104
+		$blank_datetime->set_end_time($this->convert_datetime_for_query('DTT_EVT_end', '5pm', 'ga', $timezone_string));
105
+		return array($blank_datetime);
106
+	}
107
+
108
+
109
+
110
+	/**
111
+	 *        get event start date from db
112
+	 *
113
+	 * @access        public
114
+	 * @param        int $EVT_ID
115
+	 * @return        EE_Datetime[]        array on success, FALSE on fail
116
+	 */
117
+	public function get_all_event_dates($EVT_ID = 0)
118
+	{
119
+		if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
120
+			return $this->create_new_blank_datetime();
121
+		}
122
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
123
+		if (empty($results)) {
124
+			return $this->create_new_blank_datetime();
125
+		}
126
+		return $results;
127
+	}
128
+
129
+
130
+
131
+	/**
132
+	 * get all datetimes attached to an event ordered by the DTT_order field
133
+	 *
134
+	 * @public
135
+	 * @param  int    $EVT_ID     event id
136
+	 * @param boolean $include_expired
137
+	 * @param boolean $include_deleted
138
+	 * @param  int    $limit      If included then limit the count of results by
139
+	 *                            the given number
140
+	 * @return EE_Datetime[]
141
+	 */
142
+	public function get_datetimes_for_event_ordered_by_DTT_order(
143
+		$EVT_ID,
144
+		$include_expired = true,
145
+		$include_deleted = true,
146
+		$limit = null
147
+	) {
148
+		//sanitize EVT_ID
149
+		$EVT_ID = intval($EVT_ID);
150
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
151
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
152
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
153
+		$query_params = ! empty($limit) ? array(
154
+			$where_params,
155
+			'limit'                    => $limit,
156
+			'order_by'                 => array('DTT_order' => 'ASC'),
157
+			'default_where_conditions' => 'none',
158
+		) : array($where_params, 'order_by' => array('DTT_order' => 'ASC'), 'default_where_conditions' => 'none');
159
+		if ( ! $include_expired) {
160
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
161
+		}
162
+		if ($include_deleted) {
163
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
164
+		}
165
+		$result = $this->get_all($query_params);
166
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
167
+		return $result;
168
+	}
169
+
170
+
171
+
172
+	/**
173
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance". By importance, we mean
174
+	 * that the primary datetimes are most important (DEPRECATED FOR NOW), and then the earlier datetimes are the most
175
+	 * important. Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
176
+	 *
177
+	 * @param int $EVT_ID
178
+	 * @param int $limit
179
+	 * @return EE_Datetime[]
180
+	 */
181
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
182
+	{
183
+		return $this->get_all(array(
184
+			array('Event.EVT_ID' => $EVT_ID),
185
+			'limit'                    => $limit,
186
+			'order_by'                 => array('DTT_EVT_start' => 'ASC'),
187
+			'default_where_conditions' => 'none',
188
+		));
189
+	}
190
+
191
+
192
+
193
+	/**
194
+	 * @param int     $EVT_ID
195
+	 * @param boolean $include_expired
196
+	 * @param boolean $include_deleted
197
+	 * @return EE_Datetime
198
+	 */
199
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
200
+	{
201
+		$results = $this->get_datetimes_for_event_ordered_by_start_time($EVT_ID, $include_expired, $include_deleted, 1);
202
+		if ($results) {
203
+			return array_shift($results);
204
+		} else {
205
+			return null;
206
+		}
207
+	}
208
+
209
+
210
+
211
+	/**
212
+	 * Gets the 'primary' datetime for an event.
213
+	 *
214
+	 * @param int  $EVT_ID
215
+	 * @param bool $try_to_exclude_expired
216
+	 * @param bool $try_to_exclude_deleted
217
+	 * @return \EE_Datetime
218
+	 */
219
+	public function get_primary_datetime_for_event(
220
+		$EVT_ID,
221
+		$try_to_exclude_expired = true,
222
+		$try_to_exclude_deleted = true
223
+	) {
224
+		if ($try_to_exclude_expired) {
225
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
226
+			if ($non_expired) {
227
+				return $non_expired;
228
+			}
229
+		}
230
+		if ($try_to_exclude_deleted) {
231
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
232
+			if ($expired_even) {
233
+				return $expired_even;
234
+			}
235
+		}
236
+		$deleted_even = $this->get_oldest_datetime_for_event($EVT_ID, true, true);
237
+		return $deleted_even;
238
+	}
239
+
240
+
241
+
242
+	/**
243
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
244
+	 * only by start date
245
+	 *
246
+	 * @param int     $EVT_ID
247
+	 * @param boolean $include_expired
248
+	 * @param boolean $include_deleted
249
+	 * @param int     $limit
250
+	 * @return EE_Datetime[]
251
+	 */
252
+	public function get_datetimes_for_event_ordered_by_start_time(
253
+		$EVT_ID,
254
+		$include_expired = true,
255
+		$include_deleted = true,
256
+		$limit = null
257
+	) {
258
+		//sanitize EVT_ID
259
+		$EVT_ID = intval($EVT_ID);
260
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
261
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
262
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
263
+		if ( ! $include_expired) {
264
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
265
+		}
266
+		if ($include_deleted) {
267
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
268
+		}
269
+		if ($limit) {
270
+			$query_params['limit'] = $limit;
271
+		}
272
+		$result = $this->get_all($query_params);
273
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
274
+		return $result;
275
+	}
276
+
277
+
278
+
279
+	/**
280
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
281
+	 * only by start date
282
+	 *
283
+	 * @param int     $TKT_ID
284
+	 * @param boolean $include_expired
285
+	 * @param boolean $include_deleted
286
+	 * @param int     $limit
287
+	 * @return EE_Datetime[]
288
+	 */
289
+	public function get_datetimes_for_ticket_ordered_by_start_time(
290
+		$TKT_ID,
291
+		$include_expired = true,
292
+		$include_deleted = true,
293
+		$limit = null
294
+	) {
295
+		//sanitize TKT_ID
296
+		$TKT_ID = intval($TKT_ID);
297
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
298
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
299
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
300
+		if ( ! $include_expired) {
301
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
302
+		}
303
+		if ($include_deleted) {
304
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
305
+		}
306
+		if ($limit) {
307
+			$query_params['limit'] = $limit;
308
+		}
309
+		$result = $this->get_all($query_params);
310
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
311
+		return $result;
312
+	}
313
+
314
+
315
+
316
+	/**
317
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
318
+	 * datetimes.
319
+	 *
320
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
321
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
322
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
323
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
324
+	 *                                   that number
325
+	 * @return EE_Datetime[]
326
+	 */
327
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
328
+		$TKT_ID,
329
+		$include_expired = true,
330
+		$include_deleted = true,
331
+		$limit = null
332
+	) {
333
+		//sanitize id.
334
+		$TKT_ID = intval($TKT_ID);
335
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
336
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
337
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
338
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
339
+		if ( ! $include_expired) {
340
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
341
+		}
342
+		if ($include_deleted) {
343
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
344
+		}
345
+		if ($limit) {
346
+			$query_params['limit'] = $limit;
347
+		}
348
+		$result = $this->get_all($query_params);
349
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
350
+		return $result;
351
+	}
352
+
353
+
354
+
355
+	/**
356
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
357
+	 * reason it doesn't exist, we consider the earliest event the most important)
358
+	 *
359
+	 * @param int $EVT_ID
360
+	 * @return EE_Datetime
361
+	 */
362
+	public function get_most_important_datetime_for_event($EVT_ID)
363
+	{
364
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
365
+		if ($results) {
366
+			return array_shift($results);
367
+		} else {
368
+			return null;
369
+		}
370
+	}
371
+
372
+
373
+
374
+	/**
375
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
376
+	 * grouped by month and year.
377
+	 *
378
+	 * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
379
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
380
+	 *                                   Can be:
381
+	 *                                   - '' = no filter
382
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
383
+	 *                                   - expired = Events with all datetimes expired.
384
+	 *                                   - active = Events that are published and have at least one datetime that
385
+	 *                                   starts before now and ends after now.
386
+	 *                                   - inactive = Events that are either not published.
387
+	 * @return wpdb results array
388
+	 */
389
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
390
+	{
391
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
392
+		$current_time_for_DTT_EVT_end = $this->current_time_for_query('DTT_EVT_end');
393
+		switch ($evt_active_status) {
394
+			case 'upcoming' :
395
+				$where_params['Event.status'] = 'publish';
396
+				//if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
397
+				if (isset($where_params['DTT_EVT_start'])) {
398
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
399
+				}
400
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
401
+				break;
402
+			case 'expired' :
403
+				if (isset($where_params['Event.status'])) {
404
+					unset($where_params['Event.status']);
405
+				}
406
+				//get events to exclude
407
+				$exclude_query[0] = array_merge($where_params,
408
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
409
+				//first get all events that have datetimes where its not expired.
410
+				$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Datetime.EVT_ID');
411
+				$event_ids = array_keys($event_ids);
412
+				if (isset($where_params['DTT_EVT_end'])) {
413
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
414
+				}
415
+				$where_params['DTT_EVT_end'] = array('<', $current_time_for_DTT_EVT_end);
416
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
417
+				break;
418
+			case 'active' :
419
+				$where_params['Event.status'] = 'publish';
420
+				if (isset($where_params['DTT_EVT_start'])) {
421
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
422
+				}
423
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
424
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
425
+				}
426
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
427
+				$where_params['DTT_EVT_end'] = array('>', $current_time_for_DTT_EVT_end);
428
+				break;
429
+			case 'inactive' :
430
+				if (isset($where_params['Event.status'])) {
431
+					unset($where_params['Event.status']);
432
+				}
433
+				if (isset($where_params['OR'])) {
434
+					$where_params['AND']['OR'] = $where_params['OR'];
435
+				}
436
+				if (isset($where_params['DTT_EVT_end'])) {
437
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
438
+					unset($where_params['DTT_EVT_end']);
439
+				}
440
+				if (isset($where_params['DTT_EVT_start'])) {
441
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
442
+					unset($where_params['DTT_EVT_start']);
443
+				}
444
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
445
+				break;
446
+		}
447
+		$query_params[0] = $where_params;
448
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
449
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
450
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'DTT_EVT_start');
451
+		$columns_to_select = array(
452
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
453
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
454
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
455
+		);
456
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
457
+	}
458
+
459
+
460
+
461
+	/**
462
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
463
+	 * for the tickets for each datetime)
464
+	 *
465
+	 * @param EE_Datetime[] $datetimes
466
+	 */
467
+	public function update_sold($datetimes)
468
+	{
469
+		foreach ($datetimes as $datetime) {
470
+			$datetime->update_sold();
471
+		}
472
+	}
473
+
474
+
475
+
476
+	/**
477
+	 *    Gets the total number of tickets available at a particular datetime
478
+	 *    (does NOT take into account the datetime's spaces available)
479
+	 *
480
+	 * @param int   $DTT_ID
481
+	 * @param array $query_params
482
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
483
+	 *             tickets attached to datetime then FALSE is returned.
484
+	 */
485
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, $query_params = array())
486
+	{
487
+		$datetime = $this->get_one_by_ID($DTT_ID);
488
+		if ($datetime instanceof EE_Datetime) {
489
+			return $datetime->tickets_remaining($query_params);
490
+		}
491
+		return 0;
492
+	}
493
+
494
+
495
+
496
+	/**
497
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
498
+	 *
499
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
500
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
501
+	 *                                 for all valid stati.
502
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
503
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
504
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
505
+	 *                stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming EE_Datetime::expired
506
+	 */
507
+	public function get_datetime_counts_by_status($stati_to_include = array(), $query_params = array())
508
+	{
509
+		//only accept where conditions for this query.
510
+		$_where = isset($query_params[0]) ? $query_params[0] : array();
511
+		$status_query_args = array(
512
+			EE_Datetime::active   => array_merge(
513
+				$_where,
514
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
515
+			),
516
+			EE_Datetime::upcoming => array_merge(
517
+				$_where,
518
+				array('DTT_EVT_start' => array('>', time()))
519
+			),
520
+			EE_Datetime::expired  => array_merge(
521
+				$_where,
522
+				array('DTT_EVT_end' => array('<', time()))
523
+			),
524
+		);
525
+		if ( ! empty($stati_to_include)) {
526
+			foreach (array_keys($status_query_args) as $status) {
527
+				if ( ! in_array($status, $stati_to_include)) {
528
+					unset($status_query_args[$status]);
529
+				}
530
+			}
531
+		}
532
+		//loop through and query counts for each stati.
533
+		$status_query_results = array();
534
+		foreach ($status_query_args as $status => $status_where_conditions) {
535
+			$status_query_results[$status] = EEM_Datetime::count(array($status_where_conditions), 'DTT_ID', true);
536
+		}
537
+		return $status_query_results;
538
+	}
539
+
540
+
541
+
542
+	/**
543
+	 * Returns the specific count for a given Datetime status matching any given query_params.
544
+	 *
545
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
546
+	 * @param array  $query_params
547
+	 * @return int
548
+	 */
549
+	public function get_datetime_count_for_status($status = EE_Datetime::active, $query_params = array())
550
+	{
551
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
552
+		return ! empty($count[$status]) ? $count[$status] : 0;
553
+	}
554 554
 
555 555
 
556 556
 
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 2 patches
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -1,16 +1,16 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('No direct script access allowed'); }
2 2
  /**
3
- *
4
- * Class EE_SPCO_Reg_Step_Attendee_Information
5
- *
6
- * Description
7
- *
8
- * @package 			Event Espresso
9
- * @subpackage 	core
10
- * @author 				Brent Christensen
11
- * @since 				4.5.0
12
- *
13
- */
3
+  *
4
+  * Class EE_SPCO_Reg_Step_Attendee_Information
5
+  *
6
+  * Description
7
+  *
8
+  * @package 			Event Espresso
9
+  * @subpackage 	core
10
+  * @author 				Brent Christensen
11
+  * @since 				4.5.0
12
+  *
13
+  */
14 14
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step {
15 15
 
16 16
 	/**
@@ -135,33 +135,33 @@  discard block
 block discarded – undo
135 135
 					$registration instanceof EE_Registration
136 136
 					&& $this->checkout->visit_allows_processing_of_this_registration( $registration )
137 137
 				) {
138
-                    $attendee_reg_form = $this->_registrations_reg_form($registration);
139
-                    if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
140
-                        $subsections[$registration->reg_url_link()] = $attendee_reg_form;
141
-                        if ( ! $this->checkout->admin_request) {
142
-                            $template_args['registrations'][$registration->reg_url_link()] = $registration;
143
-                            $template_args['ticket_count'][$registration->ticket()->ID()] = isset(
144
-                                $template_args['ticket_count'][$registration->ticket()->ID()]
145
-                            )
146
-                                ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
147
-                                : 1;
148
-                            $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
149
-                                $this->checkout->cart->get_grand_total(),
150
-                                'Ticket',
151
-                                array($registration->ticket()->ID())
152
-                            );
153
-                            $ticket_line_item = is_array($ticket_line_item)
154
-                                ? reset($ticket_line_item)
155
-                                : $ticket_line_item;
156
-                            $template_args['ticket_line_item'][$registration->ticket()
157
-                                                                            ->ID()] = $Line_Item_Display->display_line_item(
158
-                                $ticket_line_item
159
-                            );
160
-                        }
161
-                    }
162
-                    if ($registration->is_primary_registrant()) {
163
-                        $primary_registrant = $registration->reg_url_link();
164
-                    }
138
+					$attendee_reg_form = $this->_registrations_reg_form($registration);
139
+					if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
140
+						$subsections[$registration->reg_url_link()] = $attendee_reg_form;
141
+						if ( ! $this->checkout->admin_request) {
142
+							$template_args['registrations'][$registration->reg_url_link()] = $registration;
143
+							$template_args['ticket_count'][$registration->ticket()->ID()] = isset(
144
+								$template_args['ticket_count'][$registration->ticket()->ID()]
145
+							)
146
+								? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
147
+								: 1;
148
+							$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
149
+								$this->checkout->cart->get_grand_total(),
150
+								'Ticket',
151
+								array($registration->ticket()->ID())
152
+							);
153
+							$ticket_line_item = is_array($ticket_line_item)
154
+								? reset($ticket_line_item)
155
+								: $ticket_line_item;
156
+							$template_args['ticket_line_item'][$registration->ticket()
157
+																			->ID()] = $Line_Item_Display->display_line_item(
158
+								$ticket_line_item
159
+							);
160
+						}
161
+					}
162
+					if ($registration->is_primary_registrant()) {
163
+						$primary_registrant = $registration->reg_url_link();
164
+					}
165 165
 				}
166 166
 			}
167 167
 			// print_copy_info ?
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 				// generate hidden input
174 174
 				if (
175 175
 					isset( $subsections[ $primary_registrant ] )
176
-				     && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
176
+					 && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
177 177
 				) {
178 178
 					$subsections[ $primary_registrant ]->add_subsections( $copy_options, 'primary_registrant', false );
179 179
 				}
@@ -208,35 +208,35 @@  discard block
 block discarded – undo
208 208
 	 */
209 209
 	private function _registrations_reg_form( EE_Registration $registration ) {
210 210
 		static $attendee_nmbr = 1;
211
-        $form_args = array();
211
+		$form_args = array();
212 212
 		// verify that registration has valid event
213 213
 		if ( $registration->event() instanceof EE_Event ) {
214 214
 			$question_groups = $registration->event()->question_groups(
215
-                array(
216
-                    array(
217
-                        'Event.EVT_ID'                     => $registration->event()->ID(),
218
-                        'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false
219
-                    ),
220
-                    'order_by' => array('QSG_order' => 'ASC')
221
-                )
222
-            );
215
+				array(
216
+					array(
217
+						'Event.EVT_ID'                     => $registration->event()->ID(),
218
+						'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false
219
+					),
220
+					'order_by' => array('QSG_order' => 'ASC')
221
+				)
222
+			);
223 223
 			if ( $question_groups ) {
224
-                // array of params to pass to parent constructor
225
-                $form_args = array(
226
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
227
-                    'html_class'      => 'ee-reg-form-attendee-dv',
228
-                    'html_style'      => $this->checkout->admin_request
229
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
230
-                        : '',
231
-                    'subsections'     => array(),
232
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
233
-                        array(
234
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
235
-                            'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr)
236
-                        )
237
-                    )
238
-                );
239
-                foreach ( $question_groups as $question_group ) {
224
+				// array of params to pass to parent constructor
225
+				$form_args = array(
226
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
227
+					'html_class'      => 'ee-reg-form-attendee-dv',
228
+					'html_style'      => $this->checkout->admin_request
229
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
230
+						: '',
231
+					'subsections'     => array(),
232
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
233
+						array(
234
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
235
+							'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr)
236
+						)
237
+					)
238
+				);
239
+				foreach ( $question_groups as $question_group ) {
240 240
 					if ( $question_group instanceof EE_Question_Group ) {
241 241
 						$form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
242 242
 							$registration,
@@ -244,19 +244,19 @@  discard block
 block discarded – undo
244 244
 						);
245 245
 					}
246 246
 				}
247
-                // add hidden input
248
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
249
-                    $registration
250
-                );
251
-                // if we have question groups for additional attendees, then display the copy options
247
+				// add hidden input
248
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
249
+					$registration
250
+				);
251
+				// if we have question groups for additional attendees, then display the copy options
252 252
 				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
253
-                if ($registration->is_primary_registrant()) {
254
-                    // generate hidden input
255
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs($registration);
256
-                }
257
-            }
253
+				if ($registration->is_primary_registrant()) {
254
+					// generate hidden input
255
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs($registration);
256
+				}
257
+			}
258 258
 		}
259
-        $attendee_nmbr++;
259
+		$attendee_nmbr++;
260 260
 		return ! empty($form_args) ? new EE_Form_Section_Proper( $form_args ) : null;
261 261
 	}
262 262
 
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
 					if ( isset( $valid_data[ $reg_url_link ] ) ) {
890 890
 						// do we need to copy basic info from primary attendee ?
891 891
 						$copy_primary = isset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] )
892
-						                && absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
892
+										&& absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
893 893
 							? true
894 894
 							: false;
895 895
 						// filter form input data for this registration
@@ -1064,7 +1064,7 @@  discard block
 block discarded – undo
1064 1064
 			? $form_input
1065 1065
 			: $form_input . '-' . $registration->reg_url_link();
1066 1066
 		$answer_is_obj = isset( $this->_registration_answers[ $answer_cache_id ] )
1067
-		                 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1067
+						 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1068 1068
 			? true
1069 1069
 			: false;
1070 1070
 		//rename form_inputs if they are EE_Attendee properties
@@ -1184,7 +1184,7 @@  discard block
 block discarded – undo
1184 1184
 		// then attempt to copy them from the primary attendee
1185 1185
 		if (
1186 1186
 			$this->checkout->primary_attendee_obj instanceof EE_Attendee
1187
-            && ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1187
+			&& ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1188 1188
 		) {
1189 1189
 			return $this->checkout->primary_attendee_obj;
1190 1190
 		}
@@ -1302,7 +1302,7 @@  discard block
 block discarded – undo
1302 1302
 		}
1303 1303
 		foreach ( $critical_attendee_details as $critical_attendee_detail ) {
1304 1304
 			if ( ! isset( $attendee_data[ $critical_attendee_detail ] )
1305
-			     || empty( $attendee_data[ $critical_attendee_detail ] )
1305
+				 || empty( $attendee_data[ $critical_attendee_detail ] )
1306 1306
 			) {
1307 1307
 				$attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1308 1308
 					$critical_attendee_detail
Please login to merge, or discard this patch.
Spacing   +211 added lines, -212 removed lines patch added patch discarded remove patch
@@ -41,21 +41,21 @@  discard block
 block discarded – undo
41 41
 	 * @access    public
42 42
 	 * @param    EE_Checkout $checkout
43 43
 	 */
44
-	public function __construct( EE_Checkout $checkout ) {
44
+	public function __construct(EE_Checkout $checkout) {
45 45
 		$this->_slug = 'attendee_information';
46 46
 		$this->_name = __('Attendee Information', 'event_espresso');
47
-		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
47
+		$this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'attendee_info_main.template.php';
48 48
 		$this->checkout = $checkout;
49 49
 		$this->_reset_success_message();
50 50
 		$this->set_instructions(
51
-			__( 'Please answer the following registration questions before proceeding.', 'event_espresso' )
51
+			__('Please answer the following registration questions before proceeding.', 'event_espresso')
52 52
 		);
53 53
 	}
54 54
 
55 55
 
56 56
 
57 57
 	public function translate_js_strings() {
58
-		EE_Registry::$i18n_js_strings['required_field'] = __( ' is a required question.', 'event_espresso' );
58
+		EE_Registry::$i18n_js_strings['required_field'] = __(' is a required question.', 'event_espresso');
59 59
 		EE_Registry::$i18n_js_strings['required_multi_field'] = __(
60 60
 			' is a required question. Please enter a value for at least one of the options.',
61 61
 			'event_espresso'
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 		// calculate taxes
116 116
 		$Line_Item_Display->display_line_item(
117 117
 			$this->checkout->cart->get_grand_total(),
118
-			array( 'set_tax_rate' => true )
118
+			array('set_tax_rate' => true)
119 119
 		);
120 120
 		/** @var $subsections EE_Form_Section_Proper[] */
121 121
 		$subsections = array(
@@ -127,13 +127,13 @@  discard block
 block discarded – undo
127 127
 			'ticket_count' 	=> array()
128 128
 		);
129 129
 		// grab the saved registrations from the transaction
130
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
131
-		if ( $registrations ) {
132
-			foreach ( $registrations as $registration ) {
130
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
131
+		if ($registrations) {
132
+			foreach ($registrations as $registration) {
133 133
 				// can this registration be processed during this visit ?
134 134
 				if (
135 135
 					$registration instanceof EE_Registration
136
-					&& $this->checkout->visit_allows_processing_of_this_registration( $registration )
136
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
137 137
 				) {
138 138
                     $attendee_reg_form = $this->_registrations_reg_form($registration);
139 139
                     if ($attendee_reg_form instanceof EE_Form_Section_Proper) {
@@ -165,17 +165,17 @@  discard block
 block discarded – undo
165 165
 				}
166 166
 			}
167 167
 			// print_copy_info ?
168
-			if ( $primary_registrant && ! $this->checkout->admin_request && count( $registrations ) > 1 ) {
168
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
169 169
 				// TODO: add admin option for toggling copy attendee info, then use that value to change $this->_print_copy_info
170 170
 				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
171 171
 					? $this->_copy_attendee_info_form()
172 172
 					: $this->_auto_copy_attendee_info();
173 173
 				// generate hidden input
174 174
 				if (
175
-					isset( $subsections[ $primary_registrant ] )
176
-				     && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
175
+					isset($subsections[$primary_registrant])
176
+				     && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
177 177
 				) {
178
-					$subsections[ $primary_registrant ]->add_subsections( $copy_options, 'primary_registrant', false );
178
+					$subsections[$primary_registrant]->add_subsections($copy_options, 'primary_registrant', false);
179 179
 				}
180 180
 			}
181 181
 
@@ -187,8 +187,7 @@  discard block
 block discarded – undo
187 187
 				'html_id' 					=> $this->reg_form_name(),
188 188
 				'subsections' 			=> $subsections,
189 189
 				'layout_strategy'		=> $this->checkout->admin_request ?
190
-					new EE_Div_Per_Section_Layout() :
191
-					new EE_Template_Layout(
190
+					new EE_Div_Per_Section_Layout() : new EE_Template_Layout(
192 191
 						array(
193 192
 							'layout_template_file' 	=> $this->_template, // layout_template
194 193
 							'template_args' 				=> $template_args
@@ -206,11 +205,11 @@  discard block
 block discarded – undo
206 205
 	 * @return EE_Form_Section_Proper
207 206
 	 * @throws \EE_Error
208 207
 	 */
209
-	private function _registrations_reg_form( EE_Registration $registration ) {
208
+	private function _registrations_reg_form(EE_Registration $registration) {
210 209
 		static $attendee_nmbr = 1;
211 210
         $form_args = array();
212 211
 		// verify that registration has valid event
213
-		if ( $registration->event() instanceof EE_Event ) {
212
+		if ($registration->event() instanceof EE_Event) {
214 213
 			$question_groups = $registration->event()->question_groups(
215 214
                 array(
216 215
                     array(
@@ -220,10 +219,10 @@  discard block
 block discarded – undo
220 219
                     'order_by' => array('QSG_order' => 'ASC')
221 220
                 )
222 221
             );
223
-			if ( $question_groups ) {
222
+			if ($question_groups) {
224 223
                 // array of params to pass to parent constructor
225 224
                 $form_args = array(
226
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
225
+                    'html_id'         => 'ee-registration-'.$registration->reg_url_link(),
227 226
                     'html_class'      => 'ee-reg-form-attendee-dv',
228 227
                     'html_style'      => $this->checkout->admin_request
229 228
                         ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
@@ -236,9 +235,9 @@  discard block
 block discarded – undo
236 235
                         )
237 236
                     )
238 237
                 );
239
-                foreach ( $question_groups as $question_group ) {
240
-					if ( $question_group instanceof EE_Question_Group ) {
241
-						$form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
238
+                foreach ($question_groups as $question_group) {
239
+					if ($question_group instanceof EE_Question_Group) {
240
+						$form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
242 241
 							$registration,
243 242
 							$question_group
244 243
 						);
@@ -257,7 +256,7 @@  discard block
 block discarded – undo
257 256
             }
258 257
 		}
259 258
         $attendee_nmbr++;
260
-		return ! empty($form_args) ? new EE_Form_Section_Proper( $form_args ) : null;
259
+		return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : null;
261 260
 	}
262 261
 
263 262
 
@@ -278,7 +277,7 @@  discard block
 block discarded – undo
278 277
 		// generate hidden input
279 278
 		return new EE_Hidden_Input(
280 279
 			array(
281
-				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
280
+				'html_id' => 'additional-attendee-reg-info-'.$registration->reg_url_link(),
282 281
 				'default' => $additional_attendee_reg_info
283 282
 			)
284 283
 		);
@@ -292,26 +291,26 @@  discard block
 block discarded – undo
292 291
 	 * @return EE_Form_Section_Proper
293 292
 	 * @throws \EE_Error
294 293
 	 */
295
-	private function _question_group_reg_form( EE_Registration $registration, EE_Question_Group $question_group ){
294
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group) {
296 295
 		// array of params to pass to parent constructor
297 296
 		$form_args = array(
298
-			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
297
+			'html_id'         => 'ee-reg-form-qstn-grp-'.$question_group->identifier(),
299 298
 			'html_class'      => $this->checkout->admin_request
300 299
 				? 'form-table ee-reg-form-qstn-grp-dv'
301 300
 				: 'ee-reg-form-qstn-grp-dv',
302
-			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
301
+			'html_label_id'   => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-lbl',
303 302
 			'subsections'     => array(
304
-				'reg_form_qstn_grp_hdr' => $this->_question_group_header( $question_group )
303
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group)
305 304
 			),
306 305
 			'layout_strategy' => $this->checkout->admin_request
307 306
 				? new EE_Admin_Two_Column_Layout()
308 307
 				: new EE_Div_Per_Section_Layout()
309 308
 		);
310 309
 		// where params
311
-		$query_params = array( 'QST_deleted' => 0 );
310
+		$query_params = array('QST_deleted' => 0);
312 311
 		// don't load admin only questions on the frontend
313
-		if ( ! $this->checkout->admin_request ) {
314
-			$query_params['QST_admin_only'] = array( '!=', true );
312
+		if ( ! $this->checkout->admin_request) {
313
+			$query_params['QST_admin_only'] = array('!=', true);
315 314
 		}
316 315
 		$questions = $question_group->get_many_related(
317 316
 			'Question',
@@ -333,10 +332,10 @@  discard block
 block discarded – undo
333 332
 			)
334 333
 		);
335 334
 		// loop thru questions
336
-		foreach ( $questions as $question ) {
337
-			if( $question instanceof EE_Question ){
335
+		foreach ($questions as $question) {
336
+			if ($question instanceof EE_Question) {
338 337
 				$identifier = $question->is_system_question() ? $question->system_ID() : $question->ID();
339
-				$form_args['subsections'][ $identifier ] = $this->reg_form_question( $registration, $question );
338
+				$form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
340 339
 			}
341 340
 		}
342 341
 		$form_args['subsections'] = apply_filters(
@@ -357,7 +356,7 @@  discard block
 block discarded – undo
357 356
 			)
358 357
 		);
359 358
 //		d( $form_args );
360
-		$question_group_reg_form = new EE_Form_Section_Proper( $form_args );
359
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
361 360
 		return apply_filters(
362 361
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
363 362
 			$question_group_reg_form,
@@ -374,11 +373,11 @@  discard block
 block discarded – undo
374 373
 	 * @param EE_Question_Group $question_group
375 374
 	 * @return 	EE_Form_Section_HTML
376 375
 	 */
377
-	private function _question_group_header( EE_Question_Group $question_group ){
376
+	private function _question_group_header(EE_Question_Group $question_group) {
378 377
 		$html = '';
379 378
 		// group_name
380
-		if ( $question_group->show_group_name() && $question_group->name() !== '' ) {
381
-			if ( $this->checkout->admin_request ) {
379
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
380
+			if ($this->checkout->admin_request) {
382 381
 				$html .= EEH_HTML::br();
383 382
 				$html .= EEH_HTML::h3(
384 383
 					$question_group->name(),
@@ -392,7 +391,7 @@  discard block
 block discarded – undo
392 391
 			}
393 392
 		}
394 393
 		// group_desc
395
-		if ( $question_group->show_group_desc() && $question_group->desc() !== '' ) {
394
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
396 395
 			$html .= EEH_HTML::p(
397 396
 				$question_group->desc(),
398 397
 				'',
@@ -402,7 +401,7 @@  discard block
 block discarded – undo
402 401
 			);
403 402
 
404 403
 		}
405
-		return new EE_Form_Section_HTML( $html );
404
+		return new EE_Form_Section_HTML($html);
406 405
 	}
407 406
 
408 407
 
@@ -412,7 +411,7 @@  discard block
 block discarded – undo
412 411
 	 * @return    EE_Form_Section_Proper
413 412
 	 * @throws \EE_Error
414 413
 	 */
415
-	private function _copy_attendee_info_form(){
414
+	private function _copy_attendee_info_form() {
416 415
 		// array of params to pass to parent constructor
417 416
 		return new EE_Form_Section_Proper(
418 417
 			array(
@@ -441,7 +440,7 @@  discard block
 block discarded – undo
441 440
 	private function _auto_copy_attendee_info() {
442 441
 		return new EE_Form_Section_HTML(
443 442
 			EEH_Template::locate_template(
444
-				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
443
+				SPCO_REG_STEPS_PATH.$this->_slug.DS.'_auto_copy_attendee_info.template.php',
445 444
 				apply_filters(
446 445
 					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
447 446
 					array()
@@ -465,32 +464,32 @@  discard block
 block discarded – undo
465 464
 		$copy_attendee_info_inputs = array();
466 465
 		$prev_ticket = NULL;
467 466
 		// grab the saved registrations from the transaction
468
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
469
-		foreach ( $registrations as $registration ) {
467
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
468
+		foreach ($registrations as $registration) {
470 469
 			// for all  attendees other than the primary attendee
471
-			if ( $registration instanceof EE_Registration && ! $registration->is_primary_registrant() ) {
470
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
472 471
 				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
473
-				if ( $registration->ticket()->ID() !== $prev_ticket ) {
472
+				if ($registration->ticket()->ID() !== $prev_ticket) {
474 473
 					$item_name = $registration->ticket()->name();
475 474
 					$item_name .= $registration->ticket()->description() !== ''
476
-						? ' - ' . $registration->ticket()->description()
475
+						? ' - '.$registration->ticket()->description()
477 476
 						: '';
478
-					$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']' ] = new EE_Form_Section_HTML(
479
-						'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
477
+					$copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-'.$registration->ticket()->ID().']'] = new EE_Form_Section_HTML(
478
+						'<h6 class="spco-copy-attendee-event-hdr">'.$item_name.'</h6>'
480 479
 					);
481 480
 					$prev_ticket = $registration->ticket()->ID();
482 481
 				}
483 482
 
484
-				$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[' . $registration->ID() . ']' ] = new
483
+				$copy_attendee_info_inputs['spco_copy_attendee_chk['.$registration->ID().']'] = new
485 484
 				EE_Checkbox_Multi_Input(
486 485
 					array(
487 486
 						$registration->ID() => sprintf(
488
-							__( 'Attendee #%s', 'event_espresso' ),
487
+							__('Attendee #%s', 'event_espresso'),
489 488
 							$registration->count()
490 489
 						)
491 490
 					),
492 491
 					array(
493
-						'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
492
+						'html_id'                 => 'spco-copy-attendee-chk-'.$registration->reg_url_link(),
494 493
 						'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
495 494
 						'display_html_label_text' => false
496 495
 					)
@@ -510,7 +509,7 @@  discard block
 block discarded – undo
510 509
 	 * @return    EE_Form_Input_Base
511 510
 	 * @throws \EE_Error
512 511
 	 */
513
-	private function _additional_primary_registrant_inputs( EE_Registration $registration ){
512
+	private function _additional_primary_registrant_inputs(EE_Registration $registration) {
514 513
 		// generate hidden input
515 514
 		return new EE_Hidden_Input(
516 515
 			array(
@@ -529,7 +528,7 @@  discard block
 block discarded – undo
529 528
 	 * @return    EE_Form_Input_Base
530 529
 	 * @throws \EE_Error
531 530
 	 */
532
-	public function reg_form_question( EE_Registration $registration, EE_Question $question ){
531
+	public function reg_form_question(EE_Registration $registration, EE_Question $question) {
533 532
 
534 533
 		// if this question was for an attendee detail, then check for that answer
535 534
 		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
@@ -538,32 +537,32 @@  discard block
 block discarded – undo
538 537
 		);
539 538
 		$answer = $answer_value === null
540 539
 			? EEM_Answer::instance()->get_one(
541
-				array( array( 'QST_ID' => $question->ID(), 'REG_ID' => $registration->ID() ) )
540
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
542 541
 			)
543 542
 			: null;
544 543
 		// if NOT returning to edit an existing registration
545 544
 		// OR if this question is for an attendee property
546 545
 		// OR we still don't have an EE_Answer object
547
-		if( $answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link() ) {
546
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
548 547
 			// create an EE_Answer object for storing everything in
549
-			$answer = EE_Answer::new_instance ( array(
548
+			$answer = EE_Answer::new_instance(array(
550 549
 				'QST_ID'=> $question->ID(),
551 550
 				'REG_ID'=> $registration->ID()
552 551
 			));
553 552
 		}
554 553
 		// verify instance
555
-		if( $answer instanceof EE_Answer ){
556
-			if ( ! empty( $answer_value )) {
557
-				$answer->set( 'ANS_value', $answer_value );
554
+		if ($answer instanceof EE_Answer) {
555
+			if ( ! empty($answer_value)) {
556
+				$answer->set('ANS_value', $answer_value);
558 557
 			}
559
-			$answer->cache( 'Question', $question );
558
+			$answer->cache('Question', $question);
560 559
 			//remember system ID had a bug where sometimes it could be null
561
-			$answer_cache_id =$question->is_system_question()
562
-				? $question->system_ID() . '-' . $registration->reg_url_link()
563
-				: $question->ID() . '-' . $registration->reg_url_link();
564
-			$registration->cache( 'Answer', $answer, $answer_cache_id );
560
+			$answer_cache_id = $question->is_system_question()
561
+				? $question->system_ID().'-'.$registration->reg_url_link()
562
+				: $question->ID().'-'.$registration->reg_url_link();
563
+			$registration->cache('Answer', $answer, $answer_cache_id);
565 564
 		}
566
-		return $this->_generate_question_input( $registration, $question, $answer );
565
+		return $this->_generate_question_input($registration, $question, $answer);
567 566
 
568 567
 	}
569 568
 
@@ -576,46 +575,46 @@  discard block
 block discarded – undo
576 575
 	 * @return EE_Form_Input_Base
577 576
 	 * @throws \EE_Error
578 577
 	 */
579
-	private function _generate_question_input( EE_Registration $registration, EE_Question $question, $answer ){
578
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer) {
580 579
 		$identifier = $question->is_system_question() ? $question->system_ID() : $question->ID();
581
-		$this->_required_questions[ $identifier ] = $question->required() ? true : false;
580
+		$this->_required_questions[$identifier] = $question->required() ? true : false;
582 581
 		add_filter(
583 582
 			'FHEE__EE_Question__generate_form_input__country_options',
584
-			array( $this, 'use_cached_countries_for_form_input' ),
583
+			array($this, 'use_cached_countries_for_form_input'),
585 584
 			10,
586 585
 			4
587 586
 		);
588 587
 		add_filter(
589 588
 			'FHEE__EE_Question__generate_form_input__state_options',
590
-			array( $this, 'use_cached_states_for_form_input' ),
589
+			array($this, 'use_cached_states_for_form_input'),
591 590
 			10,
592 591
 			4
593 592
 		);
594 593
 		$input_constructor_args = array(
595
-			'html_name'     => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
596
-			'html_id'       => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
597
-			'html_class'    => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
598
-			'html_label_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
594
+			'html_name'     => 'ee_reg_qstn['.$registration->ID().']['.$identifier.']',
595
+			'html_id'       => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
596
+			'html_class'    => 'ee-reg-qstn ee-reg-qstn-'.$identifier,
597
+			'html_label_id' => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
599 598
 			'html_label_class'	=> 'ee-reg-qstn',
600 599
 		);
601
-		$input_constructor_args['html_label_id'] 	.= '-lbl';
602
-		if ( $answer instanceof EE_Answer && $answer->ID() ) {
603
-			$input_constructor_args[ 'html_name' ] .= '[' . $answer->ID() . ']';
604
-			$input_constructor_args[ 'html_id' ] .= '-' . $answer->ID();
605
-			$input_constructor_args[ 'html_label_id' ] .= '-' . $answer->ID();
600
+		$input_constructor_args['html_label_id'] .= '-lbl';
601
+		if ($answer instanceof EE_Answer && $answer->ID()) {
602
+			$input_constructor_args['html_name'] .= '['.$answer->ID().']';
603
+			$input_constructor_args['html_id'] .= '-'.$answer->ID();
604
+			$input_constructor_args['html_label_id'] .= '-'.$answer->ID();
606 605
 		}
607
-		$form_input =  $question->generate_form_input(
606
+		$form_input = $question->generate_form_input(
608 607
 			$registration,
609 608
 			$answer,
610 609
 			$input_constructor_args
611 610
 		);
612 611
 		remove_filter(
613 612
 			'FHEE__EE_Question__generate_form_input__country_options',
614
-			array( $this, 'use_cached_countries_for_form_input' )
613
+			array($this, 'use_cached_countries_for_form_input')
615 614
 		);
616 615
 		remove_filter(
617 616
 			'FHEE__EE_Question__generate_form_input__state_options',
618
-			array( $this, 'use_cached_states_for_form_input' )
617
+			array($this, 'use_cached_states_for_form_input')
619 618
 		);
620 619
 		return $form_input;
621 620
 	}
@@ -637,22 +636,22 @@  discard block
 block discarded – undo
637 636
 		\EE_Registration $registration = null,
638 637
 		\EE_Answer $answer = null
639 638
 	) {
640
-		$country_options = array( '' => '' );
639
+		$country_options = array('' => '');
641 640
 		// get possibly cached list of countries
642 641
 		$countries = $this->checkout->action === 'process_reg_step'
643 642
 			? EEM_Country::instance()->get_all_countries()
644 643
 			: EEM_Country::instance()->get_all_active_countries();
645
-		if ( ! empty( $countries )) {
646
-			foreach( $countries as $country ){
647
-				if ( $country instanceof EE_Country ) {
648
-					$country_options[ $country->ID() ] = $country->name();
644
+		if ( ! empty($countries)) {
645
+			foreach ($countries as $country) {
646
+				if ($country instanceof EE_Country) {
647
+					$country_options[$country->ID()] = $country->name();
649 648
 				}
650 649
 			}
651 650
 		}
652
-		if( $question instanceof EE_Question
653
-			&& $registration instanceof EE_Registration ) {
651
+		if ($question instanceof EE_Question
652
+			&& $registration instanceof EE_Registration) {
654 653
 			$answer = EEM_Answer::instance()->get_one(
655
-				array( array( 'QST_ID' => $question->ID(), 'REG_ID' => $registration->ID() ) )
654
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
656 655
 			);
657 656
 		} else {
658 657
 			$answer = EE_Answer::new_instance();
@@ -685,14 +684,14 @@  discard block
 block discarded – undo
685 684
 		\EE_Registration $registration = null,
686 685
 		\EE_Answer $answer = null
687 686
 	) {
688
-		$state_options = array( '' => array( '' => ''));
687
+		$state_options = array('' => array('' => ''));
689 688
 		$states = $this->checkout->action === 'process_reg_step'
690 689
 			? EEM_State::instance()->get_all_states()
691 690
 			: EEM_State::instance()->get_all_active_states();
692
-		if ( ! empty( $states )) {
693
-			foreach( $states as $state ){
694
-				if ( $state instanceof EE_State ) {
695
-					$state_options[ $state->country()->name() ][ $state->ID() ] = $state->name();
691
+		if ( ! empty($states)) {
692
+			foreach ($states as $state) {
693
+				if ($state instanceof EE_State) {
694
+					$state_options[$state->country()->name()][$state->ID()] = $state->name();
696 695
 				}
697 696
 			}
698 697
 		}
@@ -720,24 +719,24 @@  discard block
 block discarded – undo
720 719
 	 * @throws \EE_Error
721 720
 	 */
722 721
 	public function process_reg_step() {
723
-		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
722
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
724 723
 		// grab validated data from form
725 724
 		$valid_data = $this->checkout->current_step->valid_data();
726 725
 		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
727 726
 		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
728 727
 		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
729
-		if ( empty( $valid_data ))  {
728
+		if (empty($valid_data)) {
730 729
 			EE_Error::add_error(
731
-				__( 'No valid question responses were received.', 'event_espresso' ),
730
+				__('No valid question responses were received.', 'event_espresso'),
732 731
 				__FILE__,
733 732
 				__FUNCTION__,
734 733
 				__LINE__
735 734
 			);
736 735
 			return false;
737 736
 		}
738
-		if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg ) {
737
+		if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
739 738
 			EE_Error::add_error(
740
-				__( 'A valid transaction could not be initiated for processing your registrations.', 'event_espresso' ),
739
+				__('A valid transaction could not be initiated for processing your registrations.', 'event_espresso'),
741 740
 				__FILE__,
742 741
 				__FUNCTION__,
743 742
 				__LINE__
@@ -745,11 +744,11 @@  discard block
 block discarded – undo
745 744
 			return false;
746 745
 		}
747 746
 		// get cached registrations
748
-		$registrations = $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params );
747
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
749 748
 		// verify we got the goods
750
-		if ( empty( $registrations )) {
749
+		if (empty($registrations)) {
751 750
 			EE_Error::add_error(
752
-				__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' ),
751
+				__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
753 752
 				__FILE__,
754 753
 				__FUNCTION__,
755 754
 				__LINE__
@@ -757,15 +756,15 @@  discard block
 block discarded – undo
757 756
 			return false;
758 757
 		}
759 758
 		// extract attendee info from form data and save to model objects
760
-		$registrations_processed = $this->_process_registrations( $registrations, $valid_data );
759
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
761 760
 		// if first pass thru SPCO,
762 761
 		// then let's check processed registrations against the total number of tickets in the cart
763
-		if ( $registrations_processed === false ) {
762
+		if ($registrations_processed === false) {
764 763
 			// but return immediately if the previous step exited early due to errors
765 764
 			return false;
766
-		} else if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count ) {
765
+		} else if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
767 766
 			// generate a correctly translated string for all possible singular/plural combinations
768
-			if ( $this->checkout->total_ticket_count === 1 && $registrations_processed !== 1 ) {
767
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
769 768
 				$error_msg = sprintf(
770 769
 					__(
771 770
 						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
@@ -774,7 +773,7 @@  discard block
 block discarded – undo
774 773
 					$this->checkout->total_ticket_count,
775 774
 					$registrations_processed
776 775
 				);
777
-			} else if ( $this->checkout->total_ticket_count !== 1 && $registrations_processed === 1 ) {
776
+			} else if ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
778 777
 				$error_msg = sprintf(
779 778
 					__(
780 779
 						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
@@ -793,17 +792,17 @@  discard block
 block discarded – undo
793 792
 					$registrations_processed
794 793
 				);
795 794
 			}
796
-			EE_Error::add_error( $error_msg, __FILE__, __FUNCTION__, __LINE__ );
795
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
797 796
 			return false;
798 797
 		}
799 798
 		// mark this reg step as completed
800 799
 		$this->set_completed();
801 800
 		$this->_set_success_message(
802
-			__( 'The Attendee Information Step has been successfully completed.', 'event_espresso' )
801
+			__('The Attendee Information Step has been successfully completed.', 'event_espresso')
803 802
 		);
804 803
 		//do action in case a plugin wants to do something with the data submitted in step 1.
805 804
 		//passes EE_Single_Page_Checkout, and it's posted data
806
-		do_action( 'AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data );
805
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
807 806
 		return true;
808 807
 	}
809 808
 
@@ -817,9 +816,9 @@  discard block
 block discarded – undo
817 816
 	 * @return boolean | int
818 817
 	 * @throws \EE_Error
819 818
 	 */
820
-	private function _process_registrations( $registrations = array(), $valid_data = array() ) {
819
+	private function _process_registrations($registrations = array(), $valid_data = array()) {
821 820
 		// load resources and set some defaults
822
-		EE_Registry::instance()->load_model( 'Attendee' );
821
+		EE_Registry::instance()->load_model('Attendee');
823 822
 		// holder for primary registrant attendee object
824 823
 		$this->checkout->primary_attendee_obj = NULL;
825 824
 		// array for tracking reg form data for the primary registrant
@@ -836,9 +835,9 @@  discard block
 block discarded – undo
836 835
 		// attendee counter
837 836
 		$att_nmbr = 0;
838 837
 		// grab the saved registrations from the transaction
839
-		foreach ( $registrations  as $registration ) {
838
+		foreach ($registrations  as $registration) {
840 839
 			// verify EE_Registration object
841
-			if ( ! $registration instanceof EE_Registration ) {
840
+			if ( ! $registration instanceof EE_Registration) {
842 841
 				EE_Error::add_error(
843 842
 					__(
844 843
 						'An invalid Registration object was discovered when attempting to process your registration information.',
@@ -853,12 +852,12 @@  discard block
 block discarded – undo
853 852
 			/** @var string $reg_url_link */
854 853
 			$reg_url_link = $registration->reg_url_link();
855 854
 			// reg_url_link exists ?
856
-			if ( ! empty( $reg_url_link ) ) {
855
+			if ( ! empty($reg_url_link)) {
857 856
 				// should this registration be processed during this visit ?
858
-				if ( $this->checkout->visit_allows_processing_of_this_registration( $registration ) ) {
857
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
859 858
 					// if NOT revisiting, then let's save the registration now,
860 859
 					// so that we have a REG_ID to use when generating other objects
861
-					if ( ! $this->checkout->revisit ) {
860
+					if ( ! $this->checkout->revisit) {
862 861
 						$registration->save();
863 862
 					}
864 863
 					/**
@@ -868,7 +867,7 @@  discard block
 block discarded – undo
868 867
 					 * @var bool   if true is returned by the plugin then the
869 868
 					 *      		registration processing is halted.
870 869
 					 */
871
-					if ( apply_filters(
870
+					if (apply_filters(
872 871
 						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
873 872
 						false,
874 873
 						$att_nmbr,
@@ -876,38 +875,38 @@  discard block
 block discarded – undo
876 875
 						$registrations,
877 876
 						$valid_data,
878 877
 						$this
879
-					) ) {
878
+					)) {
880 879
 						return false;
881 880
 					}
882 881
 
883 882
 					// Houston, we have a registration!
884 883
 					$att_nmbr++;
885
-					$this->_attendee_data[ $reg_url_link ] = array();
884
+					$this->_attendee_data[$reg_url_link] = array();
886 885
 					// grab any existing related answer objects
887 886
 					$this->_registration_answers = $registration->answers();
888 887
 					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
889
-					if ( isset( $valid_data[ $reg_url_link ] ) ) {
888
+					if (isset($valid_data[$reg_url_link])) {
890 889
 						// do we need to copy basic info from primary attendee ?
891
-						$copy_primary = isset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] )
892
-						                && absint( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ) === 0
890
+						$copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
891
+						                && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
893 892
 							? true
894 893
 							: false;
895 894
 						// filter form input data for this registration
896
-						$valid_data[ $reg_url_link ] = (array)apply_filters(
895
+						$valid_data[$reg_url_link] = (array) apply_filters(
897 896
 							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
898
-							$valid_data[ $reg_url_link ]
897
+							$valid_data[$reg_url_link]
899 898
 						);
900 899
 						// EEH_Debug_Tools::printr( $valid_data[ $reg_url_link ], '$valid_data[ $reg_url_link ]', __FILE__, __LINE__ );
901
-						if ( isset( $valid_data['primary_attendee'] )) {
902
-							$primary_registrant['line_item_id'] =  ! empty( $valid_data['primary_attendee'] )
900
+						if (isset($valid_data['primary_attendee'])) {
901
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
903 902
 								? $valid_data['primary_attendee']
904 903
 								: false;
905
-							unset( $valid_data['primary_attendee'] );
904
+							unset($valid_data['primary_attendee']);
906 905
 						}
907 906
 						// now loop through our array of valid post data && process attendee reg forms
908
-						foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs ) {
909
-							if ( ! in_array( $form_section, $non_input_form_sections )) {
910
-								foreach ( $form_inputs as $form_input => $input_value ) {
907
+						foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
908
+							if ( ! in_array($form_section, $non_input_form_sections)) {
909
+								foreach ($form_inputs as $form_input => $input_value) {
911 910
 									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
912 911
 									// check for critical inputs
913 912
 									if (
@@ -921,16 +920,16 @@  discard block
 block discarded – undo
921 920
 									// store a bit of data about the primary attendee
922 921
 									if (
923 922
 										$att_nmbr === 1
924
-										&& ! empty( $input_value )
923
+										&& ! empty($input_value)
925 924
 										&& $reg_url_link === $primary_registrant['line_item_id']
926 925
 									) {
927
-										$primary_registrant[ $form_input ] = $input_value;
926
+										$primary_registrant[$form_input] = $input_value;
928 927
 									} else if (
929 928
 										$copy_primary
930 929
 										&& $input_value === null
931
-										&& isset( $primary_registrant[ $form_input ] )
930
+										&& isset($primary_registrant[$form_input])
932 931
 									) {
933
-										$input_value = $primary_registrant[ $form_input ];
932
+										$input_value = $primary_registrant[$form_input];
934 933
 									}
935 934
 									// now attempt to save the input data
936 935
 									if (
@@ -972,55 +971,55 @@  discard block
 block discarded – undo
972 971
 						// have we met before?
973 972
 						$attendee = $this->_find_existing_attendee(
974 973
 							$registration,
975
-							$this->_attendee_data[ $reg_url_link ]
974
+							$this->_attendee_data[$reg_url_link]
976 975
 						);
977 976
 						// did we find an already existing record for this attendee ?
978
-						if ( $attendee instanceof EE_Attendee ) {
977
+						if ($attendee instanceof EE_Attendee) {
979 978
 							$attendee = $this->_update_existing_attendee_data(
980 979
 								$attendee,
981
-								$this->_attendee_data[ $reg_url_link ]
980
+								$this->_attendee_data[$reg_url_link]
982 981
 							);
983 982
 						} else {
984 983
 							// ensure critical details are set for additional attendees
985
-							$this->_attendee_data[ $reg_url_link ] = $att_nmbr > 1
984
+							$this->_attendee_data[$reg_url_link] = $att_nmbr > 1
986 985
 								? $this->_copy_critical_attendee_details_from_primary_registrant(
987
-									$this->_attendee_data[ $reg_url_link ]
986
+									$this->_attendee_data[$reg_url_link]
988 987
 								)
989
-								: $this->_attendee_data[ $reg_url_link ];
988
+								: $this->_attendee_data[$reg_url_link];
990 989
 							$attendee = $this->_create_new_attendee(
991 990
 								$registration,
992
-								$this->_attendee_data[ $reg_url_link ]
991
+								$this->_attendee_data[$reg_url_link]
993 992
 							);
994 993
 						}
995 994
 						// who's #1 ?
996
-						if ( $att_nmbr === 1 ) {
995
+						if ($att_nmbr === 1) {
997 996
 							$this->checkout->primary_attendee_obj = $attendee;
998 997
 						}
999 998
 					}
1000 999
 					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1001 1000
 					// add relation to registration, set attendee ID, and cache attendee
1002
-					$this->_associate_attendee_with_registration( $registration, $attendee );
1001
+					$this->_associate_attendee_with_registration($registration, $attendee);
1003 1002
 					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1004
-					if ( ! $registration->attendee() instanceof EE_Attendee ) {
1005
-						EE_Error::add_error( sprintf( __( 'Registration %s has an invalid or missing Attendee object.', 'event_espresso' ), $reg_url_link ), __FILE__, __FUNCTION__, __LINE__ );
1003
+					if ( ! $registration->attendee() instanceof EE_Attendee) {
1004
+						EE_Error::add_error(sprintf(__('Registration %s has an invalid or missing Attendee object.', 'event_espresso'), $reg_url_link), __FILE__, __FUNCTION__, __LINE__);
1006 1005
 						return false;
1007 1006
 					}
1008 1007
 					/** @type EE_Registration_Processor $registration_processor */
1009
-					$registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' );
1008
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1010 1009
 					// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
1011
-					$registration_processor->toggle_incomplete_registration_status_to_default( $registration, false );
1010
+					$registration_processor->toggle_incomplete_registration_status_to_default($registration, false);
1012 1011
 					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1013 1012
 					$this->checkout->transaction->toggle_failed_transaction_status();
1014 1013
 					// if we've gotten this far, then let's save what we have
1015 1014
 					$registration->save();
1016 1015
 					// add relation between TXN and registration
1017
-					$this->_associate_registration_with_transaction( $registration );
1016
+					$this->_associate_registration_with_transaction($registration);
1018 1017
 				} // end of if ( ! $this->checkout->revisit || $this->checkout->primary_revisit || ( $this->checkout->revisit && $this->checkout->reg_url_link == $reg_url_link )) {
1019 1018
 
1020
-			}  else {
1021
-				EE_Error::add_error( __( 'An invalid or missing line item ID was encountered while attempting to process the registration form.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
1019
+			} else {
1020
+				EE_Error::add_error(__('An invalid or missing line item ID was encountered while attempting to process the registration form.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1022 1021
 				// remove malformed data
1023
-				unset( $valid_data[ $reg_url_link ] );
1022
+				unset($valid_data[$reg_url_link]);
1024 1023
 				return false;
1025 1024
 			}
1026 1025
 
@@ -1049,26 +1048,26 @@  discard block
 block discarded – undo
1049 1048
 		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1050 1049
 		// allow for plugins to hook in and do their own processing of the form input.
1051 1050
 		// For plugins to bypass normal processing here, they just need to return a boolean value.
1052
-		if ( apply_filters(
1051
+		if (apply_filters(
1053 1052
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1054 1053
 			false,
1055 1054
 			$registration,
1056 1055
 			$form_input,
1057 1056
 			$input_value,
1058 1057
 			$this
1059
-		) ) {
1058
+		)) {
1060 1059
 			return true;
1061 1060
 		}
1062 1061
 		// $answer_cache_id is the key used to find the EE_Answer we want
1063 1062
 		$answer_cache_id = $this->checkout->reg_url_link
1064 1063
 			? $form_input
1065
-			: $form_input . '-' . $registration->reg_url_link();
1066
-		$answer_is_obj = isset( $this->_registration_answers[ $answer_cache_id ] )
1067
-		                 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer
1064
+			: $form_input.'-'.$registration->reg_url_link();
1065
+		$answer_is_obj = isset($this->_registration_answers[$answer_cache_id])
1066
+		                 && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1068 1067
 			? true
1069 1068
 			: false;
1070 1069
 		//rename form_inputs if they are EE_Attendee properties
1071
-		switch( (string)$form_input ) {
1070
+		switch ((string) $form_input) {
1072 1071
 
1073 1072
 			case 'state' :
1074 1073
 			case 'STA_ID' :
@@ -1083,32 +1082,32 @@  discard block
 block discarded – undo
1083 1082
 				break;
1084 1083
 
1085 1084
 			default :
1086
-				$ATT_input = 'ATT_' . $form_input;
1085
+				$ATT_input = 'ATT_'.$form_input;
1087 1086
 				//EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1088
-				$attendee_property = EEM_Attendee::instance()->has_field( $ATT_input ) ? true : false;
1089
-				$form_input = $attendee_property ? 'ATT_' . $form_input : $form_input;
1087
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1088
+				$form_input = $attendee_property ? 'ATT_'.$form_input : $form_input;
1090 1089
 		}
1091 1090
 		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1092 1091
 		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1093 1092
 		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1094 1093
 		// if this form input has a corresponding attendee property
1095
-		if ( $attendee_property ) {
1096
-			$this->_attendee_data[ $registration->reg_url_link() ][ $form_input ] = $input_value;
1097
-			if ( $answer_is_obj ) {
1094
+		if ($attendee_property) {
1095
+			$this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1096
+			if ($answer_is_obj) {
1098 1097
 				// and delete the corresponding answer since we won't be storing this data in that object
1099
-				$registration->_remove_relation_to( $this->_registration_answers[ $answer_cache_id ], 'Answer' );
1100
-				$this->_registration_answers[ $answer_cache_id ]->delete_permanently();
1098
+				$registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1099
+				$this->_registration_answers[$answer_cache_id]->delete_permanently();
1101 1100
 			}
1102 1101
 			return true;
1103
-		} elseif ( $answer_is_obj ) {
1102
+		} elseif ($answer_is_obj) {
1104 1103
 			// save this data to the answer object
1105
-			$this->_registration_answers[ $answer_cache_id ]->set_value( $input_value );
1106
-			$result = $this->_registration_answers[ $answer_cache_id ]->save();
1104
+			$this->_registration_answers[$answer_cache_id]->set_value($input_value);
1105
+			$result = $this->_registration_answers[$answer_cache_id]->save();
1107 1106
 			return $result !== false ? true : false;
1108 1107
 		} else {
1109
-			foreach ( $this->_registration_answers as $answer ) {
1110
-				if ( $answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id ) {
1111
-					$answer->set_value( $input_value );
1108
+			foreach ($this->_registration_answers as $answer) {
1109
+				if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1110
+					$answer->set_value($input_value);
1112 1111
 					$result = $answer->save();
1113 1112
 					return $result !== false ? true : false;
1114 1113
 				}
@@ -1130,15 +1129,15 @@  discard block
 block discarded – undo
1130 1129
 		$form_input = '',
1131 1130
 		$input_value = ''
1132 1131
 	) {
1133
-		if ( empty( $input_value ) ) {
1132
+		if (empty($input_value)) {
1134 1133
 			// if the form input isn't marked as being required, then just return
1135
-			if ( ! isset( $this->_required_questions[ $form_input ] ) || ! $this->_required_questions[ $form_input ] ) {
1134
+			if ( ! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1136 1135
 				return true;
1137 1136
 			}
1138
-			switch ( $form_input ) {
1137
+			switch ($form_input) {
1139 1138
 				case 'fname' :
1140 1139
 					EE_Error::add_error(
1141
-						__( 'First Name is a required value.', 'event_espresso' ),
1140
+						__('First Name is a required value.', 'event_espresso'),
1142 1141
 						__FILE__,
1143 1142
 						__FUNCTION__,
1144 1143
 						__LINE__
@@ -1147,7 +1146,7 @@  discard block
 block discarded – undo
1147 1146
 					break;
1148 1147
 				case 'lname' :
1149 1148
 					EE_Error::add_error(
1150
-						__( 'Last Name is a required value.', 'event_espresso' ),
1149
+						__('Last Name is a required value.', 'event_espresso'),
1151 1150
 						__FILE__,
1152 1151
 						__FUNCTION__,
1153 1152
 						__LINE__
@@ -1156,7 +1155,7 @@  discard block
 block discarded – undo
1156 1155
 					break;
1157 1156
 				case 'email' :
1158 1157
 					EE_Error::add_error(
1159
-						__( 'Please enter a valid email address.', 'event_espresso' ),
1158
+						__('Please enter a valid email address.', 'event_espresso'),
1160 1159
 						__FILE__,
1161 1160
 						__FUNCTION__,
1162 1161
 						__LINE__
@@ -1178,30 +1177,30 @@  discard block
 block discarded – undo
1178 1177
 	 * @return boolean|EE_Attendee
1179 1178
 	 * @throws \EE_Error
1180 1179
 	 */
1181
-	private function _find_existing_attendee( EE_Registration $registration, $attendee_data = array() ) {
1180
+	private function _find_existing_attendee(EE_Registration $registration, $attendee_data = array()) {
1182 1181
 		$existing_attendee = null;
1183 1182
 		// if none of the critical properties are set in the incoming attendee data...
1184 1183
 		// then attempt to copy them from the primary attendee
1185 1184
 		if (
1186 1185
 			$this->checkout->primary_attendee_obj instanceof EE_Attendee
1187
-            && ! isset( $attendee_data['ATT_fname'], $attendee_data['ATT_email'] )
1186
+            && ! isset($attendee_data['ATT_fname'], $attendee_data['ATT_email'])
1188 1187
 		) {
1189 1188
 			return $this->checkout->primary_attendee_obj;
1190 1189
 		}
1191 1190
 		// does this attendee already exist in the db ?
1192 1191
 		// we're searching using a combination of first name, last name, AND email address
1193
-		$ATT_fname = isset( $attendee_data['ATT_fname'] ) && ! empty( $attendee_data['ATT_fname'] )
1192
+		$ATT_fname = isset($attendee_data['ATT_fname']) && ! empty($attendee_data['ATT_fname'])
1194 1193
 			? $attendee_data['ATT_fname']
1195 1194
 			: '';
1196
-		$ATT_lname = isset( $attendee_data['ATT_lname'] ) && ! empty( $attendee_data['ATT_lname'] )
1195
+		$ATT_lname = isset($attendee_data['ATT_lname']) && ! empty($attendee_data['ATT_lname'])
1197 1196
 			? $attendee_data['ATT_lname']
1198 1197
 			: '';
1199
-		$ATT_email = isset( $attendee_data['ATT_email'] ) && ! empty( $attendee_data['ATT_email'] )
1198
+		$ATT_email = isset($attendee_data['ATT_email']) && ! empty($attendee_data['ATT_email'])
1200 1199
 			? $attendee_data['ATT_email']
1201 1200
 			: '';
1202 1201
 		// but only if those have values
1203
-		if ( $ATT_fname && $ATT_lname && $ATT_email ) {
1204
-			$existing_attendee = EEM_Attendee::instance()->find_existing_attendee( array(
1202
+		if ($ATT_fname && $ATT_lname && $ATT_email) {
1203
+			$existing_attendee = EEM_Attendee::instance()->find_existing_attendee(array(
1205 1204
 				'ATT_fname' => $ATT_fname,
1206 1205
 				'ATT_lname' => $ATT_lname,
1207 1206
 				'ATT_email' => $ATT_email
@@ -1225,13 +1224,13 @@  discard block
 block discarded – undo
1225 1224
 	 * @return \EE_Attendee
1226 1225
 	 * @throws \EE_Error
1227 1226
 	 */
1228
-	private function _update_existing_attendee_data( EE_Attendee $existing_attendee, $attendee_data = array() ) {
1227
+	private function _update_existing_attendee_data(EE_Attendee $existing_attendee, $attendee_data = array()) {
1229 1228
 		// first remove fname, lname, and email from attendee data
1230
-		$dont_set = array( 'ATT_fname', 'ATT_lname', 'ATT_email' );
1229
+		$dont_set = array('ATT_fname', 'ATT_lname', 'ATT_email');
1231 1230
 		// now loop thru what's left and add to attendee CPT
1232
-		foreach ( $attendee_data as $property_name => $property_value ) {
1233
-			if ( ! in_array( $property_name, $dont_set ) && EEM_Attendee::instance()->has_field( $property_name )) {
1234
-				$existing_attendee->set( $property_name, $property_value );
1231
+		foreach ($attendee_data as $property_name => $property_value) {
1232
+			if ( ! in_array($property_name, $dont_set) && EEM_Attendee::instance()->has_field($property_name)) {
1233
+				$existing_attendee->set($property_name, $property_value);
1235 1234
 			}
1236 1235
 		}
1237 1236
 		// better save that now
@@ -1249,11 +1248,11 @@  discard block
 block discarded – undo
1249 1248
 	 * @return void
1250 1249
 	 * @throws \EE_Error
1251 1250
 	 */
1252
-	private function _associate_attendee_with_registration( EE_Registration $registration, EE_Attendee $attendee ) {
1251
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee) {
1253 1252
 		// add relation to attendee
1254
-		$registration->_add_relation_to( $attendee, 'Attendee' );
1255
-		$registration->set_attendee_id( $attendee->ID() );
1256
-		$registration->update_cache_after_object_save( 'Attendee', $attendee );
1253
+		$registration->_add_relation_to($attendee, 'Attendee');
1254
+		$registration->set_attendee_id($attendee->ID());
1255
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1257 1256
 	}
1258 1257
 
1259 1258
 
@@ -1265,10 +1264,10 @@  discard block
 block discarded – undo
1265 1264
 	 * @return void
1266 1265
 	 * @throws \EE_Error
1267 1266
 	 */
1268
-	private function _associate_registration_with_transaction( EE_Registration $registration ) {
1267
+	private function _associate_registration_with_transaction(EE_Registration $registration) {
1269 1268
 		// add relation to attendee
1270
-		$this->checkout->transaction->_add_relation_to( $registration, 'Registration' );
1271
-		$this->checkout->transaction->update_cache_after_object_save( 'Registration', $registration );
1269
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1270
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1272 1271
 	}
1273 1272
 
1274 1273
 
@@ -1281,14 +1280,14 @@  discard block
 block discarded – undo
1281 1280
 	 * @return array
1282 1281
 	 * @throws \EE_Error
1283 1282
 	 */
1284
-	private function _copy_critical_attendee_details_from_primary_registrant( $attendee_data = array() ) {
1283
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array()) {
1285 1284
 		// bare minimum critical details include first name, last name, email address
1286
-		$critical_attendee_details = array( 'ATT_fname', 'ATT_lname', 'ATT_email' );
1285
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1287 1286
 		// add address info to critical details?
1288
-		if ( apply_filters(
1287
+		if (apply_filters(
1289 1288
 			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1290 1289
 			false
1291
-		) ) {
1290
+		)) {
1292 1291
 			$address_details = array(
1293 1292
 				'ATT_address',
1294 1293
 				'ATT_address2',
@@ -1298,13 +1297,13 @@  discard block
 block discarded – undo
1298 1297
 				'ATT_zip',
1299 1298
 				'ATT_phone'
1300 1299
 			);
1301
-			$critical_attendee_details = array_merge( $critical_attendee_details, $address_details );
1300
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1302 1301
 		}
1303
-		foreach ( $critical_attendee_details as $critical_attendee_detail ) {
1304
-			if ( ! isset( $attendee_data[ $critical_attendee_detail ] )
1305
-			     || empty( $attendee_data[ $critical_attendee_detail ] )
1302
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1303
+			if ( ! isset($attendee_data[$critical_attendee_detail])
1304
+			     || empty($attendee_data[$critical_attendee_detail])
1306 1305
 			) {
1307
-				$attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1306
+				$attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1308 1307
 					$critical_attendee_detail
1309 1308
 				);
1310 1309
 			}
@@ -1322,11 +1321,11 @@  discard block
 block discarded – undo
1322 1321
 	 * @return \EE_Attendee
1323 1322
 	 * @throws \EE_Error
1324 1323
 	 */
1325
-	private function _create_new_attendee( EE_Registration $registration, $attendee_data = array() ) {
1324
+	private function _create_new_attendee(EE_Registration $registration, $attendee_data = array()) {
1326 1325
 		// create new attendee object
1327
-		$new_attendee = EE_Attendee::new_instance( $attendee_data );
1326
+		$new_attendee = EE_Attendee::new_instance($attendee_data);
1328 1327
 		// set author to event creator
1329
-		$new_attendee->set( 'ATT_author', $registration->event()->wp_user() );
1328
+		$new_attendee->set('ATT_author', $registration->event()->wp_user());
1330 1329
 		$new_attendee->save();
1331 1330
 		return $new_attendee;
1332 1331
 	}
@@ -1343,7 +1342,7 @@  discard block
 block discarded – undo
1343 1342
 	 */
1344 1343
 	public function update_reg_step() {
1345 1344
 		// save everything
1346
-		if ( $this->process_reg_step() ) {
1345
+		if ($this->process_reg_step()) {
1347 1346
 			$this->checkout->redirect = true;
1348 1347
 			$this->checkout->redirect_url = add_query_arg(
1349 1348
 				array(
@@ -1352,7 +1351,7 @@  discard block
 block discarded – undo
1352 1351
 				),
1353 1352
 				$this->checkout->thank_you_page_url
1354 1353
 			);
1355
-			$this->checkout->json_response->set_redirect_url( $this->checkout->redirect_url );
1354
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1356 1355
 			return true;
1357 1356
 		}
1358 1357
 		return false;
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,239 +40,239 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.24.rc.030');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.24.rc.030');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        /**
197
-         *    espresso_plugin_activation
198
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
199
-         */
200
-        function espresso_plugin_activation()
201
-        {
202
-            update_option('ee_espresso_activation', true);
203
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		/**
197
+		 *    espresso_plugin_activation
198
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
199
+		 */
200
+		function espresso_plugin_activation()
201
+		{
202
+			update_option('ee_espresso_activation', true);
203
+		}
204 204
 
205
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
206
-        /**
207
-         *    espresso_load_error_handling
208
-         *    this function loads EE's class for handling exceptions and errors
209
-         */
210
-        function espresso_load_error_handling()
211
-        {
212
-            // load debugging tools
213
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
214
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
215
-                EEH_Debug_Tools::instance();
216
-            }
217
-            // load error handling
218
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
219
-                require_once(EE_CORE . 'EE_Error.core.php');
220
-            } else {
221
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
222
-            }
223
-        }
205
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
206
+		/**
207
+		 *    espresso_load_error_handling
208
+		 *    this function loads EE's class for handling exceptions and errors
209
+		 */
210
+		function espresso_load_error_handling()
211
+		{
212
+			// load debugging tools
213
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
214
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
215
+				EEH_Debug_Tools::instance();
216
+			}
217
+			// load error handling
218
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
219
+				require_once(EE_CORE . 'EE_Error.core.php');
220
+			} else {
221
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
222
+			}
223
+		}
224 224
 
225
-        /**
226
-         *    espresso_load_required
227
-         *    given a class name and path, this function will load that file or throw an exception
228
-         *
229
-         * @param    string $classname
230
-         * @param    string $full_path_to_file
231
-         * @throws    EE_Error
232
-         */
233
-        function espresso_load_required($classname, $full_path_to_file)
234
-        {
235
-            static $error_handling_loaded = false;
236
-            if ( ! $error_handling_loaded) {
237
-                espresso_load_error_handling();
238
-                $error_handling_loaded = true;
239
-            }
240
-            if (is_readable($full_path_to_file)) {
241
-                require_once($full_path_to_file);
242
-            } else {
243
-                throw new EE_Error (
244
-                        sprintf(
245
-                                esc_html__(
246
-                                        'The %s class file could not be located or is not readable due to file permissions.',
247
-                                        'event_espresso'
248
-                                ),
249
-                                $classname
250
-                        )
251
-                );
252
-            }
253
-        }
225
+		/**
226
+		 *    espresso_load_required
227
+		 *    given a class name and path, this function will load that file or throw an exception
228
+		 *
229
+		 * @param    string $classname
230
+		 * @param    string $full_path_to_file
231
+		 * @throws    EE_Error
232
+		 */
233
+		function espresso_load_required($classname, $full_path_to_file)
234
+		{
235
+			static $error_handling_loaded = false;
236
+			if ( ! $error_handling_loaded) {
237
+				espresso_load_error_handling();
238
+				$error_handling_loaded = true;
239
+			}
240
+			if (is_readable($full_path_to_file)) {
241
+				require_once($full_path_to_file);
242
+			} else {
243
+				throw new EE_Error (
244
+						sprintf(
245
+								esc_html__(
246
+										'The %s class file could not be located or is not readable due to file permissions.',
247
+										'event_espresso'
248
+								),
249
+								$classname
250
+						)
251
+				);
252
+			}
253
+		}
254 254
 
255
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
256
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
257
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
258
-        new EE_Bootstrap();
259
-    }
255
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
256
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
257
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
258
+		new EE_Bootstrap();
259
+	}
260 260
 }
261 261
 if ( ! function_exists('espresso_deactivate_plugin')) {
262
-    /**
263
-     *    deactivate_plugin
264
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
265
-     *
266
-     * @access public
267
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
268
-     * @return    void
269
-     */
270
-    function espresso_deactivate_plugin($plugin_basename = '')
271
-    {
272
-        if ( ! function_exists('deactivate_plugins')) {
273
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
274
-        }
275
-        unset($_GET['activate'], $_REQUEST['activate']);
276
-        deactivate_plugins($plugin_basename);
277
-    }
262
+	/**
263
+	 *    deactivate_plugin
264
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
265
+	 *
266
+	 * @access public
267
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
268
+	 * @return    void
269
+	 */
270
+	function espresso_deactivate_plugin($plugin_basename = '')
271
+	{
272
+		if ( ! function_exists('deactivate_plugins')) {
273
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
274
+		}
275
+		unset($_GET['activate'], $_REQUEST['activate']);
276
+		deactivate_plugins($plugin_basename);
277
+	}
278 278
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Base_Class.class.php 2 patches
Doc Comments   +9 added lines, -8 removed lines patch added patch discarded remove patch
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
      *
575 575
      * @param \EE_Datetime_Field $datetime_field
576 576
      * @param bool               $pretty
577
-     * @param null $date_or_time
577
+     * @param string|null $date_or_time
578 578
      * @return void
579 579
      * @throws \EE_Error
580 580
      */
@@ -892,7 +892,7 @@  discard block
 block discarded – undo
892 892
      *
893 893
      * @param null  $field_to_order_by  What field is being used as the reference point.
894 894
      * @param array $query_params       Any additional conditions on the query.
895
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
895
+     * @param string  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
896 896
      *                                  you can indicate just the columns you want returned
897 897
      * @return array|EE_Base_Class
898 898
      * @throws \EE_Error
@@ -917,7 +917,7 @@  discard block
 block discarded – undo
917 917
      *
918 918
      * @param null  $field_to_order_by  What field is being used as the reference point.
919 919
      * @param array $query_params       Any additional conditions on the query.
920
-     * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
920
+     * @param string  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
921 921
      *                                  you can indicate just the column you want returned
922 922
      * @return array|EE_Base_Class
923 923
      * @throws \EE_Error
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
      * This method simply returns the RAW unprocessed value for the given property in this class
991 991
      *
992 992
      * @param  string $field_name A valid fieldname
993
-     * @return mixed              Whatever the raw value stored on the property is.
993
+     * @return integer|null              Whatever the raw value stored on the property is.
994 994
      * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
995 995
      */
996 996
     public function get_raw($field_name)
@@ -1256,7 +1256,7 @@  discard block
 block discarded – undo
1256 1256
      * sets the time on a datetime property
1257 1257
      *
1258 1258
      * @access protected
1259
-     * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1259
+     * @param string $time      a valid time string for php datetime functions (or DateTime object)
1260 1260
      * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1261 1261
      * @throws \EE_Error
1262 1262
      */
@@ -1271,7 +1271,7 @@  discard block
 block discarded – undo
1271 1271
      * sets the date on a datetime property
1272 1272
      *
1273 1273
      * @access protected
1274
-     * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1274
+     * @param string $date      a valid date string for php datetime functions ( or DateTime object)
1275 1275
      * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1276 1276
      * @throws \EE_Error
1277 1277
      */
@@ -1329,6 +1329,7 @@  discard block
 block discarded – undo
1329 1329
      * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1330 1330
      * @param string               $prepend    You can include something to prepend on the timestamp
1331 1331
      * @param string               $append     You can include something to append on the timestamp
1332
+     * @param string $args
1332 1333
      * @throws EE_Error
1333 1334
      * @return string timestamp
1334 1335
      */
@@ -1699,7 +1700,7 @@  discard block
 block discarded – undo
1699 1700
      *
1700 1701
      * @param  array  $props_n_values   incoming array of properties and their values
1701 1702
      * @param  string $classname        the classname of the child class
1702
-     * @param null    $timezone
1703
+     * @param string|null    $timezone
1703 1704
      * @param array   $date_formats     incoming date_formats in an array where the first value is the
1704 1705
      *                                  date_format and the second value is the time format
1705 1706
      * @return mixed (EE_Base_Class|bool)
@@ -1777,7 +1778,7 @@  discard block
 block discarded – undo
1777 1778
      * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1778 1779
      *
1779 1780
      * @param string $model_classname
1780
-     * @param null   $timezone
1781
+     * @param string|null   $timezone
1781 1782
      * @return EEM_Base
1782 1783
      */
1783 1784
     protected static function _get_model_instance_with_name($model_classname, $timezone = null)
Please login to merge, or discard this patch.
Indentation   +2550 added lines, -2550 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 do_action('AHEE_log', __FILE__, ' FILE LOADED', '');
5 5
 
@@ -25,2555 +25,2555 @@  discard block
 block discarded – undo
25 25
 abstract class EE_Base_Class
26 26
 {
27 27
 
28
-    /**
29
-     * This is an array of the original properties and values provided during construction
30
-     * of this model object. (keys are model field names, values are their values).
31
-     * This list is important to remember so that when we are merging data from the db, we know
32
-     * which values to override and which to not override.
33
-     *
34
-     * @var array
35
-     */
36
-    protected $_props_n_values_provided_in_constructor;
37
-
38
-    /**
39
-     * Timezone
40
-     * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT all
41
-     * EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have access to it.
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_timezone;
46
-
47
-
48
-
49
-    /**
50
-     * date format
51
-     * pattern or format for displaying dates
52
-     *
53
-     * @var string $_dt_frmt
54
-     */
55
-    protected $_dt_frmt;
56
-
57
-
58
-
59
-    /**
60
-     * time format
61
-     * pattern or format for displaying time
62
-     *
63
-     * @var string $_tm_frmt
64
-     */
65
-    protected $_tm_frmt;
66
-
67
-
68
-
69
-    /**
70
-     * This property is for holding a cached array of object properties indexed by property name as the key.
71
-     * The purpose of this is for setting a cache on properties that may have calculated values after a prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having to recalculate.
72
-     * Used by _set_cached_property() and _get_cached_property() methods.
73
-     *
74
-     * @var array
75
-     */
76
-    protected $_cached_properties = array();
77
-
78
-    /**
79
-     * An array containing keys of the related model, and values are either an array of related mode objects or a single
80
-     * related model object. see the model's _model_relations. The keys should match those specified. And if the relation
81
-     * is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object, all others have an array)
82
-     *
83
-     * @var array
84
-     */
85
-    protected $_model_relations = array();
86
-
87
-    /**
88
-     * Array where keys are field names (see the model's _fields property) and values are their values. To see what
89
-     * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
90
-     *
91
-     * @var array
92
-     */
93
-    protected $_fields = array();
94
-
95
-    /**
96
-     * @var boolean indicating whether or not this model object is intended to ever be saved
97
-     * For example, we might create model objects intended to only be used for the duration
98
-     * of this request and to be thrown away, and if they were accidentally saved
99
-     * it would be a bug.
100
-     */
101
-    protected $_allow_persist = true;
102
-
103
-
104
-
105
-    /**
106
-     * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children play nice
107
-     *
108
-     * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd layer of the model's _fields array, (eg, EVT_ID, TXN_amount, QST_name, etc) and values are their values
109
-     * @param boolean $bydb                                    a flag for setting if the class is instantiated by the corresponding db model or not.
110
-     * @param string  $timezone                                indicate what timezone you want any datetime fields to be in when instantiating a EE_Base_Class object.
111
-     * @param array   $date_formats                            An array of date formats to set on construct where first
112
-     *                                                         value is the date_format and second value is the time
113
-     *                                                         format.
114
-     * @throws EE_Error
115
-     */
116
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
117
-    {
118
-        $className = get_class($this);
119
-        do_action("AHEE__{$className}__construct", $this, $fieldValues);
120
-        $model = $this->get_model();
121
-        $model_fields = $model->field_settings(false);
122
-        // ensure $fieldValues is an array
123
-        $fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
124
-        // EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
125
-        // verify client code has not passed any invalid field names
126
-        foreach ($fieldValues as $field_name => $field_value) {
127
-            if ( ! isset($model_fields[$field_name])) {
128
-                throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s", "event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
129
-            }
130
-        }
131
-        // EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
132
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
133
-        if ( ! empty($date_formats) && is_array($date_formats)) {
134
-            list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
135
-        } else {
136
-            //set default formats for date and time
137
-            $this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
138
-            $this->_tm_frmt = (string)get_option('time_format', 'g:i a');
139
-        }
140
-        //if db model is instantiating
141
-        if ($bydb) {
142
-            //client code has indicated these field values are from the database
143
-            foreach ($model_fields as $fieldName => $field) {
144
-                $this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
145
-            }
146
-        } else {
147
-            //we're constructing a brand
148
-            //new instance of the model object. Generally, this means we'll need to do more field validation
149
-            foreach ($model_fields as $fieldName => $field) {
150
-                $this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
151
-            }
152
-        }
153
-        //remember what values were passed to this constructor
154
-        $this->_props_n_values_provided_in_constructor = $fieldValues;
155
-        //remember in entity mapper
156
-        if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
157
-            $model->add_to_entity_map($this);
158
-        }
159
-        //setup all the relations
160
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
161
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
162
-                $this->_model_relations[$relation_name] = null;
163
-            } else {
164
-                $this->_model_relations[$relation_name] = array();
165
-            }
166
-        }
167
-        /**
168
-         * Action done at the end of each model object construction
169
-         *
170
-         * @param EE_Base_Class $this the model object just created
171
-         */
172
-        do_action('AHEE__EE_Base_Class__construct__finished', $this);
173
-    }
174
-
175
-
176
-
177
-    /**
178
-     * Gets whether or not this model object is allowed to persist/be saved to the database.
179
-     *
180
-     * @return boolean
181
-     */
182
-    public function allow_persist()
183
-    {
184
-        return $this->_allow_persist;
185
-    }
186
-
187
-
188
-
189
-    /**
190
-     * Sets whether or not this model object should be allowed to be saved to the DB.
191
-     * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
192
-     * you got new information that somehow made you change your mind.
193
-     *
194
-     * @param boolean $allow_persist
195
-     * @return boolean
196
-     */
197
-    public function set_allow_persist($allow_persist)
198
-    {
199
-        return $this->_allow_persist = $allow_persist;
200
-    }
201
-
202
-
203
-
204
-    /**
205
-     * Gets the field's original value when this object was constructed during this request.
206
-     * This can be helpful when determining if a model object has changed or not
207
-     *
208
-     * @param string $field_name
209
-     * @return mixed|null
210
-     * @throws \EE_Error
211
-     */
212
-    public function get_original($field_name)
213
-    {
214
-        if (isset($this->_props_n_values_provided_in_constructor[$field_name])
215
-            && $field_settings = $this->get_model()->field_settings_for($field_name)
216
-        ) {
217
-            return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
218
-        } else {
219
-            return null;
220
-        }
221
-    }
222
-
223
-
224
-
225
-    /**
226
-     * @param EE_Base_Class $obj
227
-     * @return string
228
-     */
229
-    public function get_class($obj)
230
-    {
231
-        return get_class($obj);
232
-    }
233
-
234
-
235
-
236
-    /**
237
-     * Overrides parent because parent expects old models.
238
-     * This also doesn't do any validation, and won't work for serialized arrays
239
-     *
240
-     * @param    string $field_name
241
-     * @param    mixed  $field_value
242
-     * @param bool      $use_default
243
-     * @throws \EE_Error
244
-     */
245
-    public function set($field_name, $field_value, $use_default = false)
246
-    {
247
-        $field_obj = $this->get_model()->field_settings_for($field_name);
248
-        if ($field_obj instanceof EE_Model_Field_Base) {
249
-            //			if ( method_exists( $field_obj, 'set_timezone' )) {
250
-            if ($field_obj instanceof EE_Datetime_Field) {
251
-                $field_obj->set_timezone($this->_timezone);
252
-                $field_obj->set_date_format($this->_dt_frmt);
253
-                $field_obj->set_time_format($this->_tm_frmt);
254
-            }
255
-            $holder_of_value = $field_obj->prepare_for_set($field_value);
256
-            //should the value be null?
257
-            if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
258
-                $this->_fields[$field_name] = $field_obj->get_default_value();
259
-                /**
260
-                 * To save having to refactor all the models, if a default value is used for a
261
-                 * EE_Datetime_Field, and that value is not null nor is it a DateTime
262
-                 * object.  Then let's do a set again to ensure that it becomes a DateTime
263
-                 * object.
264
-                 *
265
-                 * @since 4.6.10+
266
-                 */
267
-                if (
268
-                    $field_obj instanceof EE_Datetime_Field
269
-                    && $this->_fields[$field_name] !== null
270
-                    && ! $this->_fields[$field_name] instanceof DateTime
271
-                ) {
272
-                    empty($this->_fields[$field_name])
273
-                        ? $this->set($field_name, time())
274
-                        : $this->set($field_name, $this->_fields[$field_name]);
275
-                }
276
-            } else {
277
-                $this->_fields[$field_name] = $holder_of_value;
278
-            }
279
-            //if we're not in the constructor...
280
-            //now check if what we set was a primary key
281
-            if (
282
-                //note: props_n_values_provided_in_constructor is only set at the END of the constructor
283
-                $this->_props_n_values_provided_in_constructor
284
-                && $field_value
285
-                && $field_name === self::_get_primary_key_name(get_class($this))
286
-            ) {
287
-                //if so, we want all this object's fields to be filled either with
288
-                //what we've explicitly set on this model
289
-                //or what we have in the db
290
-                // echo "setting primary key!";
291
-                $fields_on_model = self::_get_model(get_class($this))->field_settings();
292
-                $obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
293
-                foreach ($fields_on_model as $field_obj) {
294
-                    if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
295
-                         && $field_obj->get_name() !== $field_name
296
-                    ) {
297
-                        $this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
298
-                    }
299
-                }
300
-                //oh this model object has an ID? well make sure its in the entity mapper
301
-                $this->get_model()->add_to_entity_map($this);
302
-            }
303
-            //let's unset any cache for this field_name from the $_cached_properties property.
304
-            $this->_clear_cached_property($field_name);
305
-        } else {
306
-            throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s", "event_espresso"), $field_name));
307
-        }
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * This sets the field value on the db column if it exists for the given $column_name or
314
-     * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
315
-     *
316
-     * @see EE_message::get_column_value for related documentation on the necessity of this method.
317
-     * @param string $field_name  Must be the exact column name.
318
-     * @param mixed  $field_value The value to set.
319
-     * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
320
-     * @throws \EE_Error
321
-     */
322
-    public function set_field_or_extra_meta($field_name, $field_value)
323
-    {
324
-        if ($this->get_model()->has_field($field_name)) {
325
-            $this->set($field_name, $field_value);
326
-            return true;
327
-        } else {
328
-            //ensure this object is saved first so that extra meta can be properly related.
329
-            $this->save();
330
-            return $this->update_extra_meta($field_name, $field_value);
331
-        }
332
-    }
333
-
334
-
335
-
336
-    /**
337
-     * This retrieves the value of the db column set on this class or if that's not present
338
-     * it will attempt to retrieve from extra_meta if found.
339
-     * Example Usage:
340
-     * Via EE_Message child class:
341
-     * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
342
-     * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
343
-     * also have additional main fields specific to the messenger.  The system accommodates those extra
344
-     * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
345
-     * value for those extra fields dynamically via the EE_message object.
346
-     *
347
-     * @param  string $field_name expecting the fully qualified field name.
348
-     * @return mixed|null  value for the field if found.  null if not found.
349
-     * @throws \EE_Error
350
-     */
351
-    public function get_field_or_extra_meta($field_name)
352
-    {
353
-        if ($this->get_model()->has_field($field_name)) {
354
-            $column_value = $this->get($field_name);
355
-        } else {
356
-            //This isn't a column in the main table, let's see if it is in the extra meta.
357
-            $column_value = $this->get_extra_meta($field_name, true, null);
358
-        }
359
-        return $column_value;
360
-    }
361
-
362
-
363
-
364
-    /**
365
-     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally for being able to reference what timezone we are running conversions on when converting TO the internal timezone (UTC
366
-     * Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is available to all child classes that may be using the EE_Datetime_Field for a field data type.
367
-     *
368
-     * @access public
369
-     * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
370
-     * @return void
371
-     * @throws \EE_Error
372
-     */
373
-    public function set_timezone($timezone = '')
374
-    {
375
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
376
-        //make sure we clear all cached properties because they won't be relevant now
377
-        $this->_clear_cached_properties();
378
-        //make sure we update field settings and the date for all EE_Datetime_Fields
379
-        $model_fields = $this->get_model()->field_settings(false);
380
-        foreach ($model_fields as $field_name => $field_obj) {
381
-            if ($field_obj instanceof EE_Datetime_Field) {
382
-                $field_obj->set_timezone($this->_timezone);
383
-                if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
384
-                    $this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
385
-                }
386
-            }
387
-        }
388
-    }
389
-
390
-
391
-
392
-    /**
393
-     * This just returns whatever is set for the current timezone.
394
-     *
395
-     * @access public
396
-     * @return string timezone string
397
-     */
398
-    public function get_timezone()
399
-    {
400
-        return $this->_timezone;
401
-    }
402
-
403
-
404
-
405
-    /**
406
-     * This sets the internal date format to what is sent in to be used as the new default for the class
407
-     * internally instead of wp set date format options
408
-     *
409
-     * @since 4.6
410
-     * @param string $format should be a format recognizable by PHP date() functions.
411
-     */
412
-    public function set_date_format($format)
413
-    {
414
-        $this->_dt_frmt = $format;
415
-        //clear cached_properties because they won't be relevant now.
416
-        $this->_clear_cached_properties();
417
-    }
418
-
419
-
420
-
421
-    /**
422
-     * This sets the internal time format string to what is sent in to be used as the new default for the
423
-     * class internally instead of wp set time format options.
424
-     *
425
-     * @since 4.6
426
-     * @param string $format should be a format recognizable by PHP date() functions.
427
-     */
428
-    public function set_time_format($format)
429
-    {
430
-        $this->_tm_frmt = $format;
431
-        //clear cached_properties because they won't be relevant now.
432
-        $this->_clear_cached_properties();
433
-    }
434
-
435
-
436
-
437
-    /**
438
-     * This returns the current internal set format for the date and time formats.
439
-     *
440
-     * @param bool $full           if true (default), then return the full format.  Otherwise will return an array where the
441
-     *                             first value is the date format and the second value is the time format.
442
-     * @return mixed string|array
443
-     */
444
-    public function get_format($full = true)
445
-    {
446
-        return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     * cache
453
-     * stores the passed model object on the current model object.
454
-     * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
455
-     *
456
-     * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg 'Registration' associated with this model object
457
-     * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction, that could be a payment or a registration)
458
-     * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many items which will be stored in an array on this object
459
-     * @throws EE_Error
460
-     * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one related thing, no array)
461
-     */
462
-    public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
463
-    {
464
-        // its entirely possible that there IS no related object yet in which case there is nothing to cache.
465
-        if ( ! $object_to_cache instanceof EE_Base_Class) {
466
-            return false;
467
-        }
468
-        // also get "how" the object is related, or throw an error
469
-        if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
470
-            throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'), $relationName, get_class($this)));
471
-        }
472
-        // how many things are related ?
473
-        if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
474
-            // if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
475
-            // so for these model objects just set it to be cached
476
-            $this->_model_relations[$relationName] = $object_to_cache;
477
-            $return = true;
478
-        } else {
479
-            // otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
480
-            // eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
481
-            if ( ! is_array($this->_model_relations[$relationName])) {
482
-                // if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
483
-                $this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class ? array($this->_model_relations[$relationName]) : array();
484
-            }
485
-            // first check for a cache_id which is normally empty
486
-            if ( ! empty($cache_id)) {
487
-                // if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
488
-                $this->_model_relations[$relationName][$cache_id] = $object_to_cache;
489
-                $return = $cache_id;
490
-            } elseif ($object_to_cache->ID()) {
491
-                // OR the cached object originally came from the db, so let's just use it's PK for an ID
492
-                $this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
493
-                $return = $object_to_cache->ID();
494
-            } else {
495
-                // OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
496
-                $this->_model_relations[$relationName][] = $object_to_cache;
497
-                // move the internal pointer to the end of the array
498
-                end($this->_model_relations[$relationName]);
499
-                // and grab the key so that we can return it
500
-                $return = key($this->_model_relations[$relationName]);
501
-            }
502
-        }
503
-        return $return;
504
-    }
505
-
506
-
507
-
508
-    /**
509
-     * For adding an item to the cached_properties property.
510
-     *
511
-     * @access protected
512
-     * @param string      $fieldname the property item the corresponding value is for.
513
-     * @param mixed       $value     The value we are caching.
514
-     * @param string|null $cache_type
515
-     * @return void
516
-     * @throws \EE_Error
517
-     */
518
-    protected function _set_cached_property($fieldname, $value, $cache_type = null)
519
-    {
520
-        //first make sure this property exists
521
-        $this->get_model()->field_settings_for($fieldname);
522
-        $cache_type = empty($cache_type) ? 'standard' : $cache_type;
523
-        $this->_cached_properties[$fieldname][$cache_type] = $value;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
530
-     * This also SETS the cache if we return the actual property!
531
-     *
532
-     * @param string $fieldname        the name of the property we're trying to retrieve
533
-     * @param bool   $pretty
534
-     * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
535
-     *                                 (in cases where the same property may be used for different outputs
536
-     *                                 - i.e. datetime, money etc.)
537
-     *                                 It can also accept certain pre-defined "schema" strings
538
-     *                                 to define how to output the property.
539
-     *                                 see the field's prepare_for_pretty_echoing for what strings can be used
540
-     * @return mixed                   whatever the value for the property is we're retrieving
541
-     * @throws \EE_Error
542
-     */
543
-    protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
544
-    {
545
-        //verify the field exists
546
-        $this->get_model()->field_settings_for($fieldname);
547
-        $cache_type = $pretty ? 'pretty' : 'standard';
548
-        $cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
549
-        if (isset($this->_cached_properties[$fieldname][$cache_type])) {
550
-            return $this->_cached_properties[$fieldname][$cache_type];
551
-        }
552
-        $field_obj = $this->get_model()->field_settings_for($fieldname);
553
-        if ($field_obj instanceof EE_Model_Field_Base) {
554
-            // If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
555
-            if ($field_obj instanceof EE_Datetime_Field) {
556
-                $this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
557
-            }
558
-            if ( ! isset($this->_fields[$fieldname])) {
559
-                $this->_fields[$fieldname] = null;
560
-            }
561
-            $value = $pretty
562
-                ? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
563
-                : $field_obj->prepare_for_get($this->_fields[$fieldname]);
564
-            $this->_set_cached_property($fieldname, $value, $cache_type);
565
-            return $value;
566
-        }
567
-        return null;
568
-    }
569
-
570
-
571
-
572
-    /**
573
-     * set timezone, formats, and output for EE_Datetime_Field objects
574
-     *
575
-     * @param \EE_Datetime_Field $datetime_field
576
-     * @param bool               $pretty
577
-     * @param null $date_or_time
578
-     * @return void
579
-     * @throws \EE_Error
580
-     */
581
-    protected function _prepare_datetime_field(
582
-        EE_Datetime_Field $datetime_field,
583
-        $pretty = false,
584
-        $date_or_time = null
585
-    ) {
586
-        $datetime_field->set_timezone($this->_timezone);
587
-        $datetime_field->set_date_format($this->_dt_frmt, $pretty);
588
-        $datetime_field->set_time_format($this->_tm_frmt, $pretty);
589
-        //set the output returned
590
-        switch ($date_or_time) {
591
-            case 'D' :
592
-                $datetime_field->set_date_time_output('date');
593
-                break;
594
-            case 'T' :
595
-                $datetime_field->set_date_time_output('time');
596
-                break;
597
-            default :
598
-                $datetime_field->set_date_time_output();
599
-        }
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * This just takes care of clearing out the cached_properties
606
-     *
607
-     * @return void
608
-     */
609
-    protected function _clear_cached_properties()
610
-    {
611
-        $this->_cached_properties = array();
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     * This just clears out ONE property if it exists in the cache
618
-     *
619
-     * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
620
-     * @return void
621
-     */
622
-    protected function _clear_cached_property($property_name)
623
-    {
624
-        if (isset($this->_cached_properties[$property_name])) {
625
-            unset($this->_cached_properties[$property_name]);
626
-        }
627
-    }
628
-
629
-
630
-
631
-    /**
632
-     * Ensures that this related thing is a model object.
633
-     *
634
-     * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
635
-     * @param string $model_name   name of the related thing, eg 'Attendee',
636
-     * @return EE_Base_Class
637
-     * @throws \EE_Error
638
-     */
639
-    protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
640
-    {
641
-        $other_model_instance = self::_get_model_instance_with_name(
642
-            self::_get_model_classname($model_name),
643
-            $this->_timezone
644
-        );
645
-        return $other_model_instance->ensure_is_obj($object_or_id);
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * Forgets the cached model of the given relation Name. So the next time we request it,
652
-     * we will fetch it again from the database. (Handy if you know it's changed somehow).
653
-     * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
654
-     * then only remove that one object from our cached array. Otherwise, clear the entire list
655
-     *
656
-     * @param string $relationName                         one of the keys in the _model_relations array on the model. Eg 'Registration'
657
-     * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
658
-     *                                                     if you intend to use $clear_all = TRUE, or the relation only has 1 object anyways (ie, it's a BelongsToRelation)
659
-     * @param bool   $clear_all                            This flags clearing the entire cache relation property if this is HasMany or HABTM.
660
-     * @throws EE_Error
661
-     * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a relation from all
662
-     */
663
-    public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
664
-    {
665
-        $relationship_to_model = $this->get_model()->related_settings_for($relationName);
666
-        $index_in_cache = '';
667
-        if ( ! $relationship_to_model) {
668
-            throw new EE_Error(
669
-                sprintf(
670
-                    __("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
671
-                    $relationName,
672
-                    get_class($this)
673
-                )
674
-            );
675
-        }
676
-        if ($clear_all) {
677
-            $obj_removed = true;
678
-            $this->_model_relations[$relationName] = null;
679
-        } elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
680
-            $obj_removed = $this->_model_relations[$relationName];
681
-            $this->_model_relations[$relationName] = null;
682
-        } else {
683
-            if ($object_to_remove_or_index_into_array instanceof EE_Base_Class && $object_to_remove_or_index_into_array->ID()) {
684
-                $index_in_cache = $object_to_remove_or_index_into_array->ID();
685
-                if (is_array($this->_model_relations[$relationName]) && ! isset($this->_model_relations[$relationName][$index_in_cache])) {
686
-                    $index_found_at = null;
687
-                    //find this object in the array even though it has a different key
688
-                    foreach ($this->_model_relations[$relationName] as $index => $obj) {
689
-                        if (
690
-                            $obj instanceof EE_Base_Class
691
-                            && (
692
-                                $obj == $object_to_remove_or_index_into_array
693
-                                || $obj->ID() === $object_to_remove_or_index_into_array->ID()
694
-                            )
695
-                        ) {
696
-                            $index_found_at = $index;
697
-                            break;
698
-                        }
699
-                    }
700
-                    if ($index_found_at) {
701
-                        $index_in_cache = $index_found_at;
702
-                    } else {
703
-                        //it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
704
-                        //if it wasn't in it to begin with. So we're done
705
-                        return $object_to_remove_or_index_into_array;
706
-                    }
707
-                }
708
-            } elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
709
-                //so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
710
-                foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
711
-                    if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
712
-                        $index_in_cache = $index;
713
-                    }
714
-                }
715
-            } else {
716
-                $index_in_cache = $object_to_remove_or_index_into_array;
717
-            }
718
-            //supposedly we've found it. But it could just be that the client code
719
-            //provided a bad index/object
720
-            if (
721
-            isset(
722
-                $this->_model_relations[$relationName],
723
-                $this->_model_relations[$relationName][$index_in_cache]
724
-            )
725
-            ) {
726
-                $obj_removed = $this->_model_relations[$relationName][$index_in_cache];
727
-                unset($this->_model_relations[$relationName][$index_in_cache]);
728
-            } else {
729
-                //that thing was never cached anyways.
730
-                $obj_removed = null;
731
-            }
732
-        }
733
-        return $obj_removed;
734
-    }
735
-
736
-
737
-
738
-    /**
739
-     * update_cache_after_object_save
740
-     * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has obtained after being saved to the db
741
-     *
742
-     * @param string         $relationName       - the type of object that is cached
743
-     * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
744
-     * @param string         $current_cache_id   - the ID that was used when originally caching the object
745
-     * @return boolean TRUE on success, FALSE on fail
746
-     * @throws \EE_Error
747
-     */
748
-    public function update_cache_after_object_save($relationName, EE_Base_Class $newly_saved_object, $current_cache_id = '')
749
-    {
750
-        // verify that incoming object is of the correct type
751
-        $obj_class = 'EE_' . $relationName;
752
-        if ($newly_saved_object instanceof $obj_class) {
753
-            /* @type EE_Base_Class $newly_saved_object */
754
-            // now get the type of relation
755
-            $relationship_to_model = $this->get_model()->related_settings_for($relationName);
756
-            // if this is a 1:1 relationship
757
-            if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
758
-                // then just replace the cached object with the newly saved object
759
-                $this->_model_relations[$relationName] = $newly_saved_object;
760
-                return true;
761
-                // or if it's some kind of sordid feral polyamorous relationship...
762
-            } elseif (is_array($this->_model_relations[$relationName]) && isset($this->_model_relations[$relationName][$current_cache_id])) {
763
-                // then remove the current cached item
764
-                unset($this->_model_relations[$relationName][$current_cache_id]);
765
-                // and cache the newly saved object using it's new ID
766
-                $this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
767
-                return true;
768
-            }
769
-        }
770
-        return false;
771
-    }
772
-
773
-
774
-
775
-    /**
776
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
777
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
778
-     *
779
-     * @param string $relationName
780
-     * @return EE_Base_Class
781
-     */
782
-    public function get_one_from_cache($relationName)
783
-    {
784
-        $cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : null;
785
-        if (is_array($cached_array_or_object)) {
786
-            return array_shift($cached_array_or_object);
787
-        } else {
788
-            return $cached_array_or_object;
789
-        }
790
-    }
791
-
792
-
793
-
794
-    /**
795
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
796
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
797
-     *
798
-     * @param string $relationName
799
-     * @throws \EE_Error
800
-     * @return EE_Base_Class[] NOT necessarily indexed by primary keys
801
-     */
802
-    public function get_all_from_cache($relationName)
803
-    {
804
-        $objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
805
-        // if the result is not an array, but exists, make it an array
806
-        $objects = is_array($objects) ? $objects : array($objects);
807
-        //bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
808
-        //basically, if this model object was stored in the session, and these cached model objects
809
-        //already have IDs, let's make sure they're in their model's entity mapper
810
-        //otherwise we will have duplicates next time we call
811
-        // EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
812
-        $model = EE_Registry::instance()->load_model($relationName);
813
-        foreach ($objects as $model_object) {
814
-            if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
815
-                //ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
816
-                if ($model_object->ID()) {
817
-                    $model->add_to_entity_map($model_object);
818
-                }
819
-            } else {
820
-                throw new EE_Error(
821
-                    sprintf(
822
-                        __(
823
-                            'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
824
-                            'event_espresso'
825
-                        ),
826
-                        $relationName,
827
-                        gettype($model_object)
828
-                    )
829
-                );
830
-            }
831
-        }
832
-        return $objects;
833
-    }
834
-
835
-
836
-
837
-    /**
838
-     * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
839
-     * matching the given query conditions.
840
-     *
841
-     * @param null  $field_to_order_by  What field is being used as the reference point.
842
-     * @param int   $limit              How many objects to return.
843
-     * @param array $query_params       Any additional conditions on the query.
844
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
845
-     *                                  you can indicate just the columns you want returned
846
-     * @return array|EE_Base_Class[]
847
-     * @throws \EE_Error
848
-     */
849
-    public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
850
-    {
851
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
852
-            ? $this->get_model()->get_primary_key_field()->get_name()
853
-            : $field_to_order_by;
854
-        $current_value = ! empty($field) ? $this->get($field) : null;
855
-        if (empty($field) || empty($current_value)) {
856
-            return array();
857
-        }
858
-        return $this->get_model()->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
859
-    }
860
-
861
-
862
-
863
-    /**
864
-     * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
865
-     * matching the given query conditions.
866
-     *
867
-     * @param null  $field_to_order_by  What field is being used as the reference point.
868
-     * @param int   $limit              How many objects to return.
869
-     * @param array $query_params       Any additional conditions on the query.
870
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
871
-     *                                  you can indicate just the columns you want returned
872
-     * @return array|EE_Base_Class[]
873
-     * @throws \EE_Error
874
-     */
875
-    public function previous_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
876
-    {
877
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
878
-            ? $this->get_model()->get_primary_key_field()->get_name()
879
-            : $field_to_order_by;
880
-        $current_value = ! empty($field) ? $this->get($field) : null;
881
-        if (empty($field) || empty($current_value)) {
882
-            return array();
883
-        }
884
-        return $this->get_model()->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
885
-    }
886
-
887
-
888
-
889
-    /**
890
-     * Returns the next EE_Base_Class object in sequence from this object as found in the database
891
-     * matching the given query conditions.
892
-     *
893
-     * @param null  $field_to_order_by  What field is being used as the reference point.
894
-     * @param array $query_params       Any additional conditions on the query.
895
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
896
-     *                                  you can indicate just the columns you want returned
897
-     * @return array|EE_Base_Class
898
-     * @throws \EE_Error
899
-     */
900
-    public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
901
-    {
902
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
903
-            ? $this->get_model()->get_primary_key_field()->get_name()
904
-            : $field_to_order_by;
905
-        $current_value = ! empty($field) ? $this->get($field) : null;
906
-        if (empty($field) || empty($current_value)) {
907
-            return array();
908
-        }
909
-        return $this->get_model()->next($current_value, $field, $query_params, $columns_to_select);
910
-    }
911
-
912
-
913
-
914
-    /**
915
-     * Returns the previous EE_Base_Class object in sequence from this object as found in the database
916
-     * matching the given query conditions.
917
-     *
918
-     * @param null  $field_to_order_by  What field is being used as the reference point.
919
-     * @param array $query_params       Any additional conditions on the query.
920
-     * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
921
-     *                                  you can indicate just the column you want returned
922
-     * @return array|EE_Base_Class
923
-     * @throws \EE_Error
924
-     */
925
-    public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
926
-    {
927
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
928
-            ? $this->get_model()->get_primary_key_field()->get_name()
929
-            : $field_to_order_by;
930
-        $current_value = ! empty($field) ? $this->get($field) : null;
931
-        if (empty($field) || empty($current_value)) {
932
-            return array();
933
-        }
934
-        return $this->get_model()->previous($current_value, $field, $query_params, $columns_to_select);
935
-    }
936
-
937
-
938
-
939
-    /**
940
-     * Overrides parent because parent expects old models.
941
-     * This also doesn't do any validation, and won't work for serialized arrays
942
-     *
943
-     * @param string $field_name
944
-     * @param mixed  $field_value_from_db
945
-     * @throws \EE_Error
946
-     */
947
-    public function set_from_db($field_name, $field_value_from_db)
948
-    {
949
-        $field_obj = $this->get_model()->field_settings_for($field_name);
950
-        if ($field_obj instanceof EE_Model_Field_Base) {
951
-            //you would think the DB has no NULLs for non-null label fields right? wrong!
952
-            //eg, a CPT model object could have an entry in the posts table, but no
953
-            //entry in the meta table. Meaning that all its columns in the meta table
954
-            //are null! yikes! so when we find one like that, use defaults for its meta columns
955
-            if ($field_value_from_db === null) {
956
-                if ($field_obj->is_nullable()) {
957
-                    //if the field allows nulls, then let it be null
958
-                    $field_value = null;
959
-                } else {
960
-                    $field_value = $field_obj->get_default_value();
961
-                }
962
-            } else {
963
-                $field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
964
-            }
965
-            $this->_fields[$field_name] = $field_value;
966
-            $this->_clear_cached_property($field_name);
967
-        }
968
-    }
969
-
970
-
971
-
972
-    /**
973
-     * verifies that the specified field is of the correct type
974
-     *
975
-     * @param string $field_name
976
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
977
-     *                                (in cases where the same property may be used for different outputs
978
-     *                                - i.e. datetime, money etc.)
979
-     * @return mixed
980
-     * @throws \EE_Error
981
-     */
982
-    public function get($field_name, $extra_cache_ref = null)
983
-    {
984
-        return $this->_get_cached_property($field_name, false, $extra_cache_ref);
985
-    }
986
-
987
-
988
-
989
-    /**
990
-     * This method simply returns the RAW unprocessed value for the given property in this class
991
-     *
992
-     * @param  string $field_name A valid fieldname
993
-     * @return mixed              Whatever the raw value stored on the property is.
994
-     * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
995
-     */
996
-    public function get_raw($field_name)
997
-    {
998
-        $field_settings = $this->get_model()->field_settings_for($field_name);
999
-        return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1000
-            ? $this->_fields[$field_name]->format('U')
1001
-            : $this->_fields[$field_name];
1002
-    }
1003
-
1004
-
1005
-
1006
-    /**
1007
-     * This is used to return the internal DateTime object used for a field that is a
1008
-     * EE_Datetime_Field.
1009
-     *
1010
-     * @param string $field_name               The field name retrieving the DateTime object.
1011
-     * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1012
-     * @throws \EE_Error
1013
-     *                                         an error is set and false returned.  If the field IS an
1014
-     *                                         EE_Datetime_Field and but the field value is null, then
1015
-     *                                         just null is returned (because that indicates that likely
1016
-     *                                         this field is nullable).
1017
-     */
1018
-    public function get_DateTime_object($field_name)
1019
-    {
1020
-        $field_settings = $this->get_model()->field_settings_for($field_name);
1021
-        if ( ! $field_settings instanceof EE_Datetime_Field) {
1022
-            EE_Error::add_error(
1023
-                sprintf(
1024
-                    __(
1025
-                        'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1026
-                        'event_espresso'
1027
-                    ),
1028
-                    $field_name
1029
-                ),
1030
-                __FILE__,
1031
-                __FUNCTION__,
1032
-                __LINE__
1033
-            );
1034
-            return false;
1035
-        }
1036
-        return $this->_fields[$field_name];
1037
-    }
1038
-
1039
-
1040
-
1041
-    /**
1042
-     * To be used in template to immediately echo out the value, and format it for output.
1043
-     * Eg, should call stripslashes and whatnot before echoing
1044
-     *
1045
-     * @param string $field_name      the name of the field as it appears in the DB
1046
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1047
-     *                                (in cases where the same property may be used for different outputs
1048
-     *                                - i.e. datetime, money etc.)
1049
-     * @return void
1050
-     * @throws \EE_Error
1051
-     */
1052
-    public function e($field_name, $extra_cache_ref = null)
1053
-    {
1054
-        echo $this->get_pretty($field_name, $extra_cache_ref);
1055
-    }
1056
-
1057
-
1058
-
1059
-    /**
1060
-     * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1061
-     * can be easily used as the value of form input.
1062
-     *
1063
-     * @param string $field_name
1064
-     * @return void
1065
-     * @throws \EE_Error
1066
-     */
1067
-    public function f($field_name)
1068
-    {
1069
-        $this->e($field_name, 'form_input');
1070
-    }
1071
-
1072
-
1073
-
1074
-    /**
1075
-     * @param string $field_name
1076
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1077
-     *                                (in cases where the same property may be used for different outputs
1078
-     *                                - i.e. datetime, money etc.)
1079
-     * @return mixed
1080
-     * @throws \EE_Error
1081
-     */
1082
-    public function get_pretty($field_name, $extra_cache_ref = null)
1083
-    {
1084
-        return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1085
-    }
1086
-
1087
-
1088
-
1089
-    /**
1090
-     * This simply returns the datetime for the given field name
1091
-     * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1092
-     * (and the equivalent e_date, e_time, e_datetime).
1093
-     *
1094
-     * @access   protected
1095
-     * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1096
-     * @param string   $dt_frmt      valid datetime format used for date
1097
-     *                               (if '' then we just use the default on the field,
1098
-     *                               if NULL we use the last-used format)
1099
-     * @param string   $tm_frmt      Same as above except this is for time format
1100
-     * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1101
-     * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1102
-     * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1103
-     *                               if field is not a valid dtt field, or void if echoing
1104
-     * @throws \EE_Error
1105
-     */
1106
-    protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1107
-    {
1108
-        // clear cached property
1109
-        $this->_clear_cached_property($field_name);
1110
-        //reset format properties because they are used in get()
1111
-        $this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1112
-        $this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1113
-        if ($echo) {
1114
-            $this->e($field_name, $date_or_time);
1115
-            return '';
1116
-        }
1117
-        return $this->get($field_name, $date_or_time);
1118
-    }
1119
-
1120
-
1121
-
1122
-    /**
1123
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other echoes
1124
-     * the pretty value for dtt)
1125
-     *
1126
-     * @param  string $field_name name of model object datetime field holding the value
1127
-     * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1128
-     * @return string            datetime value formatted
1129
-     * @throws \EE_Error
1130
-     */
1131
-    public function get_date($field_name, $format = '')
1132
-    {
1133
-        return $this->_get_datetime($field_name, $format, null, 'D');
1134
-    }
1135
-
1136
-
1137
-
1138
-    /**
1139
-     * @param      $field_name
1140
-     * @param string $format
1141
-     * @throws \EE_Error
1142
-     */
1143
-    public function e_date($field_name, $format = '')
1144
-    {
1145
-        $this->_get_datetime($field_name, $format, null, 'D', true);
1146
-    }
1147
-
1148
-
1149
-
1150
-    /**
1151
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other echoes
1152
-     * the pretty value for dtt)
1153
-     *
1154
-     * @param  string $field_name name of model object datetime field holding the value
1155
-     * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1156
-     * @return string             datetime value formatted
1157
-     * @throws \EE_Error
1158
-     */
1159
-    public function get_time($field_name, $format = '')
1160
-    {
1161
-        return $this->_get_datetime($field_name, null, $format, 'T');
1162
-    }
1163
-
1164
-
1165
-
1166
-    /**
1167
-     * @param      $field_name
1168
-     * @param string $format
1169
-     * @throws \EE_Error
1170
-     */
1171
-    public function e_time($field_name, $format = '')
1172
-    {
1173
-        $this->_get_datetime($field_name, null, $format, 'T', true);
1174
-    }
1175
-
1176
-
1177
-
1178
-    /**
1179
-     * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other
1180
-     * echoes the pretty value for dtt)
1181
-     *
1182
-     * @param  string $field_name name of model object datetime field holding the value
1183
-     * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1184
-     * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1185
-     * @return string             datetime value formatted
1186
-     * @throws \EE_Error
1187
-     */
1188
-    public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1189
-    {
1190
-        return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1191
-    }
1192
-
1193
-
1194
-
1195
-    /**
1196
-     * @param string $field_name
1197
-     * @param string $dt_frmt
1198
-     * @param string $tm_frmt
1199
-     * @throws \EE_Error
1200
-     */
1201
-    public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1202
-    {
1203
-        $this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1204
-    }
1205
-
1206
-
1207
-
1208
-    /**
1209
-     * Get the i8ln value for a date using the WordPress @see date_i18n function.
1210
-     *
1211
-     * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1212
-     * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format on the object will be used.
1213
-     * @return string Date and time string in set locale or false if no field exists for the given
1214
-     * @throws \EE_Error
1215
-     *                           field name.
1216
-     */
1217
-    public function get_i18n_datetime($field_name, $format = '')
1218
-    {
1219
-        $format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1220
-        return date_i18n(
1221
-            $format,
1222
-            EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1223
-        );
1224
-    }
1225
-
1226
-
1227
-
1228
-    /**
1229
-     * This method validates whether the given field name is a valid field on the model object as well as it is of a type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is thrown.
1230
-     *
1231
-     * @param  string $field_name The field name being checked
1232
-     * @throws EE_Error
1233
-     * @return EE_Datetime_Field
1234
-     */
1235
-    protected function _get_dtt_field_settings($field_name)
1236
-    {
1237
-        $field = $this->get_model()->field_settings_for($field_name);
1238
-        //check if field is dtt
1239
-        if ($field instanceof EE_Datetime_Field) {
1240
-            return $field;
1241
-        } else {
1242
-            throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1243
-                'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1244
-        }
1245
-    }
1246
-
1247
-
1248
-
1249
-
1250
-    /**
1251
-     * NOTE ABOUT BELOW:
1252
-     * These convenience date and time setters are for setting date and time independently.  In other words you might want to change the time on a datetime_field but leave the date the same (or vice versa).
1253
-     * IF on the other hand you want to set both date and time at the same time, you can just use the models default set($fieldname,$value) method and make sure you send the entire datetime value for setting.
1254
-     */
1255
-    /**
1256
-     * sets the time on a datetime property
1257
-     *
1258
-     * @access protected
1259
-     * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1260
-     * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1261
-     * @throws \EE_Error
1262
-     */
1263
-    protected function _set_time_for($time, $fieldname)
1264
-    {
1265
-        $this->_set_date_time('T', $time, $fieldname);
1266
-    }
1267
-
1268
-
1269
-
1270
-    /**
1271
-     * sets the date on a datetime property
1272
-     *
1273
-     * @access protected
1274
-     * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1275
-     * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1276
-     * @throws \EE_Error
1277
-     */
1278
-    protected function _set_date_for($date, $fieldname)
1279
-    {
1280
-        $this->_set_date_time('D', $date, $fieldname);
1281
-    }
1282
-
1283
-
1284
-
1285
-    /**
1286
-     * This takes care of setting a date or time independently on a given model object property. This method also verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1287
-     *
1288
-     * @access protected
1289
-     * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1290
-     * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1291
-     * @param string          $fieldname      the name of the field the date OR time is being set on (must match a EE_Datetime_Field property)
1292
-     * @throws \EE_Error
1293
-     */
1294
-    protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1295
-    {
1296
-        $field = $this->_get_dtt_field_settings($fieldname);
1297
-        $field->set_timezone($this->_timezone);
1298
-        $field->set_date_format($this->_dt_frmt);
1299
-        $field->set_time_format($this->_tm_frmt);
1300
-        switch ($what) {
1301
-            case 'T' :
1302
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1303
-                    $datetime_value,
1304
-                    $this->_fields[$fieldname]
1305
-                );
1306
-                break;
1307
-            case 'D' :
1308
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1309
-                    $datetime_value,
1310
-                    $this->_fields[$fieldname]
1311
-                );
1312
-                break;
1313
-            case 'B' :
1314
-                $this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1315
-                break;
1316
-        }
1317
-        $this->_clear_cached_property($fieldname);
1318
-    }
1319
-
1320
-
1321
-
1322
-    /**
1323
-     * This will return a timestamp for the website timezone but ONLY when the current website timezone is different than the timezone set for the website.
1324
-     * NOTE, this currently only works well with methods that return values.  If you use it with methods that echo values the $_timestamp property may not get reset to its original value and that could lead to some unexpected results!
1325
-     *
1326
-     * @access public
1327
-     * @param string               $field_name This is the name of the field on the object that contains the date/time value being returned.
1328
-     * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1329
-     * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1330
-     * @param string               $prepend    You can include something to prepend on the timestamp
1331
-     * @param string               $append     You can include something to append on the timestamp
1332
-     * @throws EE_Error
1333
-     * @return string timestamp
1334
-     */
1335
-    public function display_in_my_timezone($field_name, $callback = 'get_datetime', $args = null, $prepend = '', $append = '')
1336
-    {
1337
-        $timezone = EEH_DTT_Helper::get_timezone();
1338
-        if ($timezone === $this->_timezone) {
1339
-            return '';
1340
-        }
1341
-        $original_timezone = $this->_timezone;
1342
-        $this->set_timezone($timezone);
1343
-        $fn = (array)$field_name;
1344
-        $args = array_merge($fn, (array)$args);
1345
-        if ( ! method_exists($this, $callback)) {
1346
-            throw new EE_Error(
1347
-                sprintf(
1348
-                    __(
1349
-                        'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1350
-                        'event_espresso'
1351
-                    ),
1352
-                    $callback
1353
-                )
1354
-            );
1355
-        }
1356
-        $args = (array)$args;
1357
-        $return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1358
-        $this->set_timezone($original_timezone);
1359
-        return $return;
1360
-    }
1361
-
1362
-
1363
-
1364
-    /**
1365
-     * Deletes this model object.
1366
-     * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should override
1367
-     * `EE_Base_Class::_delete` NOT this class.
1368
-     *
1369
-     * @return boolean | int
1370
-     * @throws \EE_Error
1371
-     */
1372
-    public function delete()
1373
-    {
1374
-        /**
1375
-         * Called just before the `EE_Base_Class::_delete` method call.
1376
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1377
-         * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1378
-         * soft deletes (trash) the object and does not permanently delete it.
1379
-         *
1380
-         * @param EE_Base_Class $model_object about to be 'deleted'
1381
-         */
1382
-        do_action('AHEE__EE_Base_Class__delete__before', $this);
1383
-        $result = $this->_delete();
1384
-        /**
1385
-         * Called just after the `EE_Base_Class::_delete` method call.
1386
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1387
-         * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1388
-         * soft deletes (trash) the object and does not permanently delete it.
1389
-         *
1390
-         * @param EE_Base_Class $model_object that was just 'deleted'
1391
-         * @param boolean       $result
1392
-         */
1393
-        do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1394
-        return $result;
1395
-    }
1396
-
1397
-
1398
-
1399
-    /**
1400
-     * Calls the specific delete method for the instantiated class.
1401
-     * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override default
1402
-     * functionality for "delete" (which is to call `permanently_delete`) should override this method NOT `EE_Base_Class::delete`
1403
-     *
1404
-     * @return bool|int
1405
-     * @throws \EE_Error
1406
-     */
1407
-    protected function _delete()
1408
-    {
1409
-        return $this->delete_permanently();
1410
-    }
1411
-
1412
-
1413
-
1414
-    /**
1415
-     * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an error)
1416
-     *
1417
-     * @return bool | int
1418
-     * @throws \EE_Error
1419
-     */
1420
-    public function delete_permanently()
1421
-    {
1422
-        /**
1423
-         * Called just before HARD deleting a model object
1424
-         *
1425
-         * @param EE_Base_Class $model_object about to be 'deleted'
1426
-         */
1427
-        do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1428
-        $model = $this->get_model();
1429
-        $result = $model->delete_permanently_by_ID($this->ID());
1430
-        $this->refresh_cache_of_related_objects();
1431
-        /**
1432
-         * Called just after HARD deleting a model object
1433
-         *
1434
-         * @param EE_Base_Class $model_object that was just 'deleted'
1435
-         * @param boolean       $result
1436
-         */
1437
-        do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1438
-        return $result;
1439
-    }
1440
-
1441
-
1442
-
1443
-    /**
1444
-     * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1445
-     * related model objects
1446
-     *
1447
-     * @throws \EE_Error
1448
-     */
1449
-    public function refresh_cache_of_related_objects()
1450
-    {
1451
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1452
-            if ( ! empty($this->_model_relations[$relation_name])) {
1453
-                $related_objects = $this->_model_relations[$relation_name];
1454
-                if ($relation_obj instanceof EE_Belongs_To_Relation) {
1455
-                    //this relation only stores a single model object, not an array
1456
-                    //but let's make it consistent
1457
-                    $related_objects = array($related_objects);
1458
-                }
1459
-                foreach ($related_objects as $related_object) {
1460
-                    //only refresh their cache if they're in memory
1461
-                    if ($related_object instanceof EE_Base_Class) {
1462
-                        $related_object->clear_cache($this->get_model()->get_this_model_name(), $this);
1463
-                    }
1464
-                }
1465
-            }
1466
-        }
1467
-    }
1468
-
1469
-
1470
-
1471
-    /**
1472
-     *        Saves this object to the database. An array may be supplied to set some values on this
1473
-     * object just before saving.
1474
-     *
1475
-     * @access public
1476
-     * @param array $set_cols_n_values keys are field names, values are their new values,
1477
-     *                                 if provided during the save() method (often client code will change the fields' values before calling save)
1478
-     * @throws \EE_Error
1479
-     * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1480
-     *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1481
-     */
1482
-    public function save($set_cols_n_values = array())
1483
-    {
1484
-        /**
1485
-         * Filters the fields we're about to save on the model object
1486
-         *
1487
-         * @param array         $set_cols_n_values
1488
-         * @param EE_Base_Class $model_object
1489
-         */
1490
-        $set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values, $this);
1491
-        //set attributes as provided in $set_cols_n_values
1492
-        foreach ($set_cols_n_values as $column => $value) {
1493
-            $this->set($column, $value);
1494
-        }
1495
-        /**
1496
-         * Saving a model object.
1497
-         * Before we perform a save, this action is fired.
1498
-         *
1499
-         * @param EE_Base_Class $model_object the model object about to be saved.
1500
-         */
1501
-        do_action('AHEE__EE_Base_Class__save__begin', $this);
1502
-        if ( ! $this->allow_persist()) {
1503
-            return 0;
1504
-        }
1505
-        //now get current attribute values
1506
-        $save_cols_n_values = $this->_fields;
1507
-        //if the object already has an ID, update it. Otherwise, insert it
1508
-        //also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1509
-        $old_assumption_concerning_value_preparation = $this->get_model()->get_assumption_concerning_values_already_prepared_by_model_object();
1510
-        $this->get_model()->assume_values_already_prepared_by_model_object(true);
1511
-        //does this model have an autoincrement PK?
1512
-        if ($this->get_model()->has_primary_key_field()) {
1513
-            if ($this->get_model()->get_primary_key_field()->is_auto_increment()) {
1514
-                //ok check if it's set, if so: update; if not, insert
1515
-                if ( ! empty($save_cols_n_values[self::_get_primary_key_name(get_class($this))])) {
1516
-                    $results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1517
-                } else {
1518
-                    unset($save_cols_n_values[self::_get_primary_key_name(get_class($this))]);
1519
-                    $results = $this->get_model()->insert($save_cols_n_values);
1520
-                    if ($results) {
1521
-                        //if successful, set the primary key
1522
-                        //but don't use the normal SET method, because it will check if
1523
-                        //an item with the same ID exists in the mapper & db, then
1524
-                        //will find it in the db (because we just added it) and THAT object
1525
-                        //will get added to the mapper before we can add this one!
1526
-                        //but if we just avoid using the SET method, all that headache can be avoided
1527
-                        $pk_field_name = self::_get_primary_key_name(get_class($this));
1528
-                        $this->_fields[$pk_field_name] = $results;
1529
-                        $this->_clear_cached_property($pk_field_name);
1530
-                        $this->get_model()->add_to_entity_map($this);
1531
-                        $this->_update_cached_related_model_objs_fks();
1532
-                    }
1533
-                }
1534
-            } else {//PK is NOT auto-increment
1535
-                //so check if one like it already exists in the db
1536
-                if ($this->get_model()->exists_by_ID($this->ID())) {
1537
-                    if (WP_DEBUG && ! $this->in_entity_map()) {
1538
-                        throw new EE_Error(
1539
-                            sprintf(
1540
-                                __('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1541
-                                    'event_espresso'),
1542
-                                get_class($this),
1543
-                                get_class($this->get_model()) . '::instance()->add_to_entity_map()',
1544
-                                get_class($this->get_model()) . '::instance()->get_one_by_ID()',
1545
-                                '<br />'
1546
-                            )
1547
-                        );
1548
-                    }
1549
-                    $results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1550
-                } else {
1551
-                    $results = $this->get_model()->insert($save_cols_n_values);
1552
-                    $this->_update_cached_related_model_objs_fks();
1553
-                }
1554
-            }
1555
-        } else {//there is NO primary key
1556
-            $already_in_db = false;
1557
-            foreach ($this->get_model()->unique_indexes() as $index) {
1558
-                $uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1559
-                if ($this->get_model()->exists(array($uniqueness_where_params))) {
1560
-                    $already_in_db = true;
1561
-                }
1562
-            }
1563
-            if ($already_in_db) {
1564
-                $combined_pk_fields_n_values = array_intersect_key($save_cols_n_values, $this->get_model()->get_combined_primary_key_fields());
1565
-                $results = $this->get_model()->update($save_cols_n_values, $combined_pk_fields_n_values);
1566
-            } else {
1567
-                $results = $this->get_model()->insert($save_cols_n_values);
1568
-            }
1569
-        }
1570
-        //restore the old assumption about values being prepared by the model object
1571
-        $this->get_model()->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1572
-        /**
1573
-         * After saving the model object this action is called
1574
-         *
1575
-         * @param EE_Base_Class $model_object which was just saved
1576
-         * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1577
-         *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1578
-         */
1579
-        do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1580
-        return $results;
1581
-    }
1582
-
1583
-
1584
-
1585
-    /**
1586
-     * Updates the foreign key on related models objects pointing to this to have this model object's ID
1587
-     * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB is consistent)
1588
-     * Especially useful in case we JUST added this model object ot the database
1589
-     * and we want to let its cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on
1590
-     * the transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether or not they exist in the DB (if they do, their DB records will be automatically updated)
1591
-     *
1592
-     * @return void
1593
-     * @throws \EE_Error
1594
-     */
1595
-    protected function _update_cached_related_model_objs_fks()
1596
-    {
1597
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1598
-            if ($relation_obj instanceof EE_Has_Many_Relation) {
1599
-                foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1600
-                    $fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1601
-                        $this->get_model()->get_this_model_name()
1602
-                    );
1603
-                    $related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1604
-                    if ($related_model_obj_in_cache->ID()) {
1605
-                        $related_model_obj_in_cache->save();
1606
-                    }
1607
-                }
1608
-            }
1609
-        }
1610
-    }
1611
-
1612
-
1613
-
1614
-    /**
1615
-     * Saves this model object and its NEW cached relations to the database.
1616
-     * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1617
-     * In order for that to work, we would need to mark model objects as dirty/clean...
1618
-     * because otherwise, there's a potential for infinite looping of saving
1619
-     * Saves the cached related model objects, and ensures the relation between them
1620
-     * and this object and properly setup
1621
-     *
1622
-     * @return int ID of new model object on save; 0 on failure+
1623
-     * @throws \EE_Error
1624
-     */
1625
-    public function save_new_cached_related_model_objs()
1626
-    {
1627
-        //make sure this has been saved
1628
-        if ( ! $this->ID()) {
1629
-            $id = $this->save();
1630
-        } else {
1631
-            $id = $this->ID();
1632
-        }
1633
-        //now save all the NEW cached model objects  (ie they don't exist in the DB)
1634
-        foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1635
-            if ($this->_model_relations[$relationName]) {
1636
-                //is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1637
-                //or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1638
-                if ($relationObj instanceof EE_Belongs_To_Relation) {
1639
-                    //add a relation to that relation type (which saves the appropriate thing in the process)
1640
-                    //but ONLY if it DOES NOT exist in the DB
1641
-                    /* @var $related_model_obj EE_Base_Class */
1642
-                    $related_model_obj = $this->_model_relations[$relationName];
1643
-                    //					if( ! $related_model_obj->ID()){
1644
-                    $this->_add_relation_to($related_model_obj, $relationName);
1645
-                    $related_model_obj->save_new_cached_related_model_objs();
1646
-                    //					}
1647
-                } else {
1648
-                    foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1649
-                        //add a relation to that relation type (which saves the appropriate thing in the process)
1650
-                        //but ONLY if it DOES NOT exist in the DB
1651
-                        //						if( ! $related_model_obj->ID()){
1652
-                        $this->_add_relation_to($related_model_obj, $relationName);
1653
-                        $related_model_obj->save_new_cached_related_model_objs();
1654
-                        //						}
1655
-                    }
1656
-                }
1657
-            }
1658
-        }
1659
-        return $id;
1660
-    }
1661
-
1662
-
1663
-
1664
-    /**
1665
-     * for getting a model while instantiated.
1666
-     *
1667
-     * @return \EEM_Base | \EEM_CPT_Base
1668
-     */
1669
-    public function get_model()
1670
-    {
1671
-        $modelName = self::_get_model_classname(get_class($this));
1672
-        return self::_get_model_instance_with_name($modelName, $this->_timezone);
1673
-    }
1674
-
1675
-
1676
-
1677
-    /**
1678
-     * @param $props_n_values
1679
-     * @param $classname
1680
-     * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1681
-     * @throws \EE_Error
1682
-     */
1683
-    protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1684
-    {
1685
-        //TODO: will not work for Term_Relationships because they have no PK!
1686
-        $primary_id_ref = self::_get_primary_key_name($classname);
1687
-        if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1688
-            $id = $props_n_values[$primary_id_ref];
1689
-            return self::_get_model($classname)->get_from_entity_map($id);
1690
-        }
1691
-        return false;
1692
-    }
1693
-
1694
-
1695
-
1696
-    /**
1697
-     * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for the primary key (if present in incoming values).
1698
-     * If there is a key in the incoming array that matches the primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not we return false.
1699
-     *
1700
-     * @param  array  $props_n_values   incoming array of properties and their values
1701
-     * @param  string $classname        the classname of the child class
1702
-     * @param null    $timezone
1703
-     * @param array   $date_formats     incoming date_formats in an array where the first value is the
1704
-     *                                  date_format and the second value is the time format
1705
-     * @return mixed (EE_Base_Class|bool)
1706
-     * @throws \EE_Error
1707
-     */
1708
-    protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1709
-    {
1710
-        $existing = null;
1711
-        if (self::_get_model($classname)->has_primary_key_field()) {
1712
-            $primary_id_ref = self::_get_primary_key_name($classname);
1713
-            if (array_key_exists($primary_id_ref, $props_n_values)
1714
-                && ! empty($props_n_values[$primary_id_ref])
1715
-            ) {
1716
-                $existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1717
-                    $props_n_values[$primary_id_ref]
1718
-                );
1719
-            }
1720
-        } elseif (self::_get_model($classname, $timezone)->has_all_combined_primary_key_fields($props_n_values)) {
1721
-            //no primary key on this model, but there's still a matching item in the DB
1722
-            $existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1723
-                self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1724
-            );
1725
-        }
1726
-        if ($existing) {
1727
-            //set date formats if present before setting values
1728
-            if ( ! empty($date_formats) && is_array($date_formats)) {
1729
-                $existing->set_date_format($date_formats[0]);
1730
-                $existing->set_time_format($date_formats[1]);
1731
-            } else {
1732
-                //set default formats for date and time
1733
-                $existing->set_date_format(get_option('date_format'));
1734
-                $existing->set_time_format(get_option('time_format'));
1735
-            }
1736
-            foreach ($props_n_values as $property => $field_value) {
1737
-                $existing->set($property, $field_value);
1738
-            }
1739
-            return $existing;
1740
-        } else {
1741
-            return false;
1742
-        }
1743
-    }
1744
-
1745
-
1746
-
1747
-    /**
1748
-     * Gets the EEM_*_Model for this class
1749
-     *
1750
-     * @access public now, as this is more convenient
1751
-     * @param      $classname
1752
-     * @param null $timezone
1753
-     * @throws EE_Error
1754
-     * @return EEM_Base
1755
-     */
1756
-    protected static function _get_model($classname, $timezone = null)
1757
-    {
1758
-        //find model for this class
1759
-        if ( ! $classname) {
1760
-            throw new EE_Error(
1761
-                sprintf(
1762
-                    __(
1763
-                        "What were you thinking calling _get_model(%s)?? You need to specify the class name",
1764
-                        "event_espresso"
1765
-                    ),
1766
-                    $classname
1767
-                )
1768
-            );
1769
-        }
1770
-        $modelName = self::_get_model_classname($classname);
1771
-        return self::_get_model_instance_with_name($modelName, $timezone);
1772
-    }
1773
-
1774
-
1775
-
1776
-    /**
1777
-     * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1778
-     *
1779
-     * @param string $model_classname
1780
-     * @param null   $timezone
1781
-     * @return EEM_Base
1782
-     */
1783
-    protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1784
-    {
1785
-        $model_classname = str_replace('EEM_', '', $model_classname);
1786
-        $model = EE_Registry::instance()->load_model($model_classname);
1787
-        $model->set_timezone($timezone);
1788
-        return $model;
1789
-    }
1790
-
1791
-
1792
-
1793
-    /**
1794
-     * If a model name is provided (eg Registration), gets the model classname for that model.
1795
-     * Also works if a model class's classname is provided (eg EE_Registration).
1796
-     *
1797
-     * @param null $model_name
1798
-     * @return string like EEM_Attendee
1799
-     */
1800
-    private static function _get_model_classname($model_name = null)
1801
-    {
1802
-        if (strpos($model_name, "EE_") === 0) {
1803
-            $model_classname = str_replace("EE_", "EEM_", $model_name);
1804
-        } else {
1805
-            $model_classname = "EEM_" . $model_name;
1806
-        }
1807
-        return $model_classname;
1808
-    }
1809
-
1810
-
1811
-
1812
-    /**
1813
-     * returns the name of the primary key attribute
1814
-     *
1815
-     * @param null $classname
1816
-     * @throws EE_Error
1817
-     * @return string
1818
-     */
1819
-    protected static function _get_primary_key_name($classname = null)
1820
-    {
1821
-        if ( ! $classname) {
1822
-            throw new EE_Error(
1823
-                sprintf(
1824
-                    __("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1825
-                    $classname
1826
-                )
1827
-            );
1828
-        }
1829
-        return self::_get_model($classname)->get_primary_key_field()->get_name();
1830
-    }
1831
-
1832
-
1833
-
1834
-    /**
1835
-     * Gets the value of the primary key.
1836
-     * If the object hasn't yet been saved, it should be whatever the model field's default was
1837
-     * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value is.
1838
-     * Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1839
-     *
1840
-     * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1841
-     * @throws \EE_Error
1842
-     */
1843
-    public function ID()
1844
-    {
1845
-        //now that we know the name of the variable, use a variable variable to get its value and return its
1846
-        if ($this->get_model()->has_primary_key_field()) {
1847
-            return $this->_fields[self::_get_primary_key_name(get_class($this))];
1848
-        } else {
1849
-            return $this->get_model()->get_index_primary_key_string($this->_fields);
1850
-        }
1851
-    }
1852
-
1853
-
1854
-
1855
-    /**
1856
-     * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current model is related
1857
-     * to a group of events, the $relationName should be 'Event', and should be a key in the EE Model's $_model_relations array.
1858
-     * If this model object doesn't exist in the DB, just caches the related thing
1859
-     *
1860
-     * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1861
-     * @param string $relationName                     eg 'Events','Question',etc.
1862
-     *                                                 an attendee to a group, you also want to specify which role they will have in that group. So you would use this parameter to specify array('role-column-name'=>'role-id')
1863
-     * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that allow you to further constrict the relation to being added.  However, keep in mind that the columns (keys) given must match
1864
-     *                                                 a column on the JOIN table and currently only the HABTM models accept these additional conditions.  Also remember that if an exact match isn't found for these extra cols/val pairs,
1865
-     *                                                 then a NEW row is created in the join table.
1866
-     * @param null   $cache_id
1867
-     * @throws EE_Error
1868
-     * @return EE_Base_Class the object the relation was added to
1869
-     */
1870
-    public function _add_relation_to($otherObjectModelObjectOrID, $relationName, $extra_join_model_fields_n_values = array(), $cache_id = null)
1871
-    {
1872
-        //if this thing exists in the DB, save the relation to the DB
1873
-        if ($this->ID()) {
1874
-            $otherObject = $this->get_model()->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName, $extra_join_model_fields_n_values);
1875
-            //clear cache so future get_many_related and get_first_related() return new results.
1876
-            $this->clear_cache($relationName, $otherObject, true);
1877
-            if ($otherObject instanceof EE_Base_Class) {
1878
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1879
-            }
1880
-        } else {
1881
-            //this thing doesn't exist in the DB,  so just cache it
1882
-            if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
1883
-                throw new EE_Error(sprintf(
1884
-                    __('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s', 'event_espresso'),
1885
-                    $otherObjectModelObjectOrID,
1886
-                    get_class($this)
1887
-                ));
1888
-            } else {
1889
-                $otherObject = $otherObjectModelObjectOrID;
1890
-            }
1891
-            $this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
1892
-        }
1893
-        if ($otherObject instanceof EE_Base_Class) {
1894
-            //fix the reciprocal relation too
1895
-            if ($otherObject->ID()) {
1896
-                //its saved so assumed relations exist in the DB, so we can just
1897
-                //clear the cache so future queries use the updated info in the DB
1898
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), null, true);
1899
-            } else {
1900
-                //it's not saved, so it caches relations like this
1901
-                $otherObject->cache($this->get_model()->get_this_model_name(), $this);
1902
-            }
1903
-        }
1904
-        return $otherObject;
1905
-    }
1906
-
1907
-
1908
-
1909
-    /**
1910
-     * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current model is related
1911
-     * to a group of events, the $relationName should be 'Events', and should be a key in the EE Model's $_model_relations array.
1912
-     * If this model object doesn't exist in the DB, just removes the related thing from the cache
1913
-     *
1914
-     * @param mixed  $otherObjectModelObjectOrID
1915
-     *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved to the DB yet
1916
-     * @param string $relationName
1917
-     * @param array  $where_query
1918
-     *                You can optionally include an array of key=>value pairs that allow you to further constrict the relation to being added.
1919
-     *                However, keep in mind that the columns (keys) given must match a column on the JOIN table
1920
-     *                and currently only the HABTM models accept these additional conditions.
1921
-     *                Also remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is created in the join table.
1922
-     * @return EE_Base_Class the relation was removed from
1923
-     * @throws \EE_Error
1924
-     */
1925
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
1926
-    {
1927
-        if ($this->ID()) {
1928
-            //if this exists in the DB, save the relation change to the DB too
1929
-            $otherObject = $this->get_model()->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName, $where_query);
1930
-            $this->clear_cache($relationName, $otherObject);
1931
-        } else {
1932
-            //this doesn't exist in the DB, just remove it from the cache
1933
-            $otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
1934
-        }
1935
-        if ($otherObject instanceof EE_Base_Class) {
1936
-            $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1937
-        }
1938
-        return $otherObject;
1939
-    }
1940
-
1941
-
1942
-
1943
-    /**
1944
-     * Removes ALL the related things for the $relationName.
1945
-     *
1946
-     * @param string $relationName
1947
-     * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
1948
-     * @return EE_Base_Class
1949
-     * @throws \EE_Error
1950
-     */
1951
-    public function _remove_relations($relationName, $where_query_params = array())
1952
-    {
1953
-        if ($this->ID()) {
1954
-            //if this exists in the DB, save the relation change to the DB too
1955
-            $otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
1956
-            $this->clear_cache($relationName, null, true);
1957
-        } else {
1958
-            //this doesn't exist in the DB, just remove it from the cache
1959
-            $otherObjects = $this->clear_cache($relationName, null, true);
1960
-        }
1961
-        if (is_array($otherObjects)) {
1962
-            foreach ($otherObjects as $otherObject) {
1963
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1964
-            }
1965
-        }
1966
-        return $otherObjects;
1967
-    }
1968
-
1969
-
1970
-
1971
-    /**
1972
-     * Gets all the related model objects of the specified type. Eg, if the current class if
1973
-     * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
1974
-     * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
1975
-     * because we want to get even deleted items etc.
1976
-     *
1977
-     * @param string $relationName key in the model's _model_relations array
1978
-     * @param array  $query_params like EEM_Base::get_all
1979
-     * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
1980
-     * @throws \EE_Error
1981
-     *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if you want IDs
1982
-     */
1983
-    public function get_many_related($relationName, $query_params = array())
1984
-    {
1985
-        if ($this->ID()) {
1986
-            //this exists in the DB, so get the related things from either the cache or the DB
1987
-            //if there are query parameters, forget about caching the related model objects.
1988
-            if ($query_params) {
1989
-                $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
1990
-            } else {
1991
-                //did we already cache the result of this query?
1992
-                $cached_results = $this->get_all_from_cache($relationName);
1993
-                if ( ! $cached_results) {
1994
-                    $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
1995
-                    //if no query parameters were passed, then we got all the related model objects
1996
-                    //for that relation. We can cache them then.
1997
-                    foreach ($related_model_objects as $related_model_object) {
1998
-                        $this->cache($relationName, $related_model_object);
1999
-                    }
2000
-                } else {
2001
-                    $related_model_objects = $cached_results;
2002
-                }
2003
-            }
2004
-        } else {
2005
-            //this doesn't exist in the DB, so just get the related things from the cache
2006
-            $related_model_objects = $this->get_all_from_cache($relationName);
2007
-        }
2008
-        return $related_model_objects;
2009
-    }
2010
-
2011
-
2012
-
2013
-    /**
2014
-     * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2015
-     * unless otherwise specified in the $query_params
2016
-     *
2017
-     * @param string $relation_name  model_name like 'Event', or 'Registration'
2018
-     * @param array  $query_params   like EEM_Base::get_all's
2019
-     * @param string $field_to_count name of field to count by. By default, uses primary key
2020
-     * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
2021
-     * @return int
2022
-     */
2023
-    public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2024
-    {
2025
-        return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2026
-    }
2027
-
2028
-
2029
-
2030
-    /**
2031
-     * Instead of getting the related model objects, simply sums up the values of the specified field.
2032
-     * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2033
-     *
2034
-     * @param string $relation_name model_name like 'Event', or 'Registration'
2035
-     * @param array  $query_params  like EEM_Base::get_all's
2036
-     * @param string $field_to_sum  name of field to count by.
2037
-     *                              By default, uses primary key (which doesn't make much sense, so you should probably change it)
2038
-     * @return int
2039
-     */
2040
-    public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2041
-    {
2042
-        return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2043
-    }
2044
-
2045
-
2046
-
2047
-    /**
2048
-     * Gets the first (ie, one) related model object of the specified type.
2049
-     *
2050
-     * @param string $relationName key in the model's _model_relations array
2051
-     * @param array  $query_params like EEM_Base::get_all
2052
-     * @return EE_Base_Class (not an array, a single object)
2053
-     * @throws \EE_Error
2054
-     */
2055
-    public function get_first_related($relationName, $query_params = array())
2056
-    {
2057
-        if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2058
-            //if they've provided some query parameters, don't bother trying to cache the result
2059
-            //also make sure we're not caching the result of get_first_related
2060
-            //on a relation which should have an array of objects (because the cache might have an array of objects)
2061
-            if ($query_params || ! $this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2062
-                $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2063
-            } else {
2064
-                //first, check if we've already cached the result of this query
2065
-                $cached_result = $this->get_one_from_cache($relationName);
2066
-                if ( ! $cached_result) {
2067
-                    $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2068
-                    $this->cache($relationName, $related_model_object);
2069
-                } else {
2070
-                    $related_model_object = $cached_result;
2071
-                }
2072
-            }
2073
-        } else {
2074
-            $related_model_object = null;
2075
-            //this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2076
-            if ($this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2077
-                $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2078
-            }
2079
-            //this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2080
-            if ( ! $related_model_object) {
2081
-                $related_model_object = $this->get_one_from_cache($relationName);
2082
-            }
2083
-        }
2084
-        return $related_model_object;
2085
-    }
2086
-
2087
-
2088
-
2089
-    /**
2090
-     * Does a delete on all related objects of type $relationName and removes
2091
-     * the current model object's relation to them. If they can't be deleted (because
2092
-     * of blocking related model objects) does nothing. If the related model objects are
2093
-     * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2094
-     * If this model object doesn't exist yet in the DB, just removes its related things
2095
-     *
2096
-     * @param string $relationName
2097
-     * @param array  $query_params like EEM_Base::get_all's
2098
-     * @return int how many deleted
2099
-     * @throws \EE_Error
2100
-     */
2101
-    public function delete_related($relationName, $query_params = array())
2102
-    {
2103
-        if ($this->ID()) {
2104
-            $count = $this->get_model()->delete_related($this, $relationName, $query_params);
2105
-        } else {
2106
-            $count = count($this->get_all_from_cache($relationName));
2107
-            $this->clear_cache($relationName, null, true);
2108
-        }
2109
-        return $count;
2110
-    }
2111
-
2112
-
2113
-
2114
-    /**
2115
-     * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2116
-     * the current model object's relation to them. If they can't be deleted (because
2117
-     * of blocking related model objects) just does a soft delete on it instead, if possible.
2118
-     * If the related thing isn't a soft-deletable model object, this function is identical
2119
-     * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2120
-     *
2121
-     * @param string $relationName
2122
-     * @param array  $query_params like EEM_Base::get_all's
2123
-     * @return int how many deleted (including those soft deleted)
2124
-     * @throws \EE_Error
2125
-     */
2126
-    public function delete_related_permanently($relationName, $query_params = array())
2127
-    {
2128
-        if ($this->ID()) {
2129
-            $count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2130
-        } else {
2131
-            $count = count($this->get_all_from_cache($relationName));
2132
-        }
2133
-        $this->clear_cache($relationName, null, true);
2134
-        return $count;
2135
-    }
2136
-
2137
-
2138
-
2139
-    /**
2140
-     * is_set
2141
-     * Just a simple utility function children can use for checking if property exists
2142
-     *
2143
-     * @access  public
2144
-     * @param  string $field_name property to check
2145
-     * @return bool                              TRUE if existing,FALSE if not.
2146
-     */
2147
-    public function is_set($field_name)
2148
-    {
2149
-        return isset($this->_fields[$field_name]);
2150
-    }
2151
-
2152
-
2153
-
2154
-    /**
2155
-     * Just a simple utility function children can use for checking if property (or properties) exists and throwing an EE_Error exception if they don't
2156
-     *
2157
-     * @param  mixed (string|array) $properties properties to check
2158
-     * @throws EE_Error
2159
-     * @return bool                              TRUE if existing, throw EE_Error if not.
2160
-     */
2161
-    protected function _property_exists($properties)
2162
-    {
2163
-        foreach ((array)$properties as $property_name) {
2164
-            //first make sure this property exists
2165
-            if ( ! $this->_fields[$property_name]) {
2166
-                throw new EE_Error(
2167
-                    sprintf(
2168
-                        __(
2169
-                            'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2170
-                            'event_espresso'
2171
-                        ),
2172
-                        $property_name
2173
-                    )
2174
-                );
2175
-            }
2176
-        }
2177
-        return true;
2178
-    }
2179
-
2180
-
2181
-
2182
-    /**
2183
-     * This simply returns an array of model fields for this object
2184
-     *
2185
-     * @return array
2186
-     * @throws \EE_Error
2187
-     */
2188
-    public function model_field_array()
2189
-    {
2190
-        $fields = $this->get_model()->field_settings(false);
2191
-        $properties = array();
2192
-        //remove prepended underscore
2193
-        foreach ($fields as $field_name => $settings) {
2194
-            $properties[$field_name] = $this->get($field_name);
2195
-        }
2196
-        return $properties;
2197
-    }
2198
-
2199
-
2200
-
2201
-    /**
2202
-     * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2203
-     * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called (http://www.garfieldtech.com/blog/php-magic-call)
2204
-     * and passed the method's name and arguments.
2205
-     * Instead of requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that happen?)
2206
-     * they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg, filters_hook_espresso__EE_Answer__my_great_function)
2207
-     * and accepts 2 arguments: the object on which the function was called, and an array of the original arguments passed to the function. Whatever their callback function returns will be returned by this function.
2208
-     * Example: in functions.php (or in a plugin):
2209
-     * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3);
2210
-     * function my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2211
-     * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2212
-     *        return $previousReturnValue.$returnString;
2213
-     * }
2214
-     * require('EE_Answer.class.php');
2215
-     * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2216
-     * echo $answer->my_callback('monkeys',100);
2217
-     * //will output "you called my_callback! and passed args:monkeys,100"
2218
-     *
2219
-     * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2220
-     * @param array  $args       array of original arguments passed to the function
2221
-     * @throws EE_Error
2222
-     * @return mixed whatever the plugin which calls add_filter decides
2223
-     */
2224
-    public function __call($methodName, $args)
2225
-    {
2226
-        $className = get_class($this);
2227
-        $tagName = "FHEE__{$className}__{$methodName}";
2228
-        if ( ! has_filter($tagName)) {
2229
-            throw new EE_Error(
2230
-                sprintf(
2231
-                    __(
2232
-                        "Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2233
-                        "event_espresso"
2234
-                    ),
2235
-                    $methodName,
2236
-                    $className,
2237
-                    $tagName
2238
-                )
2239
-            );
2240
-        }
2241
-        return apply_filters($tagName, null, $this, $args);
2242
-    }
2243
-
2244
-
2245
-
2246
-    /**
2247
-     * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2248
-     * A $previous_value can be specified in case there are many meta rows with the same key
2249
-     *
2250
-     * @param string $meta_key
2251
-     * @param string $meta_value
2252
-     * @param string $previous_value
2253
-     * @return int records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2254
-     * @throws \EE_Error
2255
-     * NOTE: if the values haven't changed, returns 0
2256
-     */
2257
-    public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2258
-    {
2259
-        $query_params = array(
2260
-            array(
2261
-                'EXM_key'  => $meta_key,
2262
-                'OBJ_ID'   => $this->ID(),
2263
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2264
-            ),
2265
-        );
2266
-        if ($previous_value !== null) {
2267
-            $query_params[0]['EXM_value'] = $meta_value;
2268
-        }
2269
-        $existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2270
-        if ( ! $existing_rows_like_that) {
2271
-            return $this->add_extra_meta($meta_key, $meta_value);
2272
-        } else {
2273
-            foreach ($existing_rows_like_that as $existing_row) {
2274
-                $existing_row->save(array('EXM_value' => $meta_value));
2275
-            }
2276
-            return count($existing_rows_like_that);
2277
-        }
2278
-    }
2279
-
2280
-
2281
-
2282
-    /**
2283
-     * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2284
-     * no other extra meta for this model object have the same key. Returns TRUE if the
2285
-     * extra meta row was entered, false if not
2286
-     *
2287
-     * @param string  $meta_key
2288
-     * @param string  $meta_value
2289
-     * @param boolean $unique
2290
-     * @return boolean
2291
-     * @throws \EE_Error
2292
-     */
2293
-    public function add_extra_meta($meta_key, $meta_value, $unique = false)
2294
-    {
2295
-        if ($unique) {
2296
-            $existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2297
-                array(
2298
-                    array(
2299
-                        'EXM_key'  => $meta_key,
2300
-                        'OBJ_ID'   => $this->ID(),
2301
-                        'EXM_type' => $this->get_model()->get_this_model_name(),
2302
-                    ),
2303
-                )
2304
-            );
2305
-            if ($existing_extra_meta) {
2306
-                return false;
2307
-            }
2308
-        }
2309
-        $new_extra_meta = EE_Extra_Meta::new_instance(
2310
-            array(
2311
-                'EXM_key'   => $meta_key,
2312
-                'EXM_value' => $meta_value,
2313
-                'OBJ_ID'    => $this->ID(),
2314
-                'EXM_type'  => $this->get_model()->get_this_model_name(),
2315
-            )
2316
-        );
2317
-        $new_extra_meta->save();
2318
-        return true;
2319
-    }
2320
-
2321
-
2322
-
2323
-    /**
2324
-     * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2325
-     * is specified, only deletes extra meta records with that value.
2326
-     *
2327
-     * @param string $meta_key
2328
-     * @param string $meta_value
2329
-     * @return int number of extra meta rows deleted
2330
-     * @throws \EE_Error
2331
-     */
2332
-    public function delete_extra_meta($meta_key, $meta_value = null)
2333
-    {
2334
-        $query_params = array(
2335
-            array(
2336
-                'EXM_key'  => $meta_key,
2337
-                'OBJ_ID'   => $this->ID(),
2338
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2339
-            ),
2340
-        );
2341
-        if ($meta_value !== null) {
2342
-            $query_params[0]['EXM_value'] = $meta_value;
2343
-        }
2344
-        return EEM_Extra_Meta::instance()->delete($query_params);
2345
-    }
2346
-
2347
-
2348
-
2349
-    /**
2350
-     * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2351
-     * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2352
-     * You can specify $default is case you haven't found the extra meta
2353
-     *
2354
-     * @param string  $meta_key
2355
-     * @param boolean $single
2356
-     * @param mixed   $default if we don't find anything, what should we return?
2357
-     * @return mixed single value if $single; array if ! $single
2358
-     * @throws \EE_Error
2359
-     */
2360
-    public function get_extra_meta($meta_key, $single = false, $default = null)
2361
-    {
2362
-        if ($single) {
2363
-            $result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2364
-            if ($result instanceof EE_Extra_Meta) {
2365
-                return $result->value();
2366
-            } else {
2367
-                return $default;
2368
-            }
2369
-        } else {
2370
-            $results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2371
-            if ($results) {
2372
-                $values = array();
2373
-                foreach ($results as $result) {
2374
-                    if ($result instanceof EE_Extra_Meta) {
2375
-                        $values[$result->ID()] = $result->value();
2376
-                    }
2377
-                }
2378
-                return $values;
2379
-            } else {
2380
-                return $default;
2381
-            }
2382
-        }
2383
-    }
2384
-
2385
-
2386
-
2387
-    /**
2388
-     * Returns a simple array of all the extra meta associated with this model object.
2389
-     * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2390
-     * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2391
-     * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2392
-     * If $one_of_each_key is false, it will return an array with the top-level keys being
2393
-     * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2394
-     * finally the extra meta's value as each sub-value. (eg array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2395
-     *
2396
-     * @param boolean $one_of_each_key
2397
-     * @return array
2398
-     * @throws \EE_Error
2399
-     */
2400
-    public function all_extra_meta_array($one_of_each_key = true)
2401
-    {
2402
-        $return_array = array();
2403
-        if ($one_of_each_key) {
2404
-            $extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2405
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2406
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2407
-                    $return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2408
-                }
2409
-            }
2410
-        } else {
2411
-            $extra_meta_objs = $this->get_many_related('Extra_Meta');
2412
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2413
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2414
-                    if ( ! isset($return_array[$extra_meta_obj->key()])) {
2415
-                        $return_array[$extra_meta_obj->key()] = array();
2416
-                    }
2417
-                    $return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2418
-                }
2419
-            }
2420
-        }
2421
-        return $return_array;
2422
-    }
2423
-
2424
-
2425
-
2426
-    /**
2427
-     * Gets a pretty nice displayable nice for this model object. Often overridden
2428
-     *
2429
-     * @return string
2430
-     * @throws \EE_Error
2431
-     */
2432
-    public function name()
2433
-    {
2434
-        //find a field that's not a text field
2435
-        $field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2436
-        if ($field_we_can_use) {
2437
-            return $this->get($field_we_can_use->get_name());
2438
-        } else {
2439
-            $first_few_properties = $this->model_field_array();
2440
-            $first_few_properties = array_slice($first_few_properties, 0, 3);
2441
-            $name_parts = array();
2442
-            foreach ($first_few_properties as $name => $value) {
2443
-                $name_parts[] = "$name:$value";
2444
-            }
2445
-            return implode(",", $name_parts);
2446
-        }
2447
-    }
2448
-
2449
-
2450
-
2451
-    /**
2452
-     * in_entity_map
2453
-     * Checks if this model object has been proven to already be in the entity map
2454
-     *
2455
-     * @return boolean
2456
-     * @throws \EE_Error
2457
-     */
2458
-    public function in_entity_map()
2459
-    {
2460
-        if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2461
-            //well, if we looked, did we find it in the entity map?
2462
-            return true;
2463
-        } else {
2464
-            return false;
2465
-        }
2466
-    }
2467
-
2468
-
2469
-
2470
-    /**
2471
-     * refresh_from_db
2472
-     * Makes sure the fields and values on this model object are in-sync with what's in the database.
2473
-     *
2474
-     * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2475
-     * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2476
-     */
2477
-    public function refresh_from_db()
2478
-    {
2479
-        if ($this->ID() && $this->in_entity_map()) {
2480
-            $this->get_model()->refresh_entity_map_from_db($this->ID());
2481
-        } else {
2482
-            //if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2483
-            //if it has an ID but it's not in the map, and you're asking me to refresh it
2484
-            //that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2485
-            //absolutely nothing in it for this ID
2486
-            if (WP_DEBUG) {
2487
-                throw new EE_Error(
2488
-                    sprintf(
2489
-                        __('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2490
-                            'event_espresso'),
2491
-                        $this->ID(),
2492
-                        get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2493
-                        get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2494
-                    )
2495
-                );
2496
-            }
2497
-        }
2498
-    }
2499
-
2500
-
2501
-
2502
-    /**
2503
-     * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2504
-     * (probably a bad assumption they have made, oh well)
2505
-     *
2506
-     * @return string
2507
-     */
2508
-    public function __toString()
2509
-    {
2510
-        try {
2511
-            return sprintf('%s (%s)', $this->name(), $this->ID());
2512
-        } catch (Exception $e) {
2513
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2514
-            return '';
2515
-        }
2516
-    }
2517
-
2518
-
2519
-
2520
-    /**
2521
-     * Clear related model objects if they're already in the DB, because otherwise when we
2522
-     * UN-serialize this model object we'll need to be careful to add them to the entity map.
2523
-     * This means if we have made changes to those related model objects, and want to unserialize
2524
-     * the this model object on a subsequent request, changes to those related model objects will be lost.
2525
-     * Instead, those related model objects should be directly serialized and stored.
2526
-     * Eg, the following won't work:
2527
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2528
-     * $att = $reg->attendee();
2529
-     * $att->set( 'ATT_fname', 'Dirk' );
2530
-     * update_option( 'my_option', serialize( $reg ) );
2531
-     * //END REQUEST
2532
-     * //START NEXT REQUEST
2533
-     * $reg = get_option( 'my_option' );
2534
-     * $reg->attendee()->save();
2535
-     * And would need to be replace with:
2536
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2537
-     * $att = $reg->attendee();
2538
-     * $att->set( 'ATT_fname', 'Dirk' );
2539
-     * update_option( 'my_option', serialize( $reg ) );
2540
-     * //END REQUEST
2541
-     * //START NEXT REQUEST
2542
-     * $att = get_option( 'my_option' );
2543
-     * $att->save();
2544
-     *
2545
-     * @return array
2546
-     * @throws \EE_Error
2547
-     */
2548
-    public function __sleep()
2549
-    {
2550
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
2551
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
2552
-                $classname = 'EE_' . $this->get_model()->get_this_model_name();
2553
-                if (
2554
-                    $this->get_one_from_cache($relation_name) instanceof $classname
2555
-                    && $this->get_one_from_cache($relation_name)->ID()
2556
-                ) {
2557
-                    $this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2558
-                }
2559
-            }
2560
-        }
2561
-        $this->_props_n_values_provided_in_constructor = array();
2562
-        return array_keys(get_object_vars($this));
2563
-    }
2564
-
2565
-
2566
-
2567
-    /**
2568
-     * restore _props_n_values_provided_in_constructor
2569
-     * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2570
-     * and therefore should NOT be used to determine if state change has occurred since initial construction.
2571
-     * At best, you would only be able to detect if state change has occurred during THIS request.
2572
-     */
2573
-    public function __wakeup()
2574
-    {
2575
-        $this->_props_n_values_provided_in_constructor = $this->_fields;
2576
-    }
28
+	/**
29
+	 * This is an array of the original properties and values provided during construction
30
+	 * of this model object. (keys are model field names, values are their values).
31
+	 * This list is important to remember so that when we are merging data from the db, we know
32
+	 * which values to override and which to not override.
33
+	 *
34
+	 * @var array
35
+	 */
36
+	protected $_props_n_values_provided_in_constructor;
37
+
38
+	/**
39
+	 * Timezone
40
+	 * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT all
41
+	 * EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have access to it.
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_timezone;
46
+
47
+
48
+
49
+	/**
50
+	 * date format
51
+	 * pattern or format for displaying dates
52
+	 *
53
+	 * @var string $_dt_frmt
54
+	 */
55
+	protected $_dt_frmt;
56
+
57
+
58
+
59
+	/**
60
+	 * time format
61
+	 * pattern or format for displaying time
62
+	 *
63
+	 * @var string $_tm_frmt
64
+	 */
65
+	protected $_tm_frmt;
66
+
67
+
68
+
69
+	/**
70
+	 * This property is for holding a cached array of object properties indexed by property name as the key.
71
+	 * The purpose of this is for setting a cache on properties that may have calculated values after a prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having to recalculate.
72
+	 * Used by _set_cached_property() and _get_cached_property() methods.
73
+	 *
74
+	 * @var array
75
+	 */
76
+	protected $_cached_properties = array();
77
+
78
+	/**
79
+	 * An array containing keys of the related model, and values are either an array of related mode objects or a single
80
+	 * related model object. see the model's _model_relations. The keys should match those specified. And if the relation
81
+	 * is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object, all others have an array)
82
+	 *
83
+	 * @var array
84
+	 */
85
+	protected $_model_relations = array();
86
+
87
+	/**
88
+	 * Array where keys are field names (see the model's _fields property) and values are their values. To see what
89
+	 * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
90
+	 *
91
+	 * @var array
92
+	 */
93
+	protected $_fields = array();
94
+
95
+	/**
96
+	 * @var boolean indicating whether or not this model object is intended to ever be saved
97
+	 * For example, we might create model objects intended to only be used for the duration
98
+	 * of this request and to be thrown away, and if they were accidentally saved
99
+	 * it would be a bug.
100
+	 */
101
+	protected $_allow_persist = true;
102
+
103
+
104
+
105
+	/**
106
+	 * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children play nice
107
+	 *
108
+	 * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd layer of the model's _fields array, (eg, EVT_ID, TXN_amount, QST_name, etc) and values are their values
109
+	 * @param boolean $bydb                                    a flag for setting if the class is instantiated by the corresponding db model or not.
110
+	 * @param string  $timezone                                indicate what timezone you want any datetime fields to be in when instantiating a EE_Base_Class object.
111
+	 * @param array   $date_formats                            An array of date formats to set on construct where first
112
+	 *                                                         value is the date_format and second value is the time
113
+	 *                                                         format.
114
+	 * @throws EE_Error
115
+	 */
116
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
117
+	{
118
+		$className = get_class($this);
119
+		do_action("AHEE__{$className}__construct", $this, $fieldValues);
120
+		$model = $this->get_model();
121
+		$model_fields = $model->field_settings(false);
122
+		// ensure $fieldValues is an array
123
+		$fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
124
+		// EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
125
+		// verify client code has not passed any invalid field names
126
+		foreach ($fieldValues as $field_name => $field_value) {
127
+			if ( ! isset($model_fields[$field_name])) {
128
+				throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s", "event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
129
+			}
130
+		}
131
+		// EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
132
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
133
+		if ( ! empty($date_formats) && is_array($date_formats)) {
134
+			list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
135
+		} else {
136
+			//set default formats for date and time
137
+			$this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
138
+			$this->_tm_frmt = (string)get_option('time_format', 'g:i a');
139
+		}
140
+		//if db model is instantiating
141
+		if ($bydb) {
142
+			//client code has indicated these field values are from the database
143
+			foreach ($model_fields as $fieldName => $field) {
144
+				$this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
145
+			}
146
+		} else {
147
+			//we're constructing a brand
148
+			//new instance of the model object. Generally, this means we'll need to do more field validation
149
+			foreach ($model_fields as $fieldName => $field) {
150
+				$this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
151
+			}
152
+		}
153
+		//remember what values were passed to this constructor
154
+		$this->_props_n_values_provided_in_constructor = $fieldValues;
155
+		//remember in entity mapper
156
+		if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
157
+			$model->add_to_entity_map($this);
158
+		}
159
+		//setup all the relations
160
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
161
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
162
+				$this->_model_relations[$relation_name] = null;
163
+			} else {
164
+				$this->_model_relations[$relation_name] = array();
165
+			}
166
+		}
167
+		/**
168
+		 * Action done at the end of each model object construction
169
+		 *
170
+		 * @param EE_Base_Class $this the model object just created
171
+		 */
172
+		do_action('AHEE__EE_Base_Class__construct__finished', $this);
173
+	}
174
+
175
+
176
+
177
+	/**
178
+	 * Gets whether or not this model object is allowed to persist/be saved to the database.
179
+	 *
180
+	 * @return boolean
181
+	 */
182
+	public function allow_persist()
183
+	{
184
+		return $this->_allow_persist;
185
+	}
186
+
187
+
188
+
189
+	/**
190
+	 * Sets whether or not this model object should be allowed to be saved to the DB.
191
+	 * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
192
+	 * you got new information that somehow made you change your mind.
193
+	 *
194
+	 * @param boolean $allow_persist
195
+	 * @return boolean
196
+	 */
197
+	public function set_allow_persist($allow_persist)
198
+	{
199
+		return $this->_allow_persist = $allow_persist;
200
+	}
201
+
202
+
203
+
204
+	/**
205
+	 * Gets the field's original value when this object was constructed during this request.
206
+	 * This can be helpful when determining if a model object has changed or not
207
+	 *
208
+	 * @param string $field_name
209
+	 * @return mixed|null
210
+	 * @throws \EE_Error
211
+	 */
212
+	public function get_original($field_name)
213
+	{
214
+		if (isset($this->_props_n_values_provided_in_constructor[$field_name])
215
+			&& $field_settings = $this->get_model()->field_settings_for($field_name)
216
+		) {
217
+			return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
218
+		} else {
219
+			return null;
220
+		}
221
+	}
222
+
223
+
224
+
225
+	/**
226
+	 * @param EE_Base_Class $obj
227
+	 * @return string
228
+	 */
229
+	public function get_class($obj)
230
+	{
231
+		return get_class($obj);
232
+	}
233
+
234
+
235
+
236
+	/**
237
+	 * Overrides parent because parent expects old models.
238
+	 * This also doesn't do any validation, and won't work for serialized arrays
239
+	 *
240
+	 * @param    string $field_name
241
+	 * @param    mixed  $field_value
242
+	 * @param bool      $use_default
243
+	 * @throws \EE_Error
244
+	 */
245
+	public function set($field_name, $field_value, $use_default = false)
246
+	{
247
+		$field_obj = $this->get_model()->field_settings_for($field_name);
248
+		if ($field_obj instanceof EE_Model_Field_Base) {
249
+			//			if ( method_exists( $field_obj, 'set_timezone' )) {
250
+			if ($field_obj instanceof EE_Datetime_Field) {
251
+				$field_obj->set_timezone($this->_timezone);
252
+				$field_obj->set_date_format($this->_dt_frmt);
253
+				$field_obj->set_time_format($this->_tm_frmt);
254
+			}
255
+			$holder_of_value = $field_obj->prepare_for_set($field_value);
256
+			//should the value be null?
257
+			if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
258
+				$this->_fields[$field_name] = $field_obj->get_default_value();
259
+				/**
260
+				 * To save having to refactor all the models, if a default value is used for a
261
+				 * EE_Datetime_Field, and that value is not null nor is it a DateTime
262
+				 * object.  Then let's do a set again to ensure that it becomes a DateTime
263
+				 * object.
264
+				 *
265
+				 * @since 4.6.10+
266
+				 */
267
+				if (
268
+					$field_obj instanceof EE_Datetime_Field
269
+					&& $this->_fields[$field_name] !== null
270
+					&& ! $this->_fields[$field_name] instanceof DateTime
271
+				) {
272
+					empty($this->_fields[$field_name])
273
+						? $this->set($field_name, time())
274
+						: $this->set($field_name, $this->_fields[$field_name]);
275
+				}
276
+			} else {
277
+				$this->_fields[$field_name] = $holder_of_value;
278
+			}
279
+			//if we're not in the constructor...
280
+			//now check if what we set was a primary key
281
+			if (
282
+				//note: props_n_values_provided_in_constructor is only set at the END of the constructor
283
+				$this->_props_n_values_provided_in_constructor
284
+				&& $field_value
285
+				&& $field_name === self::_get_primary_key_name(get_class($this))
286
+			) {
287
+				//if so, we want all this object's fields to be filled either with
288
+				//what we've explicitly set on this model
289
+				//or what we have in the db
290
+				// echo "setting primary key!";
291
+				$fields_on_model = self::_get_model(get_class($this))->field_settings();
292
+				$obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
293
+				foreach ($fields_on_model as $field_obj) {
294
+					if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
295
+						 && $field_obj->get_name() !== $field_name
296
+					) {
297
+						$this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
298
+					}
299
+				}
300
+				//oh this model object has an ID? well make sure its in the entity mapper
301
+				$this->get_model()->add_to_entity_map($this);
302
+			}
303
+			//let's unset any cache for this field_name from the $_cached_properties property.
304
+			$this->_clear_cached_property($field_name);
305
+		} else {
306
+			throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s", "event_espresso"), $field_name));
307
+		}
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * This sets the field value on the db column if it exists for the given $column_name or
314
+	 * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
315
+	 *
316
+	 * @see EE_message::get_column_value for related documentation on the necessity of this method.
317
+	 * @param string $field_name  Must be the exact column name.
318
+	 * @param mixed  $field_value The value to set.
319
+	 * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
320
+	 * @throws \EE_Error
321
+	 */
322
+	public function set_field_or_extra_meta($field_name, $field_value)
323
+	{
324
+		if ($this->get_model()->has_field($field_name)) {
325
+			$this->set($field_name, $field_value);
326
+			return true;
327
+		} else {
328
+			//ensure this object is saved first so that extra meta can be properly related.
329
+			$this->save();
330
+			return $this->update_extra_meta($field_name, $field_value);
331
+		}
332
+	}
333
+
334
+
335
+
336
+	/**
337
+	 * This retrieves the value of the db column set on this class or if that's not present
338
+	 * it will attempt to retrieve from extra_meta if found.
339
+	 * Example Usage:
340
+	 * Via EE_Message child class:
341
+	 * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
342
+	 * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
343
+	 * also have additional main fields specific to the messenger.  The system accommodates those extra
344
+	 * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
345
+	 * value for those extra fields dynamically via the EE_message object.
346
+	 *
347
+	 * @param  string $field_name expecting the fully qualified field name.
348
+	 * @return mixed|null  value for the field if found.  null if not found.
349
+	 * @throws \EE_Error
350
+	 */
351
+	public function get_field_or_extra_meta($field_name)
352
+	{
353
+		if ($this->get_model()->has_field($field_name)) {
354
+			$column_value = $this->get($field_name);
355
+		} else {
356
+			//This isn't a column in the main table, let's see if it is in the extra meta.
357
+			$column_value = $this->get_extra_meta($field_name, true, null);
358
+		}
359
+		return $column_value;
360
+	}
361
+
362
+
363
+
364
+	/**
365
+	 * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally for being able to reference what timezone we are running conversions on when converting TO the internal timezone (UTC
366
+	 * Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is available to all child classes that may be using the EE_Datetime_Field for a field data type.
367
+	 *
368
+	 * @access public
369
+	 * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
370
+	 * @return void
371
+	 * @throws \EE_Error
372
+	 */
373
+	public function set_timezone($timezone = '')
374
+	{
375
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
376
+		//make sure we clear all cached properties because they won't be relevant now
377
+		$this->_clear_cached_properties();
378
+		//make sure we update field settings and the date for all EE_Datetime_Fields
379
+		$model_fields = $this->get_model()->field_settings(false);
380
+		foreach ($model_fields as $field_name => $field_obj) {
381
+			if ($field_obj instanceof EE_Datetime_Field) {
382
+				$field_obj->set_timezone($this->_timezone);
383
+				if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
384
+					$this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
385
+				}
386
+			}
387
+		}
388
+	}
389
+
390
+
391
+
392
+	/**
393
+	 * This just returns whatever is set for the current timezone.
394
+	 *
395
+	 * @access public
396
+	 * @return string timezone string
397
+	 */
398
+	public function get_timezone()
399
+	{
400
+		return $this->_timezone;
401
+	}
402
+
403
+
404
+
405
+	/**
406
+	 * This sets the internal date format to what is sent in to be used as the new default for the class
407
+	 * internally instead of wp set date format options
408
+	 *
409
+	 * @since 4.6
410
+	 * @param string $format should be a format recognizable by PHP date() functions.
411
+	 */
412
+	public function set_date_format($format)
413
+	{
414
+		$this->_dt_frmt = $format;
415
+		//clear cached_properties because they won't be relevant now.
416
+		$this->_clear_cached_properties();
417
+	}
418
+
419
+
420
+
421
+	/**
422
+	 * This sets the internal time format string to what is sent in to be used as the new default for the
423
+	 * class internally instead of wp set time format options.
424
+	 *
425
+	 * @since 4.6
426
+	 * @param string $format should be a format recognizable by PHP date() functions.
427
+	 */
428
+	public function set_time_format($format)
429
+	{
430
+		$this->_tm_frmt = $format;
431
+		//clear cached_properties because they won't be relevant now.
432
+		$this->_clear_cached_properties();
433
+	}
434
+
435
+
436
+
437
+	/**
438
+	 * This returns the current internal set format for the date and time formats.
439
+	 *
440
+	 * @param bool $full           if true (default), then return the full format.  Otherwise will return an array where the
441
+	 *                             first value is the date format and the second value is the time format.
442
+	 * @return mixed string|array
443
+	 */
444
+	public function get_format($full = true)
445
+	{
446
+		return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 * cache
453
+	 * stores the passed model object on the current model object.
454
+	 * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
455
+	 *
456
+	 * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg 'Registration' associated with this model object
457
+	 * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction, that could be a payment or a registration)
458
+	 * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many items which will be stored in an array on this object
459
+	 * @throws EE_Error
460
+	 * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one related thing, no array)
461
+	 */
462
+	public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
463
+	{
464
+		// its entirely possible that there IS no related object yet in which case there is nothing to cache.
465
+		if ( ! $object_to_cache instanceof EE_Base_Class) {
466
+			return false;
467
+		}
468
+		// also get "how" the object is related, or throw an error
469
+		if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
470
+			throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'), $relationName, get_class($this)));
471
+		}
472
+		// how many things are related ?
473
+		if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
474
+			// if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
475
+			// so for these model objects just set it to be cached
476
+			$this->_model_relations[$relationName] = $object_to_cache;
477
+			$return = true;
478
+		} else {
479
+			// otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
480
+			// eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
481
+			if ( ! is_array($this->_model_relations[$relationName])) {
482
+				// if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
483
+				$this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class ? array($this->_model_relations[$relationName]) : array();
484
+			}
485
+			// first check for a cache_id which is normally empty
486
+			if ( ! empty($cache_id)) {
487
+				// if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
488
+				$this->_model_relations[$relationName][$cache_id] = $object_to_cache;
489
+				$return = $cache_id;
490
+			} elseif ($object_to_cache->ID()) {
491
+				// OR the cached object originally came from the db, so let's just use it's PK for an ID
492
+				$this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
493
+				$return = $object_to_cache->ID();
494
+			} else {
495
+				// OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
496
+				$this->_model_relations[$relationName][] = $object_to_cache;
497
+				// move the internal pointer to the end of the array
498
+				end($this->_model_relations[$relationName]);
499
+				// and grab the key so that we can return it
500
+				$return = key($this->_model_relations[$relationName]);
501
+			}
502
+		}
503
+		return $return;
504
+	}
505
+
506
+
507
+
508
+	/**
509
+	 * For adding an item to the cached_properties property.
510
+	 *
511
+	 * @access protected
512
+	 * @param string      $fieldname the property item the corresponding value is for.
513
+	 * @param mixed       $value     The value we are caching.
514
+	 * @param string|null $cache_type
515
+	 * @return void
516
+	 * @throws \EE_Error
517
+	 */
518
+	protected function _set_cached_property($fieldname, $value, $cache_type = null)
519
+	{
520
+		//first make sure this property exists
521
+		$this->get_model()->field_settings_for($fieldname);
522
+		$cache_type = empty($cache_type) ? 'standard' : $cache_type;
523
+		$this->_cached_properties[$fieldname][$cache_type] = $value;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
530
+	 * This also SETS the cache if we return the actual property!
531
+	 *
532
+	 * @param string $fieldname        the name of the property we're trying to retrieve
533
+	 * @param bool   $pretty
534
+	 * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
535
+	 *                                 (in cases where the same property may be used for different outputs
536
+	 *                                 - i.e. datetime, money etc.)
537
+	 *                                 It can also accept certain pre-defined "schema" strings
538
+	 *                                 to define how to output the property.
539
+	 *                                 see the field's prepare_for_pretty_echoing for what strings can be used
540
+	 * @return mixed                   whatever the value for the property is we're retrieving
541
+	 * @throws \EE_Error
542
+	 */
543
+	protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
544
+	{
545
+		//verify the field exists
546
+		$this->get_model()->field_settings_for($fieldname);
547
+		$cache_type = $pretty ? 'pretty' : 'standard';
548
+		$cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
549
+		if (isset($this->_cached_properties[$fieldname][$cache_type])) {
550
+			return $this->_cached_properties[$fieldname][$cache_type];
551
+		}
552
+		$field_obj = $this->get_model()->field_settings_for($fieldname);
553
+		if ($field_obj instanceof EE_Model_Field_Base) {
554
+			// If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
555
+			if ($field_obj instanceof EE_Datetime_Field) {
556
+				$this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
557
+			}
558
+			if ( ! isset($this->_fields[$fieldname])) {
559
+				$this->_fields[$fieldname] = null;
560
+			}
561
+			$value = $pretty
562
+				? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
563
+				: $field_obj->prepare_for_get($this->_fields[$fieldname]);
564
+			$this->_set_cached_property($fieldname, $value, $cache_type);
565
+			return $value;
566
+		}
567
+		return null;
568
+	}
569
+
570
+
571
+
572
+	/**
573
+	 * set timezone, formats, and output for EE_Datetime_Field objects
574
+	 *
575
+	 * @param \EE_Datetime_Field $datetime_field
576
+	 * @param bool               $pretty
577
+	 * @param null $date_or_time
578
+	 * @return void
579
+	 * @throws \EE_Error
580
+	 */
581
+	protected function _prepare_datetime_field(
582
+		EE_Datetime_Field $datetime_field,
583
+		$pretty = false,
584
+		$date_or_time = null
585
+	) {
586
+		$datetime_field->set_timezone($this->_timezone);
587
+		$datetime_field->set_date_format($this->_dt_frmt, $pretty);
588
+		$datetime_field->set_time_format($this->_tm_frmt, $pretty);
589
+		//set the output returned
590
+		switch ($date_or_time) {
591
+			case 'D' :
592
+				$datetime_field->set_date_time_output('date');
593
+				break;
594
+			case 'T' :
595
+				$datetime_field->set_date_time_output('time');
596
+				break;
597
+			default :
598
+				$datetime_field->set_date_time_output();
599
+		}
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * This just takes care of clearing out the cached_properties
606
+	 *
607
+	 * @return void
608
+	 */
609
+	protected function _clear_cached_properties()
610
+	{
611
+		$this->_cached_properties = array();
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 * This just clears out ONE property if it exists in the cache
618
+	 *
619
+	 * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
620
+	 * @return void
621
+	 */
622
+	protected function _clear_cached_property($property_name)
623
+	{
624
+		if (isset($this->_cached_properties[$property_name])) {
625
+			unset($this->_cached_properties[$property_name]);
626
+		}
627
+	}
628
+
629
+
630
+
631
+	/**
632
+	 * Ensures that this related thing is a model object.
633
+	 *
634
+	 * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
635
+	 * @param string $model_name   name of the related thing, eg 'Attendee',
636
+	 * @return EE_Base_Class
637
+	 * @throws \EE_Error
638
+	 */
639
+	protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
640
+	{
641
+		$other_model_instance = self::_get_model_instance_with_name(
642
+			self::_get_model_classname($model_name),
643
+			$this->_timezone
644
+		);
645
+		return $other_model_instance->ensure_is_obj($object_or_id);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * Forgets the cached model of the given relation Name. So the next time we request it,
652
+	 * we will fetch it again from the database. (Handy if you know it's changed somehow).
653
+	 * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
654
+	 * then only remove that one object from our cached array. Otherwise, clear the entire list
655
+	 *
656
+	 * @param string $relationName                         one of the keys in the _model_relations array on the model. Eg 'Registration'
657
+	 * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
658
+	 *                                                     if you intend to use $clear_all = TRUE, or the relation only has 1 object anyways (ie, it's a BelongsToRelation)
659
+	 * @param bool   $clear_all                            This flags clearing the entire cache relation property if this is HasMany or HABTM.
660
+	 * @throws EE_Error
661
+	 * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a relation from all
662
+	 */
663
+	public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
664
+	{
665
+		$relationship_to_model = $this->get_model()->related_settings_for($relationName);
666
+		$index_in_cache = '';
667
+		if ( ! $relationship_to_model) {
668
+			throw new EE_Error(
669
+				sprintf(
670
+					__("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
671
+					$relationName,
672
+					get_class($this)
673
+				)
674
+			);
675
+		}
676
+		if ($clear_all) {
677
+			$obj_removed = true;
678
+			$this->_model_relations[$relationName] = null;
679
+		} elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
680
+			$obj_removed = $this->_model_relations[$relationName];
681
+			$this->_model_relations[$relationName] = null;
682
+		} else {
683
+			if ($object_to_remove_or_index_into_array instanceof EE_Base_Class && $object_to_remove_or_index_into_array->ID()) {
684
+				$index_in_cache = $object_to_remove_or_index_into_array->ID();
685
+				if (is_array($this->_model_relations[$relationName]) && ! isset($this->_model_relations[$relationName][$index_in_cache])) {
686
+					$index_found_at = null;
687
+					//find this object in the array even though it has a different key
688
+					foreach ($this->_model_relations[$relationName] as $index => $obj) {
689
+						if (
690
+							$obj instanceof EE_Base_Class
691
+							&& (
692
+								$obj == $object_to_remove_or_index_into_array
693
+								|| $obj->ID() === $object_to_remove_or_index_into_array->ID()
694
+							)
695
+						) {
696
+							$index_found_at = $index;
697
+							break;
698
+						}
699
+					}
700
+					if ($index_found_at) {
701
+						$index_in_cache = $index_found_at;
702
+					} else {
703
+						//it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
704
+						//if it wasn't in it to begin with. So we're done
705
+						return $object_to_remove_or_index_into_array;
706
+					}
707
+				}
708
+			} elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
709
+				//so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
710
+				foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
711
+					if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
712
+						$index_in_cache = $index;
713
+					}
714
+				}
715
+			} else {
716
+				$index_in_cache = $object_to_remove_or_index_into_array;
717
+			}
718
+			//supposedly we've found it. But it could just be that the client code
719
+			//provided a bad index/object
720
+			if (
721
+			isset(
722
+				$this->_model_relations[$relationName],
723
+				$this->_model_relations[$relationName][$index_in_cache]
724
+			)
725
+			) {
726
+				$obj_removed = $this->_model_relations[$relationName][$index_in_cache];
727
+				unset($this->_model_relations[$relationName][$index_in_cache]);
728
+			} else {
729
+				//that thing was never cached anyways.
730
+				$obj_removed = null;
731
+			}
732
+		}
733
+		return $obj_removed;
734
+	}
735
+
736
+
737
+
738
+	/**
739
+	 * update_cache_after_object_save
740
+	 * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has obtained after being saved to the db
741
+	 *
742
+	 * @param string         $relationName       - the type of object that is cached
743
+	 * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
744
+	 * @param string         $current_cache_id   - the ID that was used when originally caching the object
745
+	 * @return boolean TRUE on success, FALSE on fail
746
+	 * @throws \EE_Error
747
+	 */
748
+	public function update_cache_after_object_save($relationName, EE_Base_Class $newly_saved_object, $current_cache_id = '')
749
+	{
750
+		// verify that incoming object is of the correct type
751
+		$obj_class = 'EE_' . $relationName;
752
+		if ($newly_saved_object instanceof $obj_class) {
753
+			/* @type EE_Base_Class $newly_saved_object */
754
+			// now get the type of relation
755
+			$relationship_to_model = $this->get_model()->related_settings_for($relationName);
756
+			// if this is a 1:1 relationship
757
+			if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
758
+				// then just replace the cached object with the newly saved object
759
+				$this->_model_relations[$relationName] = $newly_saved_object;
760
+				return true;
761
+				// or if it's some kind of sordid feral polyamorous relationship...
762
+			} elseif (is_array($this->_model_relations[$relationName]) && isset($this->_model_relations[$relationName][$current_cache_id])) {
763
+				// then remove the current cached item
764
+				unset($this->_model_relations[$relationName][$current_cache_id]);
765
+				// and cache the newly saved object using it's new ID
766
+				$this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
767
+				return true;
768
+			}
769
+		}
770
+		return false;
771
+	}
772
+
773
+
774
+
775
+	/**
776
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
777
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
778
+	 *
779
+	 * @param string $relationName
780
+	 * @return EE_Base_Class
781
+	 */
782
+	public function get_one_from_cache($relationName)
783
+	{
784
+		$cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : null;
785
+		if (is_array($cached_array_or_object)) {
786
+			return array_shift($cached_array_or_object);
787
+		} else {
788
+			return $cached_array_or_object;
789
+		}
790
+	}
791
+
792
+
793
+
794
+	/**
795
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
796
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
797
+	 *
798
+	 * @param string $relationName
799
+	 * @throws \EE_Error
800
+	 * @return EE_Base_Class[] NOT necessarily indexed by primary keys
801
+	 */
802
+	public function get_all_from_cache($relationName)
803
+	{
804
+		$objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
805
+		// if the result is not an array, but exists, make it an array
806
+		$objects = is_array($objects) ? $objects : array($objects);
807
+		//bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
808
+		//basically, if this model object was stored in the session, and these cached model objects
809
+		//already have IDs, let's make sure they're in their model's entity mapper
810
+		//otherwise we will have duplicates next time we call
811
+		// EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
812
+		$model = EE_Registry::instance()->load_model($relationName);
813
+		foreach ($objects as $model_object) {
814
+			if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
815
+				//ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
816
+				if ($model_object->ID()) {
817
+					$model->add_to_entity_map($model_object);
818
+				}
819
+			} else {
820
+				throw new EE_Error(
821
+					sprintf(
822
+						__(
823
+							'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
824
+							'event_espresso'
825
+						),
826
+						$relationName,
827
+						gettype($model_object)
828
+					)
829
+				);
830
+			}
831
+		}
832
+		return $objects;
833
+	}
834
+
835
+
836
+
837
+	/**
838
+	 * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
839
+	 * matching the given query conditions.
840
+	 *
841
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
842
+	 * @param int   $limit              How many objects to return.
843
+	 * @param array $query_params       Any additional conditions on the query.
844
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
845
+	 *                                  you can indicate just the columns you want returned
846
+	 * @return array|EE_Base_Class[]
847
+	 * @throws \EE_Error
848
+	 */
849
+	public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
850
+	{
851
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
852
+			? $this->get_model()->get_primary_key_field()->get_name()
853
+			: $field_to_order_by;
854
+		$current_value = ! empty($field) ? $this->get($field) : null;
855
+		if (empty($field) || empty($current_value)) {
856
+			return array();
857
+		}
858
+		return $this->get_model()->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
859
+	}
860
+
861
+
862
+
863
+	/**
864
+	 * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
865
+	 * matching the given query conditions.
866
+	 *
867
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
868
+	 * @param int   $limit              How many objects to return.
869
+	 * @param array $query_params       Any additional conditions on the query.
870
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
871
+	 *                                  you can indicate just the columns you want returned
872
+	 * @return array|EE_Base_Class[]
873
+	 * @throws \EE_Error
874
+	 */
875
+	public function previous_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
876
+	{
877
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
878
+			? $this->get_model()->get_primary_key_field()->get_name()
879
+			: $field_to_order_by;
880
+		$current_value = ! empty($field) ? $this->get($field) : null;
881
+		if (empty($field) || empty($current_value)) {
882
+			return array();
883
+		}
884
+		return $this->get_model()->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
885
+	}
886
+
887
+
888
+
889
+	/**
890
+	 * Returns the next EE_Base_Class object in sequence from this object as found in the database
891
+	 * matching the given query conditions.
892
+	 *
893
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
894
+	 * @param array $query_params       Any additional conditions on the query.
895
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
896
+	 *                                  you can indicate just the columns you want returned
897
+	 * @return array|EE_Base_Class
898
+	 * @throws \EE_Error
899
+	 */
900
+	public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
901
+	{
902
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
903
+			? $this->get_model()->get_primary_key_field()->get_name()
904
+			: $field_to_order_by;
905
+		$current_value = ! empty($field) ? $this->get($field) : null;
906
+		if (empty($field) || empty($current_value)) {
907
+			return array();
908
+		}
909
+		return $this->get_model()->next($current_value, $field, $query_params, $columns_to_select);
910
+	}
911
+
912
+
913
+
914
+	/**
915
+	 * Returns the previous EE_Base_Class object in sequence from this object as found in the database
916
+	 * matching the given query conditions.
917
+	 *
918
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
919
+	 * @param array $query_params       Any additional conditions on the query.
920
+	 * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
921
+	 *                                  you can indicate just the column you want returned
922
+	 * @return array|EE_Base_Class
923
+	 * @throws \EE_Error
924
+	 */
925
+	public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
926
+	{
927
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
928
+			? $this->get_model()->get_primary_key_field()->get_name()
929
+			: $field_to_order_by;
930
+		$current_value = ! empty($field) ? $this->get($field) : null;
931
+		if (empty($field) || empty($current_value)) {
932
+			return array();
933
+		}
934
+		return $this->get_model()->previous($current_value, $field, $query_params, $columns_to_select);
935
+	}
936
+
937
+
938
+
939
+	/**
940
+	 * Overrides parent because parent expects old models.
941
+	 * This also doesn't do any validation, and won't work for serialized arrays
942
+	 *
943
+	 * @param string $field_name
944
+	 * @param mixed  $field_value_from_db
945
+	 * @throws \EE_Error
946
+	 */
947
+	public function set_from_db($field_name, $field_value_from_db)
948
+	{
949
+		$field_obj = $this->get_model()->field_settings_for($field_name);
950
+		if ($field_obj instanceof EE_Model_Field_Base) {
951
+			//you would think the DB has no NULLs for non-null label fields right? wrong!
952
+			//eg, a CPT model object could have an entry in the posts table, but no
953
+			//entry in the meta table. Meaning that all its columns in the meta table
954
+			//are null! yikes! so when we find one like that, use defaults for its meta columns
955
+			if ($field_value_from_db === null) {
956
+				if ($field_obj->is_nullable()) {
957
+					//if the field allows nulls, then let it be null
958
+					$field_value = null;
959
+				} else {
960
+					$field_value = $field_obj->get_default_value();
961
+				}
962
+			} else {
963
+				$field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
964
+			}
965
+			$this->_fields[$field_name] = $field_value;
966
+			$this->_clear_cached_property($field_name);
967
+		}
968
+	}
969
+
970
+
971
+
972
+	/**
973
+	 * verifies that the specified field is of the correct type
974
+	 *
975
+	 * @param string $field_name
976
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
977
+	 *                                (in cases where the same property may be used for different outputs
978
+	 *                                - i.e. datetime, money etc.)
979
+	 * @return mixed
980
+	 * @throws \EE_Error
981
+	 */
982
+	public function get($field_name, $extra_cache_ref = null)
983
+	{
984
+		return $this->_get_cached_property($field_name, false, $extra_cache_ref);
985
+	}
986
+
987
+
988
+
989
+	/**
990
+	 * This method simply returns the RAW unprocessed value for the given property in this class
991
+	 *
992
+	 * @param  string $field_name A valid fieldname
993
+	 * @return mixed              Whatever the raw value stored on the property is.
994
+	 * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
995
+	 */
996
+	public function get_raw($field_name)
997
+	{
998
+		$field_settings = $this->get_model()->field_settings_for($field_name);
999
+		return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1000
+			? $this->_fields[$field_name]->format('U')
1001
+			: $this->_fields[$field_name];
1002
+	}
1003
+
1004
+
1005
+
1006
+	/**
1007
+	 * This is used to return the internal DateTime object used for a field that is a
1008
+	 * EE_Datetime_Field.
1009
+	 *
1010
+	 * @param string $field_name               The field name retrieving the DateTime object.
1011
+	 * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1012
+	 * @throws \EE_Error
1013
+	 *                                         an error is set and false returned.  If the field IS an
1014
+	 *                                         EE_Datetime_Field and but the field value is null, then
1015
+	 *                                         just null is returned (because that indicates that likely
1016
+	 *                                         this field is nullable).
1017
+	 */
1018
+	public function get_DateTime_object($field_name)
1019
+	{
1020
+		$field_settings = $this->get_model()->field_settings_for($field_name);
1021
+		if ( ! $field_settings instanceof EE_Datetime_Field) {
1022
+			EE_Error::add_error(
1023
+				sprintf(
1024
+					__(
1025
+						'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1026
+						'event_espresso'
1027
+					),
1028
+					$field_name
1029
+				),
1030
+				__FILE__,
1031
+				__FUNCTION__,
1032
+				__LINE__
1033
+			);
1034
+			return false;
1035
+		}
1036
+		return $this->_fields[$field_name];
1037
+	}
1038
+
1039
+
1040
+
1041
+	/**
1042
+	 * To be used in template to immediately echo out the value, and format it for output.
1043
+	 * Eg, should call stripslashes and whatnot before echoing
1044
+	 *
1045
+	 * @param string $field_name      the name of the field as it appears in the DB
1046
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1047
+	 *                                (in cases where the same property may be used for different outputs
1048
+	 *                                - i.e. datetime, money etc.)
1049
+	 * @return void
1050
+	 * @throws \EE_Error
1051
+	 */
1052
+	public function e($field_name, $extra_cache_ref = null)
1053
+	{
1054
+		echo $this->get_pretty($field_name, $extra_cache_ref);
1055
+	}
1056
+
1057
+
1058
+
1059
+	/**
1060
+	 * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1061
+	 * can be easily used as the value of form input.
1062
+	 *
1063
+	 * @param string $field_name
1064
+	 * @return void
1065
+	 * @throws \EE_Error
1066
+	 */
1067
+	public function f($field_name)
1068
+	{
1069
+		$this->e($field_name, 'form_input');
1070
+	}
1071
+
1072
+
1073
+
1074
+	/**
1075
+	 * @param string $field_name
1076
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1077
+	 *                                (in cases where the same property may be used for different outputs
1078
+	 *                                - i.e. datetime, money etc.)
1079
+	 * @return mixed
1080
+	 * @throws \EE_Error
1081
+	 */
1082
+	public function get_pretty($field_name, $extra_cache_ref = null)
1083
+	{
1084
+		return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1085
+	}
1086
+
1087
+
1088
+
1089
+	/**
1090
+	 * This simply returns the datetime for the given field name
1091
+	 * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1092
+	 * (and the equivalent e_date, e_time, e_datetime).
1093
+	 *
1094
+	 * @access   protected
1095
+	 * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1096
+	 * @param string   $dt_frmt      valid datetime format used for date
1097
+	 *                               (if '' then we just use the default on the field,
1098
+	 *                               if NULL we use the last-used format)
1099
+	 * @param string   $tm_frmt      Same as above except this is for time format
1100
+	 * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1101
+	 * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1102
+	 * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1103
+	 *                               if field is not a valid dtt field, or void if echoing
1104
+	 * @throws \EE_Error
1105
+	 */
1106
+	protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1107
+	{
1108
+		// clear cached property
1109
+		$this->_clear_cached_property($field_name);
1110
+		//reset format properties because they are used in get()
1111
+		$this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1112
+		$this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1113
+		if ($echo) {
1114
+			$this->e($field_name, $date_or_time);
1115
+			return '';
1116
+		}
1117
+		return $this->get($field_name, $date_or_time);
1118
+	}
1119
+
1120
+
1121
+
1122
+	/**
1123
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other echoes
1124
+	 * the pretty value for dtt)
1125
+	 *
1126
+	 * @param  string $field_name name of model object datetime field holding the value
1127
+	 * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1128
+	 * @return string            datetime value formatted
1129
+	 * @throws \EE_Error
1130
+	 */
1131
+	public function get_date($field_name, $format = '')
1132
+	{
1133
+		return $this->_get_datetime($field_name, $format, null, 'D');
1134
+	}
1135
+
1136
+
1137
+
1138
+	/**
1139
+	 * @param      $field_name
1140
+	 * @param string $format
1141
+	 * @throws \EE_Error
1142
+	 */
1143
+	public function e_date($field_name, $format = '')
1144
+	{
1145
+		$this->_get_datetime($field_name, $format, null, 'D', true);
1146
+	}
1147
+
1148
+
1149
+
1150
+	/**
1151
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other echoes
1152
+	 * the pretty value for dtt)
1153
+	 *
1154
+	 * @param  string $field_name name of model object datetime field holding the value
1155
+	 * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1156
+	 * @return string             datetime value formatted
1157
+	 * @throws \EE_Error
1158
+	 */
1159
+	public function get_time($field_name, $format = '')
1160
+	{
1161
+		return $this->_get_datetime($field_name, null, $format, 'T');
1162
+	}
1163
+
1164
+
1165
+
1166
+	/**
1167
+	 * @param      $field_name
1168
+	 * @param string $format
1169
+	 * @throws \EE_Error
1170
+	 */
1171
+	public function e_time($field_name, $format = '')
1172
+	{
1173
+		$this->_get_datetime($field_name, null, $format, 'T', true);
1174
+	}
1175
+
1176
+
1177
+
1178
+	/**
1179
+	 * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the other
1180
+	 * echoes the pretty value for dtt)
1181
+	 *
1182
+	 * @param  string $field_name name of model object datetime field holding the value
1183
+	 * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1184
+	 * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1185
+	 * @return string             datetime value formatted
1186
+	 * @throws \EE_Error
1187
+	 */
1188
+	public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1189
+	{
1190
+		return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1191
+	}
1192
+
1193
+
1194
+
1195
+	/**
1196
+	 * @param string $field_name
1197
+	 * @param string $dt_frmt
1198
+	 * @param string $tm_frmt
1199
+	 * @throws \EE_Error
1200
+	 */
1201
+	public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1202
+	{
1203
+		$this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1204
+	}
1205
+
1206
+
1207
+
1208
+	/**
1209
+	 * Get the i8ln value for a date using the WordPress @see date_i18n function.
1210
+	 *
1211
+	 * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1212
+	 * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format on the object will be used.
1213
+	 * @return string Date and time string in set locale or false if no field exists for the given
1214
+	 * @throws \EE_Error
1215
+	 *                           field name.
1216
+	 */
1217
+	public function get_i18n_datetime($field_name, $format = '')
1218
+	{
1219
+		$format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1220
+		return date_i18n(
1221
+			$format,
1222
+			EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1223
+		);
1224
+	}
1225
+
1226
+
1227
+
1228
+	/**
1229
+	 * This method validates whether the given field name is a valid field on the model object as well as it is of a type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is thrown.
1230
+	 *
1231
+	 * @param  string $field_name The field name being checked
1232
+	 * @throws EE_Error
1233
+	 * @return EE_Datetime_Field
1234
+	 */
1235
+	protected function _get_dtt_field_settings($field_name)
1236
+	{
1237
+		$field = $this->get_model()->field_settings_for($field_name);
1238
+		//check if field is dtt
1239
+		if ($field instanceof EE_Datetime_Field) {
1240
+			return $field;
1241
+		} else {
1242
+			throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1243
+				'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1244
+		}
1245
+	}
1246
+
1247
+
1248
+
1249
+
1250
+	/**
1251
+	 * NOTE ABOUT BELOW:
1252
+	 * These convenience date and time setters are for setting date and time independently.  In other words you might want to change the time on a datetime_field but leave the date the same (or vice versa).
1253
+	 * IF on the other hand you want to set both date and time at the same time, you can just use the models default set($fieldname,$value) method and make sure you send the entire datetime value for setting.
1254
+	 */
1255
+	/**
1256
+	 * sets the time on a datetime property
1257
+	 *
1258
+	 * @access protected
1259
+	 * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1260
+	 * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1261
+	 * @throws \EE_Error
1262
+	 */
1263
+	protected function _set_time_for($time, $fieldname)
1264
+	{
1265
+		$this->_set_date_time('T', $time, $fieldname);
1266
+	}
1267
+
1268
+
1269
+
1270
+	/**
1271
+	 * sets the date on a datetime property
1272
+	 *
1273
+	 * @access protected
1274
+	 * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1275
+	 * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1276
+	 * @throws \EE_Error
1277
+	 */
1278
+	protected function _set_date_for($date, $fieldname)
1279
+	{
1280
+		$this->_set_date_time('D', $date, $fieldname);
1281
+	}
1282
+
1283
+
1284
+
1285
+	/**
1286
+	 * This takes care of setting a date or time independently on a given model object property. This method also verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1287
+	 *
1288
+	 * @access protected
1289
+	 * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1290
+	 * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1291
+	 * @param string          $fieldname      the name of the field the date OR time is being set on (must match a EE_Datetime_Field property)
1292
+	 * @throws \EE_Error
1293
+	 */
1294
+	protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1295
+	{
1296
+		$field = $this->_get_dtt_field_settings($fieldname);
1297
+		$field->set_timezone($this->_timezone);
1298
+		$field->set_date_format($this->_dt_frmt);
1299
+		$field->set_time_format($this->_tm_frmt);
1300
+		switch ($what) {
1301
+			case 'T' :
1302
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1303
+					$datetime_value,
1304
+					$this->_fields[$fieldname]
1305
+				);
1306
+				break;
1307
+			case 'D' :
1308
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1309
+					$datetime_value,
1310
+					$this->_fields[$fieldname]
1311
+				);
1312
+				break;
1313
+			case 'B' :
1314
+				$this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1315
+				break;
1316
+		}
1317
+		$this->_clear_cached_property($fieldname);
1318
+	}
1319
+
1320
+
1321
+
1322
+	/**
1323
+	 * This will return a timestamp for the website timezone but ONLY when the current website timezone is different than the timezone set for the website.
1324
+	 * NOTE, this currently only works well with methods that return values.  If you use it with methods that echo values the $_timestamp property may not get reset to its original value and that could lead to some unexpected results!
1325
+	 *
1326
+	 * @access public
1327
+	 * @param string               $field_name This is the name of the field on the object that contains the date/time value being returned.
1328
+	 * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1329
+	 * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1330
+	 * @param string               $prepend    You can include something to prepend on the timestamp
1331
+	 * @param string               $append     You can include something to append on the timestamp
1332
+	 * @throws EE_Error
1333
+	 * @return string timestamp
1334
+	 */
1335
+	public function display_in_my_timezone($field_name, $callback = 'get_datetime', $args = null, $prepend = '', $append = '')
1336
+	{
1337
+		$timezone = EEH_DTT_Helper::get_timezone();
1338
+		if ($timezone === $this->_timezone) {
1339
+			return '';
1340
+		}
1341
+		$original_timezone = $this->_timezone;
1342
+		$this->set_timezone($timezone);
1343
+		$fn = (array)$field_name;
1344
+		$args = array_merge($fn, (array)$args);
1345
+		if ( ! method_exists($this, $callback)) {
1346
+			throw new EE_Error(
1347
+				sprintf(
1348
+					__(
1349
+						'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1350
+						'event_espresso'
1351
+					),
1352
+					$callback
1353
+				)
1354
+			);
1355
+		}
1356
+		$args = (array)$args;
1357
+		$return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1358
+		$this->set_timezone($original_timezone);
1359
+		return $return;
1360
+	}
1361
+
1362
+
1363
+
1364
+	/**
1365
+	 * Deletes this model object.
1366
+	 * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should override
1367
+	 * `EE_Base_Class::_delete` NOT this class.
1368
+	 *
1369
+	 * @return boolean | int
1370
+	 * @throws \EE_Error
1371
+	 */
1372
+	public function delete()
1373
+	{
1374
+		/**
1375
+		 * Called just before the `EE_Base_Class::_delete` method call.
1376
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1377
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1378
+		 * soft deletes (trash) the object and does not permanently delete it.
1379
+		 *
1380
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1381
+		 */
1382
+		do_action('AHEE__EE_Base_Class__delete__before', $this);
1383
+		$result = $this->_delete();
1384
+		/**
1385
+		 * Called just after the `EE_Base_Class::_delete` method call.
1386
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1387
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1388
+		 * soft deletes (trash) the object and does not permanently delete it.
1389
+		 *
1390
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1391
+		 * @param boolean       $result
1392
+		 */
1393
+		do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1394
+		return $result;
1395
+	}
1396
+
1397
+
1398
+
1399
+	/**
1400
+	 * Calls the specific delete method for the instantiated class.
1401
+	 * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override default
1402
+	 * functionality for "delete" (which is to call `permanently_delete`) should override this method NOT `EE_Base_Class::delete`
1403
+	 *
1404
+	 * @return bool|int
1405
+	 * @throws \EE_Error
1406
+	 */
1407
+	protected function _delete()
1408
+	{
1409
+		return $this->delete_permanently();
1410
+	}
1411
+
1412
+
1413
+
1414
+	/**
1415
+	 * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an error)
1416
+	 *
1417
+	 * @return bool | int
1418
+	 * @throws \EE_Error
1419
+	 */
1420
+	public function delete_permanently()
1421
+	{
1422
+		/**
1423
+		 * Called just before HARD deleting a model object
1424
+		 *
1425
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1426
+		 */
1427
+		do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1428
+		$model = $this->get_model();
1429
+		$result = $model->delete_permanently_by_ID($this->ID());
1430
+		$this->refresh_cache_of_related_objects();
1431
+		/**
1432
+		 * Called just after HARD deleting a model object
1433
+		 *
1434
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1435
+		 * @param boolean       $result
1436
+		 */
1437
+		do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1438
+		return $result;
1439
+	}
1440
+
1441
+
1442
+
1443
+	/**
1444
+	 * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1445
+	 * related model objects
1446
+	 *
1447
+	 * @throws \EE_Error
1448
+	 */
1449
+	public function refresh_cache_of_related_objects()
1450
+	{
1451
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1452
+			if ( ! empty($this->_model_relations[$relation_name])) {
1453
+				$related_objects = $this->_model_relations[$relation_name];
1454
+				if ($relation_obj instanceof EE_Belongs_To_Relation) {
1455
+					//this relation only stores a single model object, not an array
1456
+					//but let's make it consistent
1457
+					$related_objects = array($related_objects);
1458
+				}
1459
+				foreach ($related_objects as $related_object) {
1460
+					//only refresh their cache if they're in memory
1461
+					if ($related_object instanceof EE_Base_Class) {
1462
+						$related_object->clear_cache($this->get_model()->get_this_model_name(), $this);
1463
+					}
1464
+				}
1465
+			}
1466
+		}
1467
+	}
1468
+
1469
+
1470
+
1471
+	/**
1472
+	 *        Saves this object to the database. An array may be supplied to set some values on this
1473
+	 * object just before saving.
1474
+	 *
1475
+	 * @access public
1476
+	 * @param array $set_cols_n_values keys are field names, values are their new values,
1477
+	 *                                 if provided during the save() method (often client code will change the fields' values before calling save)
1478
+	 * @throws \EE_Error
1479
+	 * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1480
+	 *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1481
+	 */
1482
+	public function save($set_cols_n_values = array())
1483
+	{
1484
+		/**
1485
+		 * Filters the fields we're about to save on the model object
1486
+		 *
1487
+		 * @param array         $set_cols_n_values
1488
+		 * @param EE_Base_Class $model_object
1489
+		 */
1490
+		$set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values, $this);
1491
+		//set attributes as provided in $set_cols_n_values
1492
+		foreach ($set_cols_n_values as $column => $value) {
1493
+			$this->set($column, $value);
1494
+		}
1495
+		/**
1496
+		 * Saving a model object.
1497
+		 * Before we perform a save, this action is fired.
1498
+		 *
1499
+		 * @param EE_Base_Class $model_object the model object about to be saved.
1500
+		 */
1501
+		do_action('AHEE__EE_Base_Class__save__begin', $this);
1502
+		if ( ! $this->allow_persist()) {
1503
+			return 0;
1504
+		}
1505
+		//now get current attribute values
1506
+		$save_cols_n_values = $this->_fields;
1507
+		//if the object already has an ID, update it. Otherwise, insert it
1508
+		//also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1509
+		$old_assumption_concerning_value_preparation = $this->get_model()->get_assumption_concerning_values_already_prepared_by_model_object();
1510
+		$this->get_model()->assume_values_already_prepared_by_model_object(true);
1511
+		//does this model have an autoincrement PK?
1512
+		if ($this->get_model()->has_primary_key_field()) {
1513
+			if ($this->get_model()->get_primary_key_field()->is_auto_increment()) {
1514
+				//ok check if it's set, if so: update; if not, insert
1515
+				if ( ! empty($save_cols_n_values[self::_get_primary_key_name(get_class($this))])) {
1516
+					$results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1517
+				} else {
1518
+					unset($save_cols_n_values[self::_get_primary_key_name(get_class($this))]);
1519
+					$results = $this->get_model()->insert($save_cols_n_values);
1520
+					if ($results) {
1521
+						//if successful, set the primary key
1522
+						//but don't use the normal SET method, because it will check if
1523
+						//an item with the same ID exists in the mapper & db, then
1524
+						//will find it in the db (because we just added it) and THAT object
1525
+						//will get added to the mapper before we can add this one!
1526
+						//but if we just avoid using the SET method, all that headache can be avoided
1527
+						$pk_field_name = self::_get_primary_key_name(get_class($this));
1528
+						$this->_fields[$pk_field_name] = $results;
1529
+						$this->_clear_cached_property($pk_field_name);
1530
+						$this->get_model()->add_to_entity_map($this);
1531
+						$this->_update_cached_related_model_objs_fks();
1532
+					}
1533
+				}
1534
+			} else {//PK is NOT auto-increment
1535
+				//so check if one like it already exists in the db
1536
+				if ($this->get_model()->exists_by_ID($this->ID())) {
1537
+					if (WP_DEBUG && ! $this->in_entity_map()) {
1538
+						throw new EE_Error(
1539
+							sprintf(
1540
+								__('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1541
+									'event_espresso'),
1542
+								get_class($this),
1543
+								get_class($this->get_model()) . '::instance()->add_to_entity_map()',
1544
+								get_class($this->get_model()) . '::instance()->get_one_by_ID()',
1545
+								'<br />'
1546
+							)
1547
+						);
1548
+					}
1549
+					$results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1550
+				} else {
1551
+					$results = $this->get_model()->insert($save_cols_n_values);
1552
+					$this->_update_cached_related_model_objs_fks();
1553
+				}
1554
+			}
1555
+		} else {//there is NO primary key
1556
+			$already_in_db = false;
1557
+			foreach ($this->get_model()->unique_indexes() as $index) {
1558
+				$uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1559
+				if ($this->get_model()->exists(array($uniqueness_where_params))) {
1560
+					$already_in_db = true;
1561
+				}
1562
+			}
1563
+			if ($already_in_db) {
1564
+				$combined_pk_fields_n_values = array_intersect_key($save_cols_n_values, $this->get_model()->get_combined_primary_key_fields());
1565
+				$results = $this->get_model()->update($save_cols_n_values, $combined_pk_fields_n_values);
1566
+			} else {
1567
+				$results = $this->get_model()->insert($save_cols_n_values);
1568
+			}
1569
+		}
1570
+		//restore the old assumption about values being prepared by the model object
1571
+		$this->get_model()->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1572
+		/**
1573
+		 * After saving the model object this action is called
1574
+		 *
1575
+		 * @param EE_Base_Class $model_object which was just saved
1576
+		 * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1577
+		 *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1578
+		 */
1579
+		do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1580
+		return $results;
1581
+	}
1582
+
1583
+
1584
+
1585
+	/**
1586
+	 * Updates the foreign key on related models objects pointing to this to have this model object's ID
1587
+	 * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB is consistent)
1588
+	 * Especially useful in case we JUST added this model object ot the database
1589
+	 * and we want to let its cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on
1590
+	 * the transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether or not they exist in the DB (if they do, their DB records will be automatically updated)
1591
+	 *
1592
+	 * @return void
1593
+	 * @throws \EE_Error
1594
+	 */
1595
+	protected function _update_cached_related_model_objs_fks()
1596
+	{
1597
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1598
+			if ($relation_obj instanceof EE_Has_Many_Relation) {
1599
+				foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1600
+					$fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1601
+						$this->get_model()->get_this_model_name()
1602
+					);
1603
+					$related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1604
+					if ($related_model_obj_in_cache->ID()) {
1605
+						$related_model_obj_in_cache->save();
1606
+					}
1607
+				}
1608
+			}
1609
+		}
1610
+	}
1611
+
1612
+
1613
+
1614
+	/**
1615
+	 * Saves this model object and its NEW cached relations to the database.
1616
+	 * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1617
+	 * In order for that to work, we would need to mark model objects as dirty/clean...
1618
+	 * because otherwise, there's a potential for infinite looping of saving
1619
+	 * Saves the cached related model objects, and ensures the relation between them
1620
+	 * and this object and properly setup
1621
+	 *
1622
+	 * @return int ID of new model object on save; 0 on failure+
1623
+	 * @throws \EE_Error
1624
+	 */
1625
+	public function save_new_cached_related_model_objs()
1626
+	{
1627
+		//make sure this has been saved
1628
+		if ( ! $this->ID()) {
1629
+			$id = $this->save();
1630
+		} else {
1631
+			$id = $this->ID();
1632
+		}
1633
+		//now save all the NEW cached model objects  (ie they don't exist in the DB)
1634
+		foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1635
+			if ($this->_model_relations[$relationName]) {
1636
+				//is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1637
+				//or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1638
+				if ($relationObj instanceof EE_Belongs_To_Relation) {
1639
+					//add a relation to that relation type (which saves the appropriate thing in the process)
1640
+					//but ONLY if it DOES NOT exist in the DB
1641
+					/* @var $related_model_obj EE_Base_Class */
1642
+					$related_model_obj = $this->_model_relations[$relationName];
1643
+					//					if( ! $related_model_obj->ID()){
1644
+					$this->_add_relation_to($related_model_obj, $relationName);
1645
+					$related_model_obj->save_new_cached_related_model_objs();
1646
+					//					}
1647
+				} else {
1648
+					foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1649
+						//add a relation to that relation type (which saves the appropriate thing in the process)
1650
+						//but ONLY if it DOES NOT exist in the DB
1651
+						//						if( ! $related_model_obj->ID()){
1652
+						$this->_add_relation_to($related_model_obj, $relationName);
1653
+						$related_model_obj->save_new_cached_related_model_objs();
1654
+						//						}
1655
+					}
1656
+				}
1657
+			}
1658
+		}
1659
+		return $id;
1660
+	}
1661
+
1662
+
1663
+
1664
+	/**
1665
+	 * for getting a model while instantiated.
1666
+	 *
1667
+	 * @return \EEM_Base | \EEM_CPT_Base
1668
+	 */
1669
+	public function get_model()
1670
+	{
1671
+		$modelName = self::_get_model_classname(get_class($this));
1672
+		return self::_get_model_instance_with_name($modelName, $this->_timezone);
1673
+	}
1674
+
1675
+
1676
+
1677
+	/**
1678
+	 * @param $props_n_values
1679
+	 * @param $classname
1680
+	 * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1681
+	 * @throws \EE_Error
1682
+	 */
1683
+	protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1684
+	{
1685
+		//TODO: will not work for Term_Relationships because they have no PK!
1686
+		$primary_id_ref = self::_get_primary_key_name($classname);
1687
+		if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1688
+			$id = $props_n_values[$primary_id_ref];
1689
+			return self::_get_model($classname)->get_from_entity_map($id);
1690
+		}
1691
+		return false;
1692
+	}
1693
+
1694
+
1695
+
1696
+	/**
1697
+	 * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for the primary key (if present in incoming values).
1698
+	 * If there is a key in the incoming array that matches the primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not we return false.
1699
+	 *
1700
+	 * @param  array  $props_n_values   incoming array of properties and their values
1701
+	 * @param  string $classname        the classname of the child class
1702
+	 * @param null    $timezone
1703
+	 * @param array   $date_formats     incoming date_formats in an array where the first value is the
1704
+	 *                                  date_format and the second value is the time format
1705
+	 * @return mixed (EE_Base_Class|bool)
1706
+	 * @throws \EE_Error
1707
+	 */
1708
+	protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1709
+	{
1710
+		$existing = null;
1711
+		if (self::_get_model($classname)->has_primary_key_field()) {
1712
+			$primary_id_ref = self::_get_primary_key_name($classname);
1713
+			if (array_key_exists($primary_id_ref, $props_n_values)
1714
+				&& ! empty($props_n_values[$primary_id_ref])
1715
+			) {
1716
+				$existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1717
+					$props_n_values[$primary_id_ref]
1718
+				);
1719
+			}
1720
+		} elseif (self::_get_model($classname, $timezone)->has_all_combined_primary_key_fields($props_n_values)) {
1721
+			//no primary key on this model, but there's still a matching item in the DB
1722
+			$existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1723
+				self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1724
+			);
1725
+		}
1726
+		if ($existing) {
1727
+			//set date formats if present before setting values
1728
+			if ( ! empty($date_formats) && is_array($date_formats)) {
1729
+				$existing->set_date_format($date_formats[0]);
1730
+				$existing->set_time_format($date_formats[1]);
1731
+			} else {
1732
+				//set default formats for date and time
1733
+				$existing->set_date_format(get_option('date_format'));
1734
+				$existing->set_time_format(get_option('time_format'));
1735
+			}
1736
+			foreach ($props_n_values as $property => $field_value) {
1737
+				$existing->set($property, $field_value);
1738
+			}
1739
+			return $existing;
1740
+		} else {
1741
+			return false;
1742
+		}
1743
+	}
1744
+
1745
+
1746
+
1747
+	/**
1748
+	 * Gets the EEM_*_Model for this class
1749
+	 *
1750
+	 * @access public now, as this is more convenient
1751
+	 * @param      $classname
1752
+	 * @param null $timezone
1753
+	 * @throws EE_Error
1754
+	 * @return EEM_Base
1755
+	 */
1756
+	protected static function _get_model($classname, $timezone = null)
1757
+	{
1758
+		//find model for this class
1759
+		if ( ! $classname) {
1760
+			throw new EE_Error(
1761
+				sprintf(
1762
+					__(
1763
+						"What were you thinking calling _get_model(%s)?? You need to specify the class name",
1764
+						"event_espresso"
1765
+					),
1766
+					$classname
1767
+				)
1768
+			);
1769
+		}
1770
+		$modelName = self::_get_model_classname($classname);
1771
+		return self::_get_model_instance_with_name($modelName, $timezone);
1772
+	}
1773
+
1774
+
1775
+
1776
+	/**
1777
+	 * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1778
+	 *
1779
+	 * @param string $model_classname
1780
+	 * @param null   $timezone
1781
+	 * @return EEM_Base
1782
+	 */
1783
+	protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1784
+	{
1785
+		$model_classname = str_replace('EEM_', '', $model_classname);
1786
+		$model = EE_Registry::instance()->load_model($model_classname);
1787
+		$model->set_timezone($timezone);
1788
+		return $model;
1789
+	}
1790
+
1791
+
1792
+
1793
+	/**
1794
+	 * If a model name is provided (eg Registration), gets the model classname for that model.
1795
+	 * Also works if a model class's classname is provided (eg EE_Registration).
1796
+	 *
1797
+	 * @param null $model_name
1798
+	 * @return string like EEM_Attendee
1799
+	 */
1800
+	private static function _get_model_classname($model_name = null)
1801
+	{
1802
+		if (strpos($model_name, "EE_") === 0) {
1803
+			$model_classname = str_replace("EE_", "EEM_", $model_name);
1804
+		} else {
1805
+			$model_classname = "EEM_" . $model_name;
1806
+		}
1807
+		return $model_classname;
1808
+	}
1809
+
1810
+
1811
+
1812
+	/**
1813
+	 * returns the name of the primary key attribute
1814
+	 *
1815
+	 * @param null $classname
1816
+	 * @throws EE_Error
1817
+	 * @return string
1818
+	 */
1819
+	protected static function _get_primary_key_name($classname = null)
1820
+	{
1821
+		if ( ! $classname) {
1822
+			throw new EE_Error(
1823
+				sprintf(
1824
+					__("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1825
+					$classname
1826
+				)
1827
+			);
1828
+		}
1829
+		return self::_get_model($classname)->get_primary_key_field()->get_name();
1830
+	}
1831
+
1832
+
1833
+
1834
+	/**
1835
+	 * Gets the value of the primary key.
1836
+	 * If the object hasn't yet been saved, it should be whatever the model field's default was
1837
+	 * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value is.
1838
+	 * Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1839
+	 *
1840
+	 * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1841
+	 * @throws \EE_Error
1842
+	 */
1843
+	public function ID()
1844
+	{
1845
+		//now that we know the name of the variable, use a variable variable to get its value and return its
1846
+		if ($this->get_model()->has_primary_key_field()) {
1847
+			return $this->_fields[self::_get_primary_key_name(get_class($this))];
1848
+		} else {
1849
+			return $this->get_model()->get_index_primary_key_string($this->_fields);
1850
+		}
1851
+	}
1852
+
1853
+
1854
+
1855
+	/**
1856
+	 * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current model is related
1857
+	 * to a group of events, the $relationName should be 'Event', and should be a key in the EE Model's $_model_relations array.
1858
+	 * If this model object doesn't exist in the DB, just caches the related thing
1859
+	 *
1860
+	 * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1861
+	 * @param string $relationName                     eg 'Events','Question',etc.
1862
+	 *                                                 an attendee to a group, you also want to specify which role they will have in that group. So you would use this parameter to specify array('role-column-name'=>'role-id')
1863
+	 * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that allow you to further constrict the relation to being added.  However, keep in mind that the columns (keys) given must match
1864
+	 *                                                 a column on the JOIN table and currently only the HABTM models accept these additional conditions.  Also remember that if an exact match isn't found for these extra cols/val pairs,
1865
+	 *                                                 then a NEW row is created in the join table.
1866
+	 * @param null   $cache_id
1867
+	 * @throws EE_Error
1868
+	 * @return EE_Base_Class the object the relation was added to
1869
+	 */
1870
+	public function _add_relation_to($otherObjectModelObjectOrID, $relationName, $extra_join_model_fields_n_values = array(), $cache_id = null)
1871
+	{
1872
+		//if this thing exists in the DB, save the relation to the DB
1873
+		if ($this->ID()) {
1874
+			$otherObject = $this->get_model()->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName, $extra_join_model_fields_n_values);
1875
+			//clear cache so future get_many_related and get_first_related() return new results.
1876
+			$this->clear_cache($relationName, $otherObject, true);
1877
+			if ($otherObject instanceof EE_Base_Class) {
1878
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1879
+			}
1880
+		} else {
1881
+			//this thing doesn't exist in the DB,  so just cache it
1882
+			if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
1883
+				throw new EE_Error(sprintf(
1884
+					__('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s', 'event_espresso'),
1885
+					$otherObjectModelObjectOrID,
1886
+					get_class($this)
1887
+				));
1888
+			} else {
1889
+				$otherObject = $otherObjectModelObjectOrID;
1890
+			}
1891
+			$this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
1892
+		}
1893
+		if ($otherObject instanceof EE_Base_Class) {
1894
+			//fix the reciprocal relation too
1895
+			if ($otherObject->ID()) {
1896
+				//its saved so assumed relations exist in the DB, so we can just
1897
+				//clear the cache so future queries use the updated info in the DB
1898
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), null, true);
1899
+			} else {
1900
+				//it's not saved, so it caches relations like this
1901
+				$otherObject->cache($this->get_model()->get_this_model_name(), $this);
1902
+			}
1903
+		}
1904
+		return $otherObject;
1905
+	}
1906
+
1907
+
1908
+
1909
+	/**
1910
+	 * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current model is related
1911
+	 * to a group of events, the $relationName should be 'Events', and should be a key in the EE Model's $_model_relations array.
1912
+	 * If this model object doesn't exist in the DB, just removes the related thing from the cache
1913
+	 *
1914
+	 * @param mixed  $otherObjectModelObjectOrID
1915
+	 *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved to the DB yet
1916
+	 * @param string $relationName
1917
+	 * @param array  $where_query
1918
+	 *                You can optionally include an array of key=>value pairs that allow you to further constrict the relation to being added.
1919
+	 *                However, keep in mind that the columns (keys) given must match a column on the JOIN table
1920
+	 *                and currently only the HABTM models accept these additional conditions.
1921
+	 *                Also remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is created in the join table.
1922
+	 * @return EE_Base_Class the relation was removed from
1923
+	 * @throws \EE_Error
1924
+	 */
1925
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
1926
+	{
1927
+		if ($this->ID()) {
1928
+			//if this exists in the DB, save the relation change to the DB too
1929
+			$otherObject = $this->get_model()->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName, $where_query);
1930
+			$this->clear_cache($relationName, $otherObject);
1931
+		} else {
1932
+			//this doesn't exist in the DB, just remove it from the cache
1933
+			$otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
1934
+		}
1935
+		if ($otherObject instanceof EE_Base_Class) {
1936
+			$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1937
+		}
1938
+		return $otherObject;
1939
+	}
1940
+
1941
+
1942
+
1943
+	/**
1944
+	 * Removes ALL the related things for the $relationName.
1945
+	 *
1946
+	 * @param string $relationName
1947
+	 * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
1948
+	 * @return EE_Base_Class
1949
+	 * @throws \EE_Error
1950
+	 */
1951
+	public function _remove_relations($relationName, $where_query_params = array())
1952
+	{
1953
+		if ($this->ID()) {
1954
+			//if this exists in the DB, save the relation change to the DB too
1955
+			$otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
1956
+			$this->clear_cache($relationName, null, true);
1957
+		} else {
1958
+			//this doesn't exist in the DB, just remove it from the cache
1959
+			$otherObjects = $this->clear_cache($relationName, null, true);
1960
+		}
1961
+		if (is_array($otherObjects)) {
1962
+			foreach ($otherObjects as $otherObject) {
1963
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1964
+			}
1965
+		}
1966
+		return $otherObjects;
1967
+	}
1968
+
1969
+
1970
+
1971
+	/**
1972
+	 * Gets all the related model objects of the specified type. Eg, if the current class if
1973
+	 * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
1974
+	 * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
1975
+	 * because we want to get even deleted items etc.
1976
+	 *
1977
+	 * @param string $relationName key in the model's _model_relations array
1978
+	 * @param array  $query_params like EEM_Base::get_all
1979
+	 * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
1980
+	 * @throws \EE_Error
1981
+	 *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if you want IDs
1982
+	 */
1983
+	public function get_many_related($relationName, $query_params = array())
1984
+	{
1985
+		if ($this->ID()) {
1986
+			//this exists in the DB, so get the related things from either the cache or the DB
1987
+			//if there are query parameters, forget about caching the related model objects.
1988
+			if ($query_params) {
1989
+				$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
1990
+			} else {
1991
+				//did we already cache the result of this query?
1992
+				$cached_results = $this->get_all_from_cache($relationName);
1993
+				if ( ! $cached_results) {
1994
+					$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
1995
+					//if no query parameters were passed, then we got all the related model objects
1996
+					//for that relation. We can cache them then.
1997
+					foreach ($related_model_objects as $related_model_object) {
1998
+						$this->cache($relationName, $related_model_object);
1999
+					}
2000
+				} else {
2001
+					$related_model_objects = $cached_results;
2002
+				}
2003
+			}
2004
+		} else {
2005
+			//this doesn't exist in the DB, so just get the related things from the cache
2006
+			$related_model_objects = $this->get_all_from_cache($relationName);
2007
+		}
2008
+		return $related_model_objects;
2009
+	}
2010
+
2011
+
2012
+
2013
+	/**
2014
+	 * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2015
+	 * unless otherwise specified in the $query_params
2016
+	 *
2017
+	 * @param string $relation_name  model_name like 'Event', or 'Registration'
2018
+	 * @param array  $query_params   like EEM_Base::get_all's
2019
+	 * @param string $field_to_count name of field to count by. By default, uses primary key
2020
+	 * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger that by the setting $distinct to TRUE;
2021
+	 * @return int
2022
+	 */
2023
+	public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2024
+	{
2025
+		return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2026
+	}
2027
+
2028
+
2029
+
2030
+	/**
2031
+	 * Instead of getting the related model objects, simply sums up the values of the specified field.
2032
+	 * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2033
+	 *
2034
+	 * @param string $relation_name model_name like 'Event', or 'Registration'
2035
+	 * @param array  $query_params  like EEM_Base::get_all's
2036
+	 * @param string $field_to_sum  name of field to count by.
2037
+	 *                              By default, uses primary key (which doesn't make much sense, so you should probably change it)
2038
+	 * @return int
2039
+	 */
2040
+	public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2041
+	{
2042
+		return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2043
+	}
2044
+
2045
+
2046
+
2047
+	/**
2048
+	 * Gets the first (ie, one) related model object of the specified type.
2049
+	 *
2050
+	 * @param string $relationName key in the model's _model_relations array
2051
+	 * @param array  $query_params like EEM_Base::get_all
2052
+	 * @return EE_Base_Class (not an array, a single object)
2053
+	 * @throws \EE_Error
2054
+	 */
2055
+	public function get_first_related($relationName, $query_params = array())
2056
+	{
2057
+		if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2058
+			//if they've provided some query parameters, don't bother trying to cache the result
2059
+			//also make sure we're not caching the result of get_first_related
2060
+			//on a relation which should have an array of objects (because the cache might have an array of objects)
2061
+			if ($query_params || ! $this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2062
+				$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2063
+			} else {
2064
+				//first, check if we've already cached the result of this query
2065
+				$cached_result = $this->get_one_from_cache($relationName);
2066
+				if ( ! $cached_result) {
2067
+					$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2068
+					$this->cache($relationName, $related_model_object);
2069
+				} else {
2070
+					$related_model_object = $cached_result;
2071
+				}
2072
+			}
2073
+		} else {
2074
+			$related_model_object = null;
2075
+			//this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2076
+			if ($this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2077
+				$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2078
+			}
2079
+			//this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2080
+			if ( ! $related_model_object) {
2081
+				$related_model_object = $this->get_one_from_cache($relationName);
2082
+			}
2083
+		}
2084
+		return $related_model_object;
2085
+	}
2086
+
2087
+
2088
+
2089
+	/**
2090
+	 * Does a delete on all related objects of type $relationName and removes
2091
+	 * the current model object's relation to them. If they can't be deleted (because
2092
+	 * of blocking related model objects) does nothing. If the related model objects are
2093
+	 * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2094
+	 * If this model object doesn't exist yet in the DB, just removes its related things
2095
+	 *
2096
+	 * @param string $relationName
2097
+	 * @param array  $query_params like EEM_Base::get_all's
2098
+	 * @return int how many deleted
2099
+	 * @throws \EE_Error
2100
+	 */
2101
+	public function delete_related($relationName, $query_params = array())
2102
+	{
2103
+		if ($this->ID()) {
2104
+			$count = $this->get_model()->delete_related($this, $relationName, $query_params);
2105
+		} else {
2106
+			$count = count($this->get_all_from_cache($relationName));
2107
+			$this->clear_cache($relationName, null, true);
2108
+		}
2109
+		return $count;
2110
+	}
2111
+
2112
+
2113
+
2114
+	/**
2115
+	 * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2116
+	 * the current model object's relation to them. If they can't be deleted (because
2117
+	 * of blocking related model objects) just does a soft delete on it instead, if possible.
2118
+	 * If the related thing isn't a soft-deletable model object, this function is identical
2119
+	 * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2120
+	 *
2121
+	 * @param string $relationName
2122
+	 * @param array  $query_params like EEM_Base::get_all's
2123
+	 * @return int how many deleted (including those soft deleted)
2124
+	 * @throws \EE_Error
2125
+	 */
2126
+	public function delete_related_permanently($relationName, $query_params = array())
2127
+	{
2128
+		if ($this->ID()) {
2129
+			$count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2130
+		} else {
2131
+			$count = count($this->get_all_from_cache($relationName));
2132
+		}
2133
+		$this->clear_cache($relationName, null, true);
2134
+		return $count;
2135
+	}
2136
+
2137
+
2138
+
2139
+	/**
2140
+	 * is_set
2141
+	 * Just a simple utility function children can use for checking if property exists
2142
+	 *
2143
+	 * @access  public
2144
+	 * @param  string $field_name property to check
2145
+	 * @return bool                              TRUE if existing,FALSE if not.
2146
+	 */
2147
+	public function is_set($field_name)
2148
+	{
2149
+		return isset($this->_fields[$field_name]);
2150
+	}
2151
+
2152
+
2153
+
2154
+	/**
2155
+	 * Just a simple utility function children can use for checking if property (or properties) exists and throwing an EE_Error exception if they don't
2156
+	 *
2157
+	 * @param  mixed (string|array) $properties properties to check
2158
+	 * @throws EE_Error
2159
+	 * @return bool                              TRUE if existing, throw EE_Error if not.
2160
+	 */
2161
+	protected function _property_exists($properties)
2162
+	{
2163
+		foreach ((array)$properties as $property_name) {
2164
+			//first make sure this property exists
2165
+			if ( ! $this->_fields[$property_name]) {
2166
+				throw new EE_Error(
2167
+					sprintf(
2168
+						__(
2169
+							'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2170
+							'event_espresso'
2171
+						),
2172
+						$property_name
2173
+					)
2174
+				);
2175
+			}
2176
+		}
2177
+		return true;
2178
+	}
2179
+
2180
+
2181
+
2182
+	/**
2183
+	 * This simply returns an array of model fields for this object
2184
+	 *
2185
+	 * @return array
2186
+	 * @throws \EE_Error
2187
+	 */
2188
+	public function model_field_array()
2189
+	{
2190
+		$fields = $this->get_model()->field_settings(false);
2191
+		$properties = array();
2192
+		//remove prepended underscore
2193
+		foreach ($fields as $field_name => $settings) {
2194
+			$properties[$field_name] = $this->get($field_name);
2195
+		}
2196
+		return $properties;
2197
+	}
2198
+
2199
+
2200
+
2201
+	/**
2202
+	 * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2203
+	 * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called (http://www.garfieldtech.com/blog/php-magic-call)
2204
+	 * and passed the method's name and arguments.
2205
+	 * Instead of requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that happen?)
2206
+	 * they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg, filters_hook_espresso__EE_Answer__my_great_function)
2207
+	 * and accepts 2 arguments: the object on which the function was called, and an array of the original arguments passed to the function. Whatever their callback function returns will be returned by this function.
2208
+	 * Example: in functions.php (or in a plugin):
2209
+	 * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3);
2210
+	 * function my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2211
+	 * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2212
+	 *        return $previousReturnValue.$returnString;
2213
+	 * }
2214
+	 * require('EE_Answer.class.php');
2215
+	 * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2216
+	 * echo $answer->my_callback('monkeys',100);
2217
+	 * //will output "you called my_callback! and passed args:monkeys,100"
2218
+	 *
2219
+	 * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2220
+	 * @param array  $args       array of original arguments passed to the function
2221
+	 * @throws EE_Error
2222
+	 * @return mixed whatever the plugin which calls add_filter decides
2223
+	 */
2224
+	public function __call($methodName, $args)
2225
+	{
2226
+		$className = get_class($this);
2227
+		$tagName = "FHEE__{$className}__{$methodName}";
2228
+		if ( ! has_filter($tagName)) {
2229
+			throw new EE_Error(
2230
+				sprintf(
2231
+					__(
2232
+						"Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2233
+						"event_espresso"
2234
+					),
2235
+					$methodName,
2236
+					$className,
2237
+					$tagName
2238
+				)
2239
+			);
2240
+		}
2241
+		return apply_filters($tagName, null, $this, $args);
2242
+	}
2243
+
2244
+
2245
+
2246
+	/**
2247
+	 * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2248
+	 * A $previous_value can be specified in case there are many meta rows with the same key
2249
+	 *
2250
+	 * @param string $meta_key
2251
+	 * @param string $meta_value
2252
+	 * @param string $previous_value
2253
+	 * @return int records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2254
+	 * @throws \EE_Error
2255
+	 * NOTE: if the values haven't changed, returns 0
2256
+	 */
2257
+	public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2258
+	{
2259
+		$query_params = array(
2260
+			array(
2261
+				'EXM_key'  => $meta_key,
2262
+				'OBJ_ID'   => $this->ID(),
2263
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2264
+			),
2265
+		);
2266
+		if ($previous_value !== null) {
2267
+			$query_params[0]['EXM_value'] = $meta_value;
2268
+		}
2269
+		$existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2270
+		if ( ! $existing_rows_like_that) {
2271
+			return $this->add_extra_meta($meta_key, $meta_value);
2272
+		} else {
2273
+			foreach ($existing_rows_like_that as $existing_row) {
2274
+				$existing_row->save(array('EXM_value' => $meta_value));
2275
+			}
2276
+			return count($existing_rows_like_that);
2277
+		}
2278
+	}
2279
+
2280
+
2281
+
2282
+	/**
2283
+	 * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2284
+	 * no other extra meta for this model object have the same key. Returns TRUE if the
2285
+	 * extra meta row was entered, false if not
2286
+	 *
2287
+	 * @param string  $meta_key
2288
+	 * @param string  $meta_value
2289
+	 * @param boolean $unique
2290
+	 * @return boolean
2291
+	 * @throws \EE_Error
2292
+	 */
2293
+	public function add_extra_meta($meta_key, $meta_value, $unique = false)
2294
+	{
2295
+		if ($unique) {
2296
+			$existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2297
+				array(
2298
+					array(
2299
+						'EXM_key'  => $meta_key,
2300
+						'OBJ_ID'   => $this->ID(),
2301
+						'EXM_type' => $this->get_model()->get_this_model_name(),
2302
+					),
2303
+				)
2304
+			);
2305
+			if ($existing_extra_meta) {
2306
+				return false;
2307
+			}
2308
+		}
2309
+		$new_extra_meta = EE_Extra_Meta::new_instance(
2310
+			array(
2311
+				'EXM_key'   => $meta_key,
2312
+				'EXM_value' => $meta_value,
2313
+				'OBJ_ID'    => $this->ID(),
2314
+				'EXM_type'  => $this->get_model()->get_this_model_name(),
2315
+			)
2316
+		);
2317
+		$new_extra_meta->save();
2318
+		return true;
2319
+	}
2320
+
2321
+
2322
+
2323
+	/**
2324
+	 * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2325
+	 * is specified, only deletes extra meta records with that value.
2326
+	 *
2327
+	 * @param string $meta_key
2328
+	 * @param string $meta_value
2329
+	 * @return int number of extra meta rows deleted
2330
+	 * @throws \EE_Error
2331
+	 */
2332
+	public function delete_extra_meta($meta_key, $meta_value = null)
2333
+	{
2334
+		$query_params = array(
2335
+			array(
2336
+				'EXM_key'  => $meta_key,
2337
+				'OBJ_ID'   => $this->ID(),
2338
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2339
+			),
2340
+		);
2341
+		if ($meta_value !== null) {
2342
+			$query_params[0]['EXM_value'] = $meta_value;
2343
+		}
2344
+		return EEM_Extra_Meta::instance()->delete($query_params);
2345
+	}
2346
+
2347
+
2348
+
2349
+	/**
2350
+	 * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2351
+	 * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2352
+	 * You can specify $default is case you haven't found the extra meta
2353
+	 *
2354
+	 * @param string  $meta_key
2355
+	 * @param boolean $single
2356
+	 * @param mixed   $default if we don't find anything, what should we return?
2357
+	 * @return mixed single value if $single; array if ! $single
2358
+	 * @throws \EE_Error
2359
+	 */
2360
+	public function get_extra_meta($meta_key, $single = false, $default = null)
2361
+	{
2362
+		if ($single) {
2363
+			$result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2364
+			if ($result instanceof EE_Extra_Meta) {
2365
+				return $result->value();
2366
+			} else {
2367
+				return $default;
2368
+			}
2369
+		} else {
2370
+			$results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2371
+			if ($results) {
2372
+				$values = array();
2373
+				foreach ($results as $result) {
2374
+					if ($result instanceof EE_Extra_Meta) {
2375
+						$values[$result->ID()] = $result->value();
2376
+					}
2377
+				}
2378
+				return $values;
2379
+			} else {
2380
+				return $default;
2381
+			}
2382
+		}
2383
+	}
2384
+
2385
+
2386
+
2387
+	/**
2388
+	 * Returns a simple array of all the extra meta associated with this model object.
2389
+	 * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2390
+	 * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2391
+	 * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2392
+	 * If $one_of_each_key is false, it will return an array with the top-level keys being
2393
+	 * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2394
+	 * finally the extra meta's value as each sub-value. (eg array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2395
+	 *
2396
+	 * @param boolean $one_of_each_key
2397
+	 * @return array
2398
+	 * @throws \EE_Error
2399
+	 */
2400
+	public function all_extra_meta_array($one_of_each_key = true)
2401
+	{
2402
+		$return_array = array();
2403
+		if ($one_of_each_key) {
2404
+			$extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2405
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2406
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2407
+					$return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2408
+				}
2409
+			}
2410
+		} else {
2411
+			$extra_meta_objs = $this->get_many_related('Extra_Meta');
2412
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2413
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2414
+					if ( ! isset($return_array[$extra_meta_obj->key()])) {
2415
+						$return_array[$extra_meta_obj->key()] = array();
2416
+					}
2417
+					$return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2418
+				}
2419
+			}
2420
+		}
2421
+		return $return_array;
2422
+	}
2423
+
2424
+
2425
+
2426
+	/**
2427
+	 * Gets a pretty nice displayable nice for this model object. Often overridden
2428
+	 *
2429
+	 * @return string
2430
+	 * @throws \EE_Error
2431
+	 */
2432
+	public function name()
2433
+	{
2434
+		//find a field that's not a text field
2435
+		$field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2436
+		if ($field_we_can_use) {
2437
+			return $this->get($field_we_can_use->get_name());
2438
+		} else {
2439
+			$first_few_properties = $this->model_field_array();
2440
+			$first_few_properties = array_slice($first_few_properties, 0, 3);
2441
+			$name_parts = array();
2442
+			foreach ($first_few_properties as $name => $value) {
2443
+				$name_parts[] = "$name:$value";
2444
+			}
2445
+			return implode(",", $name_parts);
2446
+		}
2447
+	}
2448
+
2449
+
2450
+
2451
+	/**
2452
+	 * in_entity_map
2453
+	 * Checks if this model object has been proven to already be in the entity map
2454
+	 *
2455
+	 * @return boolean
2456
+	 * @throws \EE_Error
2457
+	 */
2458
+	public function in_entity_map()
2459
+	{
2460
+		if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2461
+			//well, if we looked, did we find it in the entity map?
2462
+			return true;
2463
+		} else {
2464
+			return false;
2465
+		}
2466
+	}
2467
+
2468
+
2469
+
2470
+	/**
2471
+	 * refresh_from_db
2472
+	 * Makes sure the fields and values on this model object are in-sync with what's in the database.
2473
+	 *
2474
+	 * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2475
+	 * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2476
+	 */
2477
+	public function refresh_from_db()
2478
+	{
2479
+		if ($this->ID() && $this->in_entity_map()) {
2480
+			$this->get_model()->refresh_entity_map_from_db($this->ID());
2481
+		} else {
2482
+			//if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2483
+			//if it has an ID but it's not in the map, and you're asking me to refresh it
2484
+			//that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2485
+			//absolutely nothing in it for this ID
2486
+			if (WP_DEBUG) {
2487
+				throw new EE_Error(
2488
+					sprintf(
2489
+						__('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2490
+							'event_espresso'),
2491
+						$this->ID(),
2492
+						get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2493
+						get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2494
+					)
2495
+				);
2496
+			}
2497
+		}
2498
+	}
2499
+
2500
+
2501
+
2502
+	/**
2503
+	 * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2504
+	 * (probably a bad assumption they have made, oh well)
2505
+	 *
2506
+	 * @return string
2507
+	 */
2508
+	public function __toString()
2509
+	{
2510
+		try {
2511
+			return sprintf('%s (%s)', $this->name(), $this->ID());
2512
+		} catch (Exception $e) {
2513
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2514
+			return '';
2515
+		}
2516
+	}
2517
+
2518
+
2519
+
2520
+	/**
2521
+	 * Clear related model objects if they're already in the DB, because otherwise when we
2522
+	 * UN-serialize this model object we'll need to be careful to add them to the entity map.
2523
+	 * This means if we have made changes to those related model objects, and want to unserialize
2524
+	 * the this model object on a subsequent request, changes to those related model objects will be lost.
2525
+	 * Instead, those related model objects should be directly serialized and stored.
2526
+	 * Eg, the following won't work:
2527
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2528
+	 * $att = $reg->attendee();
2529
+	 * $att->set( 'ATT_fname', 'Dirk' );
2530
+	 * update_option( 'my_option', serialize( $reg ) );
2531
+	 * //END REQUEST
2532
+	 * //START NEXT REQUEST
2533
+	 * $reg = get_option( 'my_option' );
2534
+	 * $reg->attendee()->save();
2535
+	 * And would need to be replace with:
2536
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2537
+	 * $att = $reg->attendee();
2538
+	 * $att->set( 'ATT_fname', 'Dirk' );
2539
+	 * update_option( 'my_option', serialize( $reg ) );
2540
+	 * //END REQUEST
2541
+	 * //START NEXT REQUEST
2542
+	 * $att = get_option( 'my_option' );
2543
+	 * $att->save();
2544
+	 *
2545
+	 * @return array
2546
+	 * @throws \EE_Error
2547
+	 */
2548
+	public function __sleep()
2549
+	{
2550
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
2551
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
2552
+				$classname = 'EE_' . $this->get_model()->get_this_model_name();
2553
+				if (
2554
+					$this->get_one_from_cache($relation_name) instanceof $classname
2555
+					&& $this->get_one_from_cache($relation_name)->ID()
2556
+				) {
2557
+					$this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2558
+				}
2559
+			}
2560
+		}
2561
+		$this->_props_n_values_provided_in_constructor = array();
2562
+		return array_keys(get_object_vars($this));
2563
+	}
2564
+
2565
+
2566
+
2567
+	/**
2568
+	 * restore _props_n_values_provided_in_constructor
2569
+	 * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2570
+	 * and therefore should NOT be used to determine if state change has occurred since initial construction.
2571
+	 * At best, you would only be able to detect if state change has occurred during THIS request.
2572
+	 */
2573
+	public function __wakeup()
2574
+	{
2575
+		$this->_props_n_values_provided_in_constructor = $this->_fields;
2576
+	}
2577 2577
 
2578 2578
 
2579 2579
 
Please login to merge, or discard this patch.