Completed
Branch BUG/pantheon-session-fatal-2 (2f2c99)
by
unknown
19:07 queued 09:56
created
data_migration_scripts/4_1_0_stages/EE_DMS_4_1_0_attendees.dmsstage.php 2 patches
Indentation   +598 added lines, -602 removed lines patch added patch discarded remove patch
@@ -53,10 +53,6 @@  discard block
 block discarded – undo
53 53
 ENGINE=InnoDB
54 54
 AUTO_INCREMENT=3
55 55
 ;
56
-
57
-
58
-
59
-
60 56
  * 4.1 Attendee tables and fields:
61 57
  * $this->_tables = array(
62 58
             'Attendee_CPT'=> new EE_Primary_Table('posts', 'ID'),
@@ -186,634 +182,634 @@  discard block
 block discarded – undo
186 182
  */
187 183
 class EE_DMS_4_1_0_attendees extends EE_Data_Migration_Script_Stage_Table
188 184
 {
189
-    private $_new_attendee_cpt_table;
190
-    private $_new_attendee_meta_table;
191
-    private $_new_reg_table;
192
-    private $_new_transaction_table;
193
-    private $_new_payment_table;
194
-    private $_new_line_table;
195
-    private $_old_mer_table;
196
-    private $_new_ticket_table;
197
-    private $_new_ticket_datetime_table;
198
-    private $_new_datetime_table;
199
-    private $_new_datetime_ticket_table;
200
-    private $_new_price_table;
201
-    private $_new_ticket_price_table;
202
-    /**
203
-     * Rememebrs whether or not the mer table exists
204
-     * @var boolean
205
-     */
206
-    private $_mer_tables_exist = null;
207
-    public function __construct()
208
-    {
209
-        global $wpdb;
210
-        $this->_pretty_name = __("Attendees", "event_espresso");
211
-        $this->_old_table = $wpdb->prefix."events_attendee";
212
-        $this->_extra_where_sql = 'AS att
185
+	private $_new_attendee_cpt_table;
186
+	private $_new_attendee_meta_table;
187
+	private $_new_reg_table;
188
+	private $_new_transaction_table;
189
+	private $_new_payment_table;
190
+	private $_new_line_table;
191
+	private $_old_mer_table;
192
+	private $_new_ticket_table;
193
+	private $_new_ticket_datetime_table;
194
+	private $_new_datetime_table;
195
+	private $_new_datetime_ticket_table;
196
+	private $_new_price_table;
197
+	private $_new_ticket_price_table;
198
+	/**
199
+	 * Rememebrs whether or not the mer table exists
200
+	 * @var boolean
201
+	 */
202
+	private $_mer_tables_exist = null;
203
+	public function __construct()
204
+	{
205
+		global $wpdb;
206
+		$this->_pretty_name = __("Attendees", "event_espresso");
207
+		$this->_old_table = $wpdb->prefix."events_attendee";
208
+		$this->_extra_where_sql = 'AS att
213 209
             INNER JOIN ' . $wpdb->prefix . 'events_detail AS e ON att.event_id=e.id
214 210
             WHERE e.event_status!="D"';
215
-        $this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
216
-        $this->_new_attendee_cpt_table = $wpdb->posts;
217
-        $this->_new_attendee_meta_table = $wpdb->prefix."esp_attendee_meta";
218
-        $this->_new_reg_table = $wpdb->prefix."esp_registration";
219
-        $this->_new_transaction_table = $wpdb->prefix."esp_transaction";
220
-        $this->_new_payment_table = $wpdb->prefix."esp_payment";
221
-        $this->_new_line_table = $wpdb->prefix."esp_line_item";
222
-        $this->_new_ticket_table = $wpdb->prefix."esp_ticket";
223
-        $this->_new_ticket_datetime_table = $wpdb->prefix."esp_datetime_ticket";
224
-        $this->_new_datetime_table = $wpdb->prefix."esp_datetime";
225
-        $this->_new_datetime_ticket_table = $wpdb->prefix."esp_datetime_ticket";
226
-        $this->_new_price_table = $wpdb->prefix."esp_price";
227
-        $this->_new_ticket_price_table = $wpdb->prefix."esp_ticket_price";
228
-        parent::__construct();
229
-    }
211
+		$this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
212
+		$this->_new_attendee_cpt_table = $wpdb->posts;
213
+		$this->_new_attendee_meta_table = $wpdb->prefix."esp_attendee_meta";
214
+		$this->_new_reg_table = $wpdb->prefix."esp_registration";
215
+		$this->_new_transaction_table = $wpdb->prefix."esp_transaction";
216
+		$this->_new_payment_table = $wpdb->prefix."esp_payment";
217
+		$this->_new_line_table = $wpdb->prefix."esp_line_item";
218
+		$this->_new_ticket_table = $wpdb->prefix."esp_ticket";
219
+		$this->_new_ticket_datetime_table = $wpdb->prefix."esp_datetime_ticket";
220
+		$this->_new_datetime_table = $wpdb->prefix."esp_datetime";
221
+		$this->_new_datetime_ticket_table = $wpdb->prefix."esp_datetime_ticket";
222
+		$this->_new_price_table = $wpdb->prefix."esp_price";
223
+		$this->_new_ticket_price_table = $wpdb->prefix."esp_ticket_price";
224
+		parent::__construct();
225
+	}
230 226
 
231
-    protected function _migrate_old_row($old_row)
232
-    {
233
-        // first check if there's already a new attendee with similar characteristics
234
-        $new_att_id = $this->_find_attendee_cpt_matching($old_row);
235
-        if (! $new_att_id) {
236
-            $new_att_id = $this->_insert_new_attendee_cpt($old_row);
237
-            if (! $new_att_id) {
238
-                // if we couldnt even make an attendee, abandon all hope
239
-                return false;
240
-            }
241
-            $new_att_meta_id = $this->_insert_attendee_meta_row($old_row, $new_att_id);
242
-            if ($new_att_meta_id) {
243
-                $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_meta_table, $new_att_meta_id);
244
-            }
245
-        }
246
-        $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
227
+	protected function _migrate_old_row($old_row)
228
+	{
229
+		// first check if there's already a new attendee with similar characteristics
230
+		$new_att_id = $this->_find_attendee_cpt_matching($old_row);
231
+		if (! $new_att_id) {
232
+			$new_att_id = $this->_insert_new_attendee_cpt($old_row);
233
+			if (! $new_att_id) {
234
+				// if we couldnt even make an attendee, abandon all hope
235
+				return false;
236
+			}
237
+			$new_att_meta_id = $this->_insert_attendee_meta_row($old_row, $new_att_id);
238
+			if ($new_att_meta_id) {
239
+				$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_meta_table, $new_att_meta_id);
240
+			}
241
+		}
242
+		$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
247 243
 
248
-        $txn_id = $this->_insert_new_transaction($old_row);
249
-        if (! $txn_id) {
250
-            // if we couldnt make the transaction, also abandon all hope
251
-            return false;
252
-        }
253
-        $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_transaction_table, $txn_id);
254
-        $pay_id = $this->_insert_new_payment($old_row, $txn_id);
255
-        if ($pay_id) {
256
-            $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_payment_table, $pay_id);
257
-        }
244
+		$txn_id = $this->_insert_new_transaction($old_row);
245
+		if (! $txn_id) {
246
+			// if we couldnt make the transaction, also abandon all hope
247
+			return false;
248
+		}
249
+		$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_transaction_table, $txn_id);
250
+		$pay_id = $this->_insert_new_payment($old_row, $txn_id);
251
+		if ($pay_id) {
252
+			$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_payment_table, $pay_id);
253
+		}
258 254
 
259 255
 
260
-        // even if there was no payment, we can go ahead with adding the reg
261
-        $new_regs = $this->_insert_new_registrations($old_row, $new_att_id, $txn_id);
262
-        if ($new_regs) {
263
-            $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_reg_table, $new_regs);
264
-        }
265
-    }
266
-    /**
267
-     * Checks if there's already an attendee CPT in the db that has the same
268
-     * first and last name, and email. If so, returns its ID as an int.
269
-     * @global type $wpdb
270
-     * @param array $old_attendee
271
-     * @return int
272
-     */
273
-    private function _find_attendee_cpt_matching($old_attendee)
274
-    {
275
-        global $wpdb;
276
-        $existing_attendee_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_new_attendee_cpt_table." AS cpt INNER JOIN ".$this->_new_attendee_meta_table." AS meta ON cpt.ID = meta.ATT_ID WHERE meta.ATT_fname = %s AND meta.ATT_lname = %s AND meta.ATT_email = %s LIMIT 1", $old_attendee['fname'], $old_attendee['lname'], $old_attendee['email']));
277
-        return intval($existing_attendee_id);
278
-    }
279
-    private function _insert_new_attendee_cpt($old_attendee)
280
-    {
281
-        global $wpdb;
282
-        $cols_n_values = array(
283
-            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
284
-            'post_content'=>'',// ATT_bio
285
-            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
286
-            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
287
-            'post_excerpt'=>'',// ATT_short_bio
288
-            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
289
-            'post_author'=>0,// ATT_author
290
-            'post_parent'=>0,// ATT_parent
291
-            'post_type'=>'espresso_attendees',// post_type
292
-            'post_status'=>'publish'// status
293
-        );
294
-        $datatypes = array(
295
-            '%s',// ATT_full_name
296
-            '%s',// ATT_bio
297
-            '%s',// ATT_slug
298
-            '%s',// ATT_created
299
-            '%s',// ATT_short_bio
300
-            '%s',// ATT_modified
301
-            '%d',// ATT_author
302
-            '%d',// ATT_parent
303
-            '%s',// post_type
304
-            '%s',// status
305
-        );
306
-        $success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
307
-        if (! $success) {
308
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
309
-            return 0;
310
-        }
311
-        $new_id = $wpdb->insert_id;
312
-        return $new_id;
313
-    }
256
+		// even if there was no payment, we can go ahead with adding the reg
257
+		$new_regs = $this->_insert_new_registrations($old_row, $new_att_id, $txn_id);
258
+		if ($new_regs) {
259
+			$this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_reg_table, $new_regs);
260
+		}
261
+	}
262
+	/**
263
+	 * Checks if there's already an attendee CPT in the db that has the same
264
+	 * first and last name, and email. If so, returns its ID as an int.
265
+	 * @global type $wpdb
266
+	 * @param array $old_attendee
267
+	 * @return int
268
+	 */
269
+	private function _find_attendee_cpt_matching($old_attendee)
270
+	{
271
+		global $wpdb;
272
+		$existing_attendee_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_new_attendee_cpt_table." AS cpt INNER JOIN ".$this->_new_attendee_meta_table." AS meta ON cpt.ID = meta.ATT_ID WHERE meta.ATT_fname = %s AND meta.ATT_lname = %s AND meta.ATT_email = %s LIMIT 1", $old_attendee['fname'], $old_attendee['lname'], $old_attendee['email']));
273
+		return intval($existing_attendee_id);
274
+	}
275
+	private function _insert_new_attendee_cpt($old_attendee)
276
+	{
277
+		global $wpdb;
278
+		$cols_n_values = array(
279
+			'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
280
+			'post_content'=>'',// ATT_bio
281
+			'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
282
+			'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
283
+			'post_excerpt'=>'',// ATT_short_bio
284
+			'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
285
+			'post_author'=>0,// ATT_author
286
+			'post_parent'=>0,// ATT_parent
287
+			'post_type'=>'espresso_attendees',// post_type
288
+			'post_status'=>'publish'// status
289
+		);
290
+		$datatypes = array(
291
+			'%s',// ATT_full_name
292
+			'%s',// ATT_bio
293
+			'%s',// ATT_slug
294
+			'%s',// ATT_created
295
+			'%s',// ATT_short_bio
296
+			'%s',// ATT_modified
297
+			'%d',// ATT_author
298
+			'%d',// ATT_parent
299
+			'%s',// post_type
300
+			'%s',// status
301
+		);
302
+		$success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
303
+		if (! $success) {
304
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
305
+			return 0;
306
+		}
307
+		$new_id = $wpdb->insert_id;
308
+		return $new_id;
309
+	}
314 310
 
315
-    private function _insert_attendee_meta_row($old_attendee, $new_attendee_cpt_id)
316
-    {
317
-        global $wpdb;
318
-        // get the state and country ids from the old row
319
-        try {
320
-            $new_country = $this->get_migration_script()->get_or_create_country(stripslashes($old_attendee['country_id']));
321
-            $new_country_iso = $new_country['CNT_ISO'];
322
-        } catch (EE_Error $exception) {
323
-            $new_country_iso = $this->get_migration_script()->get_default_country_iso();
324
-        }
325
-        try {
326
-            $new_state = $this->get_migration_script()->get_or_create_state(stripslashes($old_attendee['state']), $new_country_iso);
327
-            $new_state_id = $new_state['STA_ID'];
328
-        } catch (EE_Error $exception) {
329
-            $new_state_id = 0;
330
-        }
331
-        $cols_n_values = array(
332
-            'ATT_ID'=>$new_attendee_cpt_id,
333
-            'ATT_fname'=>stripslashes($old_attendee['fname']),
334
-            'ATT_lname'=>stripslashes($old_attendee['lname']),
335
-            'ATT_address'=>stripslashes($old_attendee['address']),
336
-            'ATT_address2'=>stripslashes($old_attendee['address2']),
337
-            'ATT_city'=>stripslashes($old_attendee['city']),
338
-            'STA_ID'=>$new_state_id,
339
-            'CNT_ISO'=>$new_country_iso,
340
-            'ATT_zip'=>stripslashes($old_attendee['zip']),
341
-            'ATT_email'=>stripslashes($old_attendee['email']),
342
-            'ATT_phone'=>stripslashes($old_attendee['phone']),
343
-        );
344
-        $datatypes = array(
345
-            '%d',// ATT_ID
346
-            '%s',// ATT_fname
347
-            '%s',// ATT_lname
348
-            '%s',// ATT_address
349
-            '%s',// ATT_address2
350
-            '%s',// ATT_city
351
-            '%d',// STA_ID
352
-            '%s',// CNT_ISO
353
-            '%s',// ATT_zip
354
-            '%s',// ATT_email
355
-            '%s',// ATT_phone
356
-        );
357
-        $success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
358
-        if (! $success) {
359
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
360
-            return 0;
361
-        }
362
-        $new_id = $wpdb->insert_id;
363
-        return $new_id;
364
-    }
311
+	private function _insert_attendee_meta_row($old_attendee, $new_attendee_cpt_id)
312
+	{
313
+		global $wpdb;
314
+		// get the state and country ids from the old row
315
+		try {
316
+			$new_country = $this->get_migration_script()->get_or_create_country(stripslashes($old_attendee['country_id']));
317
+			$new_country_iso = $new_country['CNT_ISO'];
318
+		} catch (EE_Error $exception) {
319
+			$new_country_iso = $this->get_migration_script()->get_default_country_iso();
320
+		}
321
+		try {
322
+			$new_state = $this->get_migration_script()->get_or_create_state(stripslashes($old_attendee['state']), $new_country_iso);
323
+			$new_state_id = $new_state['STA_ID'];
324
+		} catch (EE_Error $exception) {
325
+			$new_state_id = 0;
326
+		}
327
+		$cols_n_values = array(
328
+			'ATT_ID'=>$new_attendee_cpt_id,
329
+			'ATT_fname'=>stripslashes($old_attendee['fname']),
330
+			'ATT_lname'=>stripslashes($old_attendee['lname']),
331
+			'ATT_address'=>stripslashes($old_attendee['address']),
332
+			'ATT_address2'=>stripslashes($old_attendee['address2']),
333
+			'ATT_city'=>stripslashes($old_attendee['city']),
334
+			'STA_ID'=>$new_state_id,
335
+			'CNT_ISO'=>$new_country_iso,
336
+			'ATT_zip'=>stripslashes($old_attendee['zip']),
337
+			'ATT_email'=>stripslashes($old_attendee['email']),
338
+			'ATT_phone'=>stripslashes($old_attendee['phone']),
339
+		);
340
+		$datatypes = array(
341
+			'%d',// ATT_ID
342
+			'%s',// ATT_fname
343
+			'%s',// ATT_lname
344
+			'%s',// ATT_address
345
+			'%s',// ATT_address2
346
+			'%s',// ATT_city
347
+			'%d',// STA_ID
348
+			'%s',// CNT_ISO
349
+			'%s',// ATT_zip
350
+			'%s',// ATT_email
351
+			'%s',// ATT_phone
352
+		);
353
+		$success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
354
+		if (! $success) {
355
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
356
+			return 0;
357
+		}
358
+		$new_id = $wpdb->insert_id;
359
+		return $new_id;
360
+	}
365 361
 
366
-    /**
367
-     * Note: we don't necessarily create a new transaction for each attendee row.
368
-     * Only if the old attendee 'is_primary' is true; otherwise we find the old attendee row that
369
-     * 'is_primary' and has the same 'txn_id', then we return ITS new transaction id
370
-     * @global type $wpdb
371
-     * @param type $old_attendee
372
-     * @return int new transaction id
373
-     */
374
-    private function _insert_new_transaction($old_attendee)
375
-    {
376
-        global $wpdb;
362
+	/**
363
+	 * Note: we don't necessarily create a new transaction for each attendee row.
364
+	 * Only if the old attendee 'is_primary' is true; otherwise we find the old attendee row that
365
+	 * 'is_primary' and has the same 'txn_id', then we return ITS new transaction id
366
+	 * @global type $wpdb
367
+	 * @param type $old_attendee
368
+	 * @return int new transaction id
369
+	 */
370
+	private function _insert_new_transaction($old_attendee)
371
+	{
372
+		global $wpdb;
377 373
 
378
-        // first: let's check for an existing transaction for this old attendee
379
-        if (intval($old_attendee['is_primary'])) {// primary attendee, so create txn
380
-            $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
381
-        } else { // non-primary attendee, so find its primary attendee's transaction
382
-            $primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
383
-            if (! $primary_attendee_old_id) {
384
-                $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
385
-                $primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
386
-            }
387
-            $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
388
-            if (! $txn_id) {
389
-                $this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
390
-                $txn_id = 0;
391
-            }
392
-        }
393
-        // if there isn't yet a transaction row for this, create one
394
-        // (so even if it was a non-primary attendee with no EE3 primary attendee,
395
-        // it ought to have SOME transaction, so we'll make one)
396
-        if (! $txn_id) {
397
-            // maps 3.1 payment stati onto 4.1 transaction stati
398
-            $txn_status_mapping = array(
399
-                'Completed'=>'TCM',
400
-                'Pending'=>'TIN',
401
-                'Payment Declined'=>'TIN',
402
-                'Incomplete'=>'TIN',
403
-                'Not Completed'=>'TIN',
404
-                'Cancelled'=>'TIN',
405
-                'Declined'=>'TIN'
406
-            );
407
-            $STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
408
-            $cols_n_values = array(
409
-                'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
410
-                'TXN_total'=>floatval($old_attendee['total_cost']),
411
-                'TXN_paid'=>floatval($old_attendee['amount_pd']),
412
-                'STS_ID'=>$STS_ID,
413
-                'TXN_hash_salt'=>$old_attendee['hashSalt']
414
-            );
415
-            $datatypes = array(
416
-                '%s',// TXN_timestamp
417
-                '%f',// TXN_total
418
-                '%f',// TXN_paid
419
-                '%s',// STS_ID
420
-                '%s',// TXN_hash_salt
421
-            );
422
-            $success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
423
-            if (! $success) {
424
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
425
-                return 0;
426
-            }
427
-            $txn_id = $wpdb->insert_id;
428
-        }
374
+		// first: let's check for an existing transaction for this old attendee
375
+		if (intval($old_attendee['is_primary'])) {// primary attendee, so create txn
376
+			$txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
377
+		} else { // non-primary attendee, so find its primary attendee's transaction
378
+			$primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
379
+			if (! $primary_attendee_old_id) {
380
+				$primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
381
+				$primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
382
+			}
383
+			$txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
384
+			if (! $txn_id) {
385
+				$this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
386
+				$txn_id = 0;
387
+			}
388
+		}
389
+		// if there isn't yet a transaction row for this, create one
390
+		// (so even if it was a non-primary attendee with no EE3 primary attendee,
391
+		// it ought to have SOME transaction, so we'll make one)
392
+		if (! $txn_id) {
393
+			// maps 3.1 payment stati onto 4.1 transaction stati
394
+			$txn_status_mapping = array(
395
+				'Completed'=>'TCM',
396
+				'Pending'=>'TIN',
397
+				'Payment Declined'=>'TIN',
398
+				'Incomplete'=>'TIN',
399
+				'Not Completed'=>'TIN',
400
+				'Cancelled'=>'TIN',
401
+				'Declined'=>'TIN'
402
+			);
403
+			$STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
404
+			$cols_n_values = array(
405
+				'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
406
+				'TXN_total'=>floatval($old_attendee['total_cost']),
407
+				'TXN_paid'=>floatval($old_attendee['amount_pd']),
408
+				'STS_ID'=>$STS_ID,
409
+				'TXN_hash_salt'=>$old_attendee['hashSalt']
410
+			);
411
+			$datatypes = array(
412
+				'%s',// TXN_timestamp
413
+				'%f',// TXN_total
414
+				'%f',// TXN_paid
415
+				'%s',// STS_ID
416
+				'%s',// TXN_hash_salt
417
+			);
418
+			$success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
419
+			if (! $success) {
420
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
421
+				return 0;
422
+			}
423
+			$txn_id = $wpdb->insert_id;
424
+		}
429 425
 
430
-        return $txn_id;
431
-    }
432
-    /**
433
-     * Detects if the MER tables exist
434
-     * @global type $wpdb
435
-     * @return boolean
436
-     */
437
-    private function _mer_tables_exist()
438
-    {
439
-        if ($this->_mer_tables_exist === null) {
440
-            global $wpdb;
426
+		return $txn_id;
427
+	}
428
+	/**
429
+	 * Detects if the MER tables exist
430
+	 * @global type $wpdb
431
+	 * @return boolean
432
+	 */
433
+	private function _mer_tables_exist()
434
+	{
435
+		if ($this->_mer_tables_exist === null) {
436
+			global $wpdb;
441 437
 
442
-            if ($wpdb->get_var("SHOW TABLES LIKE '{$this->_old_mer_table}'") != $this->_old_mer_table) {
443
-                $this->_mer_tables_exist = false;
444
-            } else {
445
-                $this->_mer_tables_exist = true;
446
-            }
447
-        }
448
-        return $this->_mer_tables_exist;
449
-    }
438
+			if ($wpdb->get_var("SHOW TABLES LIKE '{$this->_old_mer_table}'") != $this->_old_mer_table) {
439
+				$this->_mer_tables_exist = false;
440
+			} else {
441
+				$this->_mer_tables_exist = true;
442
+			}
443
+		}
444
+		return $this->_mer_tables_exist;
445
+	}
450 446
 
451
-    /**
452
-     * Gets the 4.1 registration's status given the 3.1 attendee row. We consider
453
-     * whether the event required pre-approval or not,a dn the 4.1 payment status.
454
-     * @global type $wpdb
455
-     * @param type $old_attendee_row
456
-     * @return string
457
-     */
458
-    private function _get_reg_status_for_old_payment_status($old_attendee_row)
459
-    {
460
-        // need event default reg status and if pre_approval was required
461
-        global $wpdb;
462
-        $event_required_pre_approval = $wpdb->get_var($wpdb->prepare("SELECT require_pre_approval FROM ".$wpdb->prefix."events_detail WHERE id = %d", $old_attendee_row['event_id']));
463
-        return $this->get_migration_script()->convert_3_1_payment_status_to_4_1_STS_ID(
464
-            $old_attendee_row['payment_status'],
465
-            intval($event_required_pre_approval) && intval($old_attendee_row['pre_approve'])
466
-        );
467
-    }
468
-    /**
469
-     * Adds however many rgistrations are indicated by the old attendee's QUANTITY field,
470
-     * and returns an array of their IDs
471
-     * @global type $wpdb
472
-     * @param array $old_attendee
473
-     * @param int $new_attendee_id
474
-     * @param int $new_txn_id
475
-     * @return array of new registratio ids
476
-     */
477
-    private function _insert_new_registrations($old_attendee, $new_attendee_id, $new_txn_id)
478
-    {
479
-        global $wpdb;
447
+	/**
448
+	 * Gets the 4.1 registration's status given the 3.1 attendee row. We consider
449
+	 * whether the event required pre-approval or not,a dn the 4.1 payment status.
450
+	 * @global type $wpdb
451
+	 * @param type $old_attendee_row
452
+	 * @return string
453
+	 */
454
+	private function _get_reg_status_for_old_payment_status($old_attendee_row)
455
+	{
456
+		// need event default reg status and if pre_approval was required
457
+		global $wpdb;
458
+		$event_required_pre_approval = $wpdb->get_var($wpdb->prepare("SELECT require_pre_approval FROM ".$wpdb->prefix."events_detail WHERE id = %d", $old_attendee_row['event_id']));
459
+		return $this->get_migration_script()->convert_3_1_payment_status_to_4_1_STS_ID(
460
+			$old_attendee_row['payment_status'],
461
+			intval($event_required_pre_approval) && intval($old_attendee_row['pre_approve'])
462
+		);
463
+	}
464
+	/**
465
+	 * Adds however many rgistrations are indicated by the old attendee's QUANTITY field,
466
+	 * and returns an array of their IDs
467
+	 * @global type $wpdb
468
+	 * @param array $old_attendee
469
+	 * @param int $new_attendee_id
470
+	 * @param int $new_txn_id
471
+	 * @return array of new registratio ids
472
+	 */
473
+	private function _insert_new_registrations($old_attendee, $new_attendee_id, $new_txn_id)
474
+	{
475
+		global $wpdb;
480 476
 
481
-        $STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
482
-        $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
483
-        if (! $new_event_id) {
484
-            $this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
485
-        }
477
+		$STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
478
+		$new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
479
+		if (! $new_event_id) {
480
+			$this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
481
+		}
486 482
 
487
-        $ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
488
-        if (! $ticket_id) {
489
-            $ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
490
-            $this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
491
-        }
492
-        $regs_on_this_row = intval($old_attendee['quantity']);
493
-        $new_regs = array();
494
-        // 4 cases we need to account for:
495
-        // 1 old attendee_details row with a quantity of X (no mer)
496
-        // Y old attendee_details rows with a quantity of 1 (no mer) joined by their common registration_id
497
-        // Y old attendee_details rows with a quantity of x (because of mer)
498
-        // Y old attendee_details rows with a quantity of 1 (because of mer) joined by wp_events_multi_event_registration_id_group
499
-        for ($count = 1; $count <= $regs_on_this_row; $count++) {
500
-            // sum regs on older rows
501
-            $regs_on_this_event_and_txn = $this->_sum_old_attendees_on_old_txn($old_attendee, true);
502
-            $cols_n_values = array(
503
-                'EVT_ID'=>$new_event_id,
504
-                'ATT_ID'=>$new_attendee_id,
505
-                'TXN_ID'=>$new_txn_id,
506
-                'TKT_ID'=>$ticket_id,
507
-                'STS_ID'=>$STS_ID,
508
-                'REG_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
509
-                'REG_final_price'=>$old_attendee['final_price'],
510
-                'REG_session'=> substr($old_attendee['attendee_session'], 0, 44),
511
-                'REG_code'=>sanitize_key($old_attendee['registration_id']),
512
-                'REG_url_link'=>  sanitize_key($old_attendee['registration_id'].'-'.$count),
513
-                'REG_count'=>$regs_on_this_event_and_txn + $count,
514
-                'REG_group_size'=>$this->_sum_old_attendees_on_old_txn($old_attendee, false),
515
-                'REG_att_is_going'=>true,
516
-                'REG_deleted'=>false
517
-            );
518
-            $datatypes = array(
519
-                '%d',// EVT_ID
520
-                '%d',// ATT_ID
521
-                '%d',// TXN_ID
522
-                '%d',// TKT_ID
523
-                '%s',// STS_ID
524
-                '%s',// REG_date
525
-                '%f',// REG_final_price
526
-                '%s',// REG_session
527
-                '%s',// REG_code
528
-                '%s',// REG_url_link
529
-                '%d',// REG_count
530
-                '%d',// REG_group_size
531
-                '%d',// REG_att_is_going
532
-                '%d',// REG_deleted
533
-            );
534
-            $success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
535
-            if (! $success) {
536
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
537
-                return 0;
538
-            }
539
-            $cols_n_values['REG_ID'] = $wpdb->insert_id;
540
-            $new_regs[] = $wpdb->insert_id;
541
-        }
542
-        $this->_add_regs_to_ticket_and_datetimes($ticket_id, count($new_regs), $STS_ID);
543
-        return $new_regs;
544
-    }
483
+		$ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
484
+		if (! $ticket_id) {
485
+			$ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
486
+			$this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
487
+		}
488
+		$regs_on_this_row = intval($old_attendee['quantity']);
489
+		$new_regs = array();
490
+		// 4 cases we need to account for:
491
+		// 1 old attendee_details row with a quantity of X (no mer)
492
+		// Y old attendee_details rows with a quantity of 1 (no mer) joined by their common registration_id
493
+		// Y old attendee_details rows with a quantity of x (because of mer)
494
+		// Y old attendee_details rows with a quantity of 1 (because of mer) joined by wp_events_multi_event_registration_id_group
495
+		for ($count = 1; $count <= $regs_on_this_row; $count++) {
496
+			// sum regs on older rows
497
+			$regs_on_this_event_and_txn = $this->_sum_old_attendees_on_old_txn($old_attendee, true);
498
+			$cols_n_values = array(
499
+				'EVT_ID'=>$new_event_id,
500
+				'ATT_ID'=>$new_attendee_id,
501
+				'TXN_ID'=>$new_txn_id,
502
+				'TKT_ID'=>$ticket_id,
503
+				'STS_ID'=>$STS_ID,
504
+				'REG_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
505
+				'REG_final_price'=>$old_attendee['final_price'],
506
+				'REG_session'=> substr($old_attendee['attendee_session'], 0, 44),
507
+				'REG_code'=>sanitize_key($old_attendee['registration_id']),
508
+				'REG_url_link'=>  sanitize_key($old_attendee['registration_id'].'-'.$count),
509
+				'REG_count'=>$regs_on_this_event_and_txn + $count,
510
+				'REG_group_size'=>$this->_sum_old_attendees_on_old_txn($old_attendee, false),
511
+				'REG_att_is_going'=>true,
512
+				'REG_deleted'=>false
513
+			);
514
+			$datatypes = array(
515
+				'%d',// EVT_ID
516
+				'%d',// ATT_ID
517
+				'%d',// TXN_ID
518
+				'%d',// TKT_ID
519
+				'%s',// STS_ID
520
+				'%s',// REG_date
521
+				'%f',// REG_final_price
522
+				'%s',// REG_session
523
+				'%s',// REG_code
524
+				'%s',// REG_url_link
525
+				'%d',// REG_count
526
+				'%d',// REG_group_size
527
+				'%d',// REG_att_is_going
528
+				'%d',// REG_deleted
529
+			);
530
+			$success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
531
+			if (! $success) {
532
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
533
+				return 0;
534
+			}
535
+			$cols_n_values['REG_ID'] = $wpdb->insert_id;
536
+			$new_regs[] = $wpdb->insert_id;
537
+		}
538
+		$this->_add_regs_to_ticket_and_datetimes($ticket_id, count($new_regs), $STS_ID);
539
+		return $new_regs;
540
+	}
545 541
 
546
-    /**
547
-     * Increments the sold values on the ticket and its related datetimes by the amount sold,
548
-     * which should be done directly after adding the rows. Yes this means we're constantly incrementing
549
-     * the sold amounts as we go, and is less efficient than a single big query,
550
-     * but its safer because we KNOW these regs have been added, rather than inferring
551
-     * that they WILL be added (because the attendees stage runs nearly last during
552
-     * the migration script)
553
-     * @param type $new_ticket_id
554
-     * @param type $sold
555
-     * @param type $STS_ID
556
-     * @return boolean whether they were successfully updated or not
557
-     */
558
-    protected function _add_regs_to_ticket_and_datetimes($new_ticket_id, $quantity_sold, $STS_ID)
559
-    {
560
-        if ($STS_ID != 'RAP') {
561
-            return true;
562
-        }
563
-        global $wpdb;
564
-        $success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
565
-        if ($success) {
566
-            // get the ticket's datetimes, and increment them too
567
-            $success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
542
+	/**
543
+	 * Increments the sold values on the ticket and its related datetimes by the amount sold,
544
+	 * which should be done directly after adding the rows. Yes this means we're constantly incrementing
545
+	 * the sold amounts as we go, and is less efficient than a single big query,
546
+	 * but its safer because we KNOW these regs have been added, rather than inferring
547
+	 * that they WILL be added (because the attendees stage runs nearly last during
548
+	 * the migration script)
549
+	 * @param type $new_ticket_id
550
+	 * @param type $sold
551
+	 * @param type $STS_ID
552
+	 * @return boolean whether they were successfully updated or not
553
+	 */
554
+	protected function _add_regs_to_ticket_and_datetimes($new_ticket_id, $quantity_sold, $STS_ID)
555
+	{
556
+		if ($STS_ID != 'RAP') {
557
+			return true;
558
+		}
559
+		global $wpdb;
560
+		$success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
561
+		if ($success) {
562
+			// get the ticket's datetimes, and increment them too
563
+			$success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
568 564
 				INNER JOIN {$this->_new_ticket_datetime_table} as DTK ON TKT.TKT_ID = DTK.TKT_ID
569 565
 				INNER JOIN {$this->_new_datetime_table} as DTT ON DTK.DTT_ID = DTT.DTT_ID
570 566
 				SET DTT.DTT_sold = DTT.DTT_sold + %d WHERE TKT.TKT_ID = %d", $quantity_sold, $new_ticket_id));
571
-            if (! $success_update_dateimtes) {
572
-                $this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
573
-            }
574
-        } else {
575
-            $this->add_error(sprintf(__("Could not update ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
576
-        }
577
-        return true;
578
-    }
579
-    /**
580
-     * Makes a best guess at which ticket is the one the attendee purchased.
581
-     * Obviously, the old attendee's event_id narrows it down quite a bit;
582
-     * then the old attendee's orig_price and event_time, and price_option can uniquely identify the ticket
583
-     * however, if we don't find an exact match, see if any of those conditions match;
584
-     * and lastly if none of that works, just use the first ticket for the event we find
585
-     * @param array $old_attendee
586
-     */
587
-    private function _try_to_find_new_ticket_id($old_attendee, $new_event_id)
588
-    {
589
-        global $wpdb;
590
-        $tickets_table = $this->_new_ticket_table;
591
-        $datetime_tickets_table = $this->_new_ticket_datetime_table;
592
-        $datetime_table = $this->_new_datetime_table;
567
+			if (! $success_update_dateimtes) {
568
+				$this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
569
+			}
570
+		} else {
571
+			$this->add_error(sprintf(__("Could not update ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
572
+		}
573
+		return true;
574
+	}
575
+	/**
576
+	 * Makes a best guess at which ticket is the one the attendee purchased.
577
+	 * Obviously, the old attendee's event_id narrows it down quite a bit;
578
+	 * then the old attendee's orig_price and event_time, and price_option can uniquely identify the ticket
579
+	 * however, if we don't find an exact match, see if any of those conditions match;
580
+	 * and lastly if none of that works, just use the first ticket for the event we find
581
+	 * @param array $old_attendee
582
+	 */
583
+	private function _try_to_find_new_ticket_id($old_attendee, $new_event_id)
584
+	{
585
+		global $wpdb;
586
+		$tickets_table = $this->_new_ticket_table;
587
+		$datetime_tickets_table = $this->_new_ticket_datetime_table;
588
+		$datetime_table = $this->_new_datetime_table;
593 589
 
594
-        $old_att_price_option = $old_attendee['price_option'];
595
-        $old_att_price = floatval($old_attendee['orig_price']);
590
+		$old_att_price_option = $old_attendee['price_option'];
591
+		$old_att_price = floatval($old_attendee['orig_price']);
596 592
 
597
-        $old_att_start_date = $old_attendee['start_date'];
598
-        $old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
599
-        $old_att_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
600
-        // add all conditions to an array from which we can SHIFT conditions off in order to widen our search
601
-        // the most important condition should be last, as it will be array_shift'ed off last
602
-        $conditions = array(
603
-            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
604
-            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
605
-            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
606
-            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
607
-        );
608
-        $select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
593
+		$old_att_start_date = $old_attendee['start_date'];
594
+		$old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
595
+		$old_att_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
596
+		// add all conditions to an array from which we can SHIFT conditions off in order to widen our search
597
+		// the most important condition should be last, as it will be array_shift'ed off last
598
+		$conditions = array(
599
+			$wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
600
+			$wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
601
+			$wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
602
+			$wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
603
+		);
604
+		$select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
609 605
 			$datetime_tickets_table ON $tickets_table.TKT_ID = $datetime_tickets_table.TKT_ID INNER JOIN
610 606
 			$datetime_table ON $datetime_tickets_table.DTT_ID = $datetime_table.DTT_ID";
611
-        // start running queries, widening search each time by removing a condition
612
-        do {
613
-            $full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
614
-            $ticket_id_found = $wpdb->get_var($full_query);
615
-            array_shift($conditions);
616
-        } while (! $ticket_id_found && $conditions);
617
-        return $ticket_id_found;
618
-    }
607
+		// start running queries, widening search each time by removing a condition
608
+		do {
609
+			$full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
610
+			$ticket_id_found = $wpdb->get_var($full_query);
611
+			array_shift($conditions);
612
+		} while (! $ticket_id_found && $conditions);
613
+		return $ticket_id_found;
614
+	}
619 615
 
620
-    /**
621
-     * If we couldn't find a 4.1 ticket for a 3.1 attendee row, this function creates one;
622
-     * and it also tries to find a datetime that works, and a inserts a price, and associates
623
-     * the new ticket to that datetime and price.
624
-     * @return int ticket id
625
-     */
626
-    private function _insert_new_ticket_because_none_found($old_attendee, $new_event_id)
627
-    {
628
-        global $wpdb;
629
-        $old_att_price_option = $old_attendee['price_option'];
630
-        $old_att_price = floatval($old_attendee['orig_price']);
616
+	/**
617
+	 * If we couldn't find a 4.1 ticket for a 3.1 attendee row, this function creates one;
618
+	 * and it also tries to find a datetime that works, and a inserts a price, and associates
619
+	 * the new ticket to that datetime and price.
620
+	 * @return int ticket id
621
+	 */
622
+	private function _insert_new_ticket_because_none_found($old_attendee, $new_event_id)
623
+	{
624
+		global $wpdb;
625
+		$old_att_price_option = $old_attendee['price_option'];
626
+		$old_att_price = floatval($old_attendee['orig_price']);
631 627
 
632
-        $old_att_start_date = $old_attendee['start_date'];
633
-        $old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
634
-        $old_att_start_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
628
+		$old_att_start_date = $old_attendee['start_date'];
629
+		$old_att_start_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
630
+		$old_att_start_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_start_date $old_att_start_time:00");
635 631
 
636 632
 
637
-        // insert new datetime unless we find one
638
-        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
639
-        if (! $datetime_id) {
640
-            $old_att_end_date = $old_attendee['start_date'];
641
-            $old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
642
-            $old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
643
-            $wpdb->insert(
644
-                $this->_new_datetime_table,
645
-                array(
646
-                        'EVT_ID' => $new_event_id,
647
-                        'DTT_EVT_start' => $old_att_start_datetime,
648
-                        'DTT_EVT_end' => $old_att_end_datetime,
649
-                        'DTT_deleted' => true
650
-                    ),
651
-                array(
652
-                        '%d',// EVT_ID
653
-                        '%s',// DTT_EVT_start
654
-                        '%s',// DTT_EVT_end
655
-                        '%d',// DTT_deleted
656
-                    )
657
-            );
658
-            $datetime_id = $wpdb->insert_id;
659
-        }
633
+		// insert new datetime unless we find one
634
+		$datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
635
+		if (! $datetime_id) {
636
+			$old_att_end_date = $old_attendee['start_date'];
637
+			$old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
638
+			$old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
639
+			$wpdb->insert(
640
+				$this->_new_datetime_table,
641
+				array(
642
+						'EVT_ID' => $new_event_id,
643
+						'DTT_EVT_start' => $old_att_start_datetime,
644
+						'DTT_EVT_end' => $old_att_end_datetime,
645
+						'DTT_deleted' => true
646
+					),
647
+				array(
648
+						'%d',// EVT_ID
649
+						'%s',// DTT_EVT_start
650
+						'%s',// DTT_EVT_end
651
+						'%d',// DTT_deleted
652
+					)
653
+			);
654
+			$datetime_id = $wpdb->insert_id;
655
+		}
660 656
 
661
-        // insert new ticket
662
-        $success = $wpdb->insert(
663
-            $wpdb->prefix . 'esp_ticket',
664
-            array(
665
-                    'TKT_name' => $old_att_price_option,
666
-                    'TKT_qty' => -1,
667
-                    'TKT_price' => $old_att_price,
668
-                    'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
669
-                    'TKT_end_date' => $old_att_end_datetime,
657
+		// insert new ticket
658
+		$success = $wpdb->insert(
659
+			$wpdb->prefix . 'esp_ticket',
660
+			array(
661
+					'TKT_name' => $old_att_price_option,
662
+					'TKT_qty' => -1,
663
+					'TKT_price' => $old_att_price,
664
+					'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
665
+					'TKT_end_date' => $old_att_end_datetime,
670 666
 
671
-                ),
672
-            array(
673
-                    '%s',// name
674
-                    '%d',// qty
675
-                    '%d',// price
676
-                    '%s',// start_date
677
-                    '%s',// end_date
678
-                )
679
-        );
680
-        $ticket_id = $wpdb->insert_id;
681
-        // associate the ticket with the datetime we found earlier
682
-        $wpdb->insert(
683
-            $this->_new_datetime_ticket_table,
684
-            array(
685
-                    'DTT_ID' => $datetime_id,
686
-                    'TKT_ID' => $ticket_id
687
-                ),
688
-            array(
689
-                    '%d',// DTT_ID
690
-                    '%d',// TKT_ID
691
-                )
692
-        );
693
-        // insert new price
694
-        $wpdb->insert(
695
-            $this->_new_price_table,
696
-            array(
697
-                    'PRC_amount' => $old_att_price,
698
-                    'PRT_ID' => EE_DMS_4_1_0_prices::price_type_base,
699
-                    'PRC_name' => $old_att_price_option,
700
-                    'PRC_deleted' => true
701
-                ),
702
-            array(
703
-                    '%d',// PRC_amount
704
-                    '%d',// PRT_ID
705
-                    '%s',// PRC_name
706
-                    '%d',// PRC_deleted
707
-                )
708
-        );
709
-        $price_id = $wpdb->insert_id;
710
-        // associate the price to the ticket
711
-        $wpdb->insert(
712
-            $this->_new_ticket_price_table,
713
-            array(
714
-                    'TKT_ID' => $ticket_id,
715
-                    'PRC_ID' => $price_id
716
-                ),
717
-            array(
718
-                    '%d',// TKT_ID
719
-                    '%d',// PRC_ID
720
-                )
721
-        );
722
-        return $ticket_id;
723
-    }
724
-    /**
725
-     * Counts all the registrations on this transaction. If $count_only_older is TRUE then returns the number added SO FAR (ie,
726
-     * only considers attendee rows with an ID less than this one's), but if $count_only_older is FALSe returns ALL
727
-     * @global type $wpdb
728
-     * @param array $old_attendee_row
729
-     * @param boolean $count_only_older true if you want the running count (ie, the total up to this row), and false if you want ALL
730
-     * @return int
731
-     */
732
-    private function _sum_old_attendees_on_old_txn($old_attendee_row, $count_only_older = false)
733
-    {
734
-        global $wpdb;
735
-        $count_only_older_sql = $count_only_older ? $wpdb->prepare(" AND id<%d", $old_attendee_row['id']) : '';
736
-        $count = intval($wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM ".$this->_old_table." WHERE registration_id=%s $count_only_older_sql", $old_attendee_row['registration_id'])));
667
+				),
668
+			array(
669
+					'%s',// name
670
+					'%d',// qty
671
+					'%d',// price
672
+					'%s',// start_date
673
+					'%s',// end_date
674
+				)
675
+		);
676
+		$ticket_id = $wpdb->insert_id;
677
+		// associate the ticket with the datetime we found earlier
678
+		$wpdb->insert(
679
+			$this->_new_datetime_ticket_table,
680
+			array(
681
+					'DTT_ID' => $datetime_id,
682
+					'TKT_ID' => $ticket_id
683
+				),
684
+			array(
685
+					'%d',// DTT_ID
686
+					'%d',// TKT_ID
687
+				)
688
+		);
689
+		// insert new price
690
+		$wpdb->insert(
691
+			$this->_new_price_table,
692
+			array(
693
+					'PRC_amount' => $old_att_price,
694
+					'PRT_ID' => EE_DMS_4_1_0_prices::price_type_base,
695
+					'PRC_name' => $old_att_price_option,
696
+					'PRC_deleted' => true
697
+				),
698
+			array(
699
+					'%d',// PRC_amount
700
+					'%d',// PRT_ID
701
+					'%s',// PRC_name
702
+					'%d',// PRC_deleted
703
+				)
704
+		);
705
+		$price_id = $wpdb->insert_id;
706
+		// associate the price to the ticket
707
+		$wpdb->insert(
708
+			$this->_new_ticket_price_table,
709
+			array(
710
+					'TKT_ID' => $ticket_id,
711
+					'PRC_ID' => $price_id
712
+				),
713
+			array(
714
+					'%d',// TKT_ID
715
+					'%d',// PRC_ID
716
+				)
717
+		);
718
+		return $ticket_id;
719
+	}
720
+	/**
721
+	 * Counts all the registrations on this transaction. If $count_only_older is TRUE then returns the number added SO FAR (ie,
722
+	 * only considers attendee rows with an ID less than this one's), but if $count_only_older is FALSe returns ALL
723
+	 * @global type $wpdb
724
+	 * @param array $old_attendee_row
725
+	 * @param boolean $count_only_older true if you want the running count (ie, the total up to this row), and false if you want ALL
726
+	 * @return int
727
+	 */
728
+	private function _sum_old_attendees_on_old_txn($old_attendee_row, $count_only_older = false)
729
+	{
730
+		global $wpdb;
731
+		$count_only_older_sql = $count_only_older ? $wpdb->prepare(" AND id<%d", $old_attendee_row['id']) : '';
732
+		$count = intval($wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM ".$this->_old_table." WHERE registration_id=%s $count_only_older_sql", $old_attendee_row['registration_id'])));
737 733
 
738
-        if ($this->_mer_tables_exist()) {
739
-            // if MER exists, then its a little tricky.
740
-            // when users registered by adding items to the cart, and it was a
741
-            // group registration requiring additional attendee INFO, then the attendee rows
742
-            // DO NOT have the same registration_id (although they probably should have)
743
-            // they are related just like MER attendee rows are related, through the MER group table
744
-            // BUT we want to count all the MER attendee rows for the same registration
745
-            $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee_row['registration_id']);
734
+		if ($this->_mer_tables_exist()) {
735
+			// if MER exists, then its a little tricky.
736
+			// when users registered by adding items to the cart, and it was a
737
+			// group registration requiring additional attendee INFO, then the attendee rows
738
+			// DO NOT have the same registration_id (although they probably should have)
739
+			// they are related just like MER attendee rows are related, through the MER group table
740
+			// BUT we want to count all the MER attendee rows for the same registration
741
+			$primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee_row['registration_id']);
746 742
 
747
-            $count_using_mer_table = $wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM {$this->_old_table} att INNER JOIN {$this->_old_mer_table} mer ON att.registration_id = mer.registration_id WHERE att.event_id=%d AND mer.primary_registration_id = %s $count_only_older_sql", $old_attendee_row['event_id'], $primary_attendee['registration_id']));
748
-            $count = max($count_using_mer_table, $count);
749
-        }
750
-        return $count;
751
-    }
752
-    private function _insert_new_payment($old_attendee, $new_txn_id)
753
-    {
754
-        global $wpdb;
755
-        // only add a payment for primary attendees
756
-        $old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
757
-        // if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
758
-        if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
759
-            $pay_status_mapping = array(
760
-                'Completed'=>'PAP',
761
-                'Payment Declined'=>'PDC',
762
-                'Cancelled'=>'PCN',
763
-                'Declined'=>'PDC'
764
-            );
765
-            $by_admin = $old_attendee['payment'] == 'Admin';
766
-            $STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
767
-            $cols_n_values = array(
768
-                'TXN_ID'=>$new_txn_id,
769
-                'STS_ID'=>$STS_ID,
770
-                'PAY_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
771
-                'PAY_method'=>'CART',
772
-                'PAY_amount'=>$old_attendee['amount_pd'],
773
-                'PAY_gateway'=>$old_attendee['txn_type'],
774
-                'PAY_gateway_response'=>'',
775
-                'PAY_txn_id_chq_nmbr'=>substr($old_attendee['txn_id'], 0, 32),
776
-                'PAY_via_admin'=>$by_admin,
777
-                'PAY_details'=>$old_attendee['transaction_details']
743
+			$count_using_mer_table = $wpdb->get_var($wpdb->prepare("SELECT SUM(quantity) FROM {$this->_old_table} att INNER JOIN {$this->_old_mer_table} mer ON att.registration_id = mer.registration_id WHERE att.event_id=%d AND mer.primary_registration_id = %s $count_only_older_sql", $old_attendee_row['event_id'], $primary_attendee['registration_id']));
744
+			$count = max($count_using_mer_table, $count);
745
+		}
746
+		return $count;
747
+	}
748
+	private function _insert_new_payment($old_attendee, $new_txn_id)
749
+	{
750
+		global $wpdb;
751
+		// only add a payment for primary attendees
752
+		$old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
753
+		// if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
754
+		if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
755
+			$pay_status_mapping = array(
756
+				'Completed'=>'PAP',
757
+				'Payment Declined'=>'PDC',
758
+				'Cancelled'=>'PCN',
759
+				'Declined'=>'PDC'
760
+			);
761
+			$by_admin = $old_attendee['payment'] == 'Admin';
762
+			$STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
763
+			$cols_n_values = array(
764
+				'TXN_ID'=>$new_txn_id,
765
+				'STS_ID'=>$STS_ID,
766
+				'PAY_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
767
+				'PAY_method'=>'CART',
768
+				'PAY_amount'=>$old_attendee['amount_pd'],
769
+				'PAY_gateway'=>$old_attendee['txn_type'],
770
+				'PAY_gateway_response'=>'',
771
+				'PAY_txn_id_chq_nmbr'=>substr($old_attendee['txn_id'], 0, 32),
772
+				'PAY_via_admin'=>$by_admin,
773
+				'PAY_details'=>$old_attendee['transaction_details']
778 774
 
779
-            );
780
-            $datatypes = array(
781
-                '%d',// TXN_Id
782
-                '%s',// STS_ID
783
-                '%s',// PAY_timestamp
784
-                '%s',// PAY_method
785
-                '%f',// PAY_amount
786
-                '%s',// PAY_gateway
787
-                '%s',// PAY_gateway_response
788
-                '%s',// PAY_txn_id_chq_nmbr
789
-                '%d',// PAY_via_admin
790
-                '%s',// PAY_details
791
-            );
792
-            $success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
793
-            if (! $success) {
794
-                $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
795
-                return 0;
796
-            }
797
-            $new_id = $wpdb->insert_id;
798
-            return $new_id;
799
-        } else {
800
-            return 0;
801
-        }
802
-    }
775
+			);
776
+			$datatypes = array(
777
+				'%d',// TXN_Id
778
+				'%s',// STS_ID
779
+				'%s',// PAY_timestamp
780
+				'%s',// PAY_method
781
+				'%f',// PAY_amount
782
+				'%s',// PAY_gateway
783
+				'%s',// PAY_gateway_response
784
+				'%s',// PAY_txn_id_chq_nmbr
785
+				'%d',// PAY_via_admin
786
+				'%s',// PAY_details
787
+			);
788
+			$success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
789
+			if (! $success) {
790
+				$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
791
+				return 0;
792
+			}
793
+			$new_id = $wpdb->insert_id;
794
+			return $new_id;
795
+		} else {
796
+			return 0;
797
+		}
798
+	}
803 799
 
804
-    /**
805
-     * If MER is active, if you want ot fin dthe other registrations on that attendee row
806
-     * @global type $wpdb
807
-     * @param type $old_registration_id
808
-     * @return array
809
-     */
810
-    private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
811
-    {
812
-        if (! $this->_mer_tables_exist()) {
813
-            return false;
814
-        }
815
-        global $wpdb;
816
-        $old_att_for_primary_reg = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->_old_mer_table} AS mer INNER JOIN {$this->_old_table} AS att ON mer.primary_registration_id = att.registration_id WHERE mer.registration_id=%s LIMIT 1", $old_registration_id), ARRAY_A);
817
-        return $old_att_for_primary_reg;
818
-    }
800
+	/**
801
+	 * If MER is active, if you want ot fin dthe other registrations on that attendee row
802
+	 * @global type $wpdb
803
+	 * @param type $old_registration_id
804
+	 * @return array
805
+	 */
806
+	private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
807
+	{
808
+		if (! $this->_mer_tables_exist()) {
809
+			return false;
810
+		}
811
+		global $wpdb;
812
+		$old_att_for_primary_reg = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->_old_mer_table} AS mer INNER JOIN {$this->_old_table} AS att ON mer.primary_registration_id = att.registration_id WHERE mer.registration_id=%s LIMIT 1", $old_registration_id), ARRAY_A);
813
+		return $old_att_for_primary_reg;
814
+	}
819 815
 }
Please login to merge, or discard this patch.
Spacing   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
         $this->_pretty_name = __("Attendees", "event_espresso");
211 211
         $this->_old_table = $wpdb->prefix."events_attendee";
212 212
         $this->_extra_where_sql = 'AS att
213
-            INNER JOIN ' . $wpdb->prefix . 'events_detail AS e ON att.event_id=e.id
213
+            INNER JOIN ' . $wpdb->prefix.'events_detail AS e ON att.event_id=e.id
214 214
             WHERE e.event_status!="D"';
215 215
         $this->_old_mer_table = $wpdb->prefix."events_multi_event_registration_id_group";
216 216
         $this->_new_attendee_cpt_table = $wpdb->posts;
@@ -232,9 +232,9 @@  discard block
 block discarded – undo
232 232
     {
233 233
         // first check if there's already a new attendee with similar characteristics
234 234
         $new_att_id = $this->_find_attendee_cpt_matching($old_row);
235
-        if (! $new_att_id) {
235
+        if ( ! $new_att_id) {
236 236
             $new_att_id = $this->_insert_new_attendee_cpt($old_row);
237
-            if (! $new_att_id) {
237
+            if ( ! $new_att_id) {
238 238
                 // if we couldnt even make an attendee, abandon all hope
239 239
                 return false;
240 240
             }
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
         $this->get_migration_script()->set_mapping($this->_old_table, $old_row['id'], $this->_new_attendee_cpt_table, $new_att_id);
247 247
 
248 248
         $txn_id = $this->_insert_new_transaction($old_row);
249
-        if (! $txn_id) {
249
+        if ( ! $txn_id) {
250 250
             // if we couldnt make the transaction, also abandon all hope
251 251
             return false;
252 252
         }
@@ -280,31 +280,31 @@  discard block
 block discarded – undo
280 280
     {
281 281
         global $wpdb;
282 282
         $cols_n_values = array(
283
-            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']),// ATT_full_name
284
-            'post_content'=>'',// ATT_bio
285
-            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']),// ATT_slug
286
-            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_created
287
-            'post_excerpt'=>'',// ATT_short_bio
288
-            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),// ATT_modified
289
-            'post_author'=>0,// ATT_author
290
-            'post_parent'=>0,// ATT_parent
291
-            'post_type'=>'espresso_attendees',// post_type
283
+            'post_title'=>stripslashes($old_attendee['fname']." ".$old_attendee['lname']), // ATT_full_name
284
+            'post_content'=>'', // ATT_bio
285
+            'post_name'=>sanitize_title($old_attendee['fname']."-".$old_attendee['lname']), // ATT_slug
286
+            'post_date'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']), // ATT_created
287
+            'post_excerpt'=>'', // ATT_short_bio
288
+            'post_modified'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']), // ATT_modified
289
+            'post_author'=>0, // ATT_author
290
+            'post_parent'=>0, // ATT_parent
291
+            'post_type'=>'espresso_attendees', // post_type
292 292
             'post_status'=>'publish'// status
293 293
         );
294 294
         $datatypes = array(
295
-            '%s',// ATT_full_name
296
-            '%s',// ATT_bio
297
-            '%s',// ATT_slug
298
-            '%s',// ATT_created
299
-            '%s',// ATT_short_bio
300
-            '%s',// ATT_modified
301
-            '%d',// ATT_author
302
-            '%d',// ATT_parent
303
-            '%s',// post_type
304
-            '%s',// status
295
+            '%s', // ATT_full_name
296
+            '%s', // ATT_bio
297
+            '%s', // ATT_slug
298
+            '%s', // ATT_created
299
+            '%s', // ATT_short_bio
300
+            '%s', // ATT_modified
301
+            '%d', // ATT_author
302
+            '%d', // ATT_parent
303
+            '%s', // post_type
304
+            '%s', // status
305 305
         );
306 306
         $success = $wpdb->insert($this->_new_attendee_cpt_table, $cols_n_values, $datatypes);
307
-        if (! $success) {
307
+        if ( ! $success) {
308 308
             $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
309 309
             return 0;
310 310
         }
@@ -342,20 +342,20 @@  discard block
 block discarded – undo
342 342
             'ATT_phone'=>stripslashes($old_attendee['phone']),
343 343
         );
344 344
         $datatypes = array(
345
-            '%d',// ATT_ID
346
-            '%s',// ATT_fname
347
-            '%s',// ATT_lname
348
-            '%s',// ATT_address
349
-            '%s',// ATT_address2
350
-            '%s',// ATT_city
351
-            '%d',// STA_ID
352
-            '%s',// CNT_ISO
353
-            '%s',// ATT_zip
354
-            '%s',// ATT_email
355
-            '%s',// ATT_phone
345
+            '%d', // ATT_ID
346
+            '%s', // ATT_fname
347
+            '%s', // ATT_lname
348
+            '%s', // ATT_address
349
+            '%s', // ATT_address2
350
+            '%s', // ATT_city
351
+            '%d', // STA_ID
352
+            '%s', // CNT_ISO
353
+            '%s', // ATT_zip
354
+            '%s', // ATT_email
355
+            '%s', // ATT_phone
356 356
         );
357 357
         $success = $wpdb->insert($this->_new_attendee_meta_table, $cols_n_values, $datatypes);
358
-        if (! $success) {
358
+        if ( ! $success) {
359 359
             $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_meta_table, $cols_n_values, $datatypes));
360 360
             return 0;
361 361
         }
@@ -380,12 +380,12 @@  discard block
 block discarded – undo
380 380
             $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($old_attendee['id']), $this->_new_transaction_table);
381 381
         } else { // non-primary attendee, so find its primary attendee's transaction
382 382
             $primary_attendee_old_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".$this->_old_table." WHERE is_primary=1 and registration_id=%s", $old_attendee['registration_id']));
383
-            if (! $primary_attendee_old_id) {
383
+            if ( ! $primary_attendee_old_id) {
384 384
                 $primary_attendee = $this->_find_mer_primary_attendee_using_mer_tables($old_attendee['registration_id']);
385 385
                 $primary_attendee_old_id = is_array($primary_attendee) ? $primary_attendee['id'] : null;
386 386
             }
387 387
             $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, intval($primary_attendee_old_id), $this->_new_transaction_table);
388
-            if (! $txn_id) {
388
+            if ( ! $txn_id) {
389 389
                 $this->add_error(sprintf(__("Could not find primary attendee's new transaction. Current attendee is: %s, we think the 3.1 primary attendee for it has id %d, but there's no 4.1 transaction for that primary attendee id.", "event_espresso"), $this->_json_encode($old_attendee), $primary_attendee_old_id));
390 390
                 $txn_id = 0;
391 391
             }
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
         // if there isn't yet a transaction row for this, create one
394 394
         // (so even if it was a non-primary attendee with no EE3 primary attendee,
395 395
         // it ought to have SOME transaction, so we'll make one)
396
-        if (! $txn_id) {
396
+        if ( ! $txn_id) {
397 397
             // maps 3.1 payment stati onto 4.1 transaction stati
398 398
             $txn_status_mapping = array(
399 399
                 'Completed'=>'TCM',
@@ -404,7 +404,7 @@  discard block
 block discarded – undo
404 404
                 'Cancelled'=>'TIN',
405 405
                 'Declined'=>'TIN'
406 406
             );
407
-            $STS_ID = isset($txn_status_mapping[ $old_attendee['payment_status'] ]) ? $txn_status_mapping[ $old_attendee['payment_status'] ] : 'TIN';
407
+            $STS_ID = isset($txn_status_mapping[$old_attendee['payment_status']]) ? $txn_status_mapping[$old_attendee['payment_status']] : 'TIN';
408 408
             $cols_n_values = array(
409 409
                 'TXN_timestamp'=>$this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, $old_attendee['date']),
410 410
                 'TXN_total'=>floatval($old_attendee['total_cost']),
@@ -413,14 +413,14 @@  discard block
 block discarded – undo
413 413
                 'TXN_hash_salt'=>$old_attendee['hashSalt']
414 414
             );
415 415
             $datatypes = array(
416
-                '%s',// TXN_timestamp
417
-                '%f',// TXN_total
418
-                '%f',// TXN_paid
419
-                '%s',// STS_ID
420
-                '%s',// TXN_hash_salt
416
+                '%s', // TXN_timestamp
417
+                '%f', // TXN_total
418
+                '%f', // TXN_paid
419
+                '%s', // STS_ID
420
+                '%s', // TXN_hash_salt
421 421
             );
422 422
             $success = $wpdb->insert($this->_new_transaction_table, $cols_n_values, $datatypes);
423
-            if (! $success) {
423
+            if ( ! $success) {
424 424
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_transaction_table, $cols_n_values, $datatypes));
425 425
                 return 0;
426 426
             }
@@ -480,12 +480,12 @@  discard block
 block discarded – undo
480 480
 
481 481
         $STS_ID = $this->_get_reg_status_for_old_payment_status($old_attendee);
482 482
         $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix.'events_detail', $old_attendee['event_id'], $wpdb->posts);
483
-        if (! $new_event_id) {
483
+        if ( ! $new_event_id) {
484 484
             $this->add_error(sprintf(__("Could not find NEW event CPT ID for old event '%d' on old attendee %s", "event_espresso"), $old_attendee['event_id'], $this->_json_encode($old_attendee)));
485 485
         }
486 486
 
487 487
         $ticket_id = $this->_try_to_find_new_ticket_id($old_attendee, $new_event_id);
488
-        if (! $ticket_id) {
488
+        if ( ! $ticket_id) {
489 489
             $ticket_id = $this->_insert_new_ticket_because_none_found($old_attendee, $new_event_id);
490 490
             $this->add_error(sprintf(__('Could not find a ticket for old attendee with id %d for new event %d, so created a new ticket with id %d', 'event_espresso'), $old_attendee['id'], $new_event_id, $ticket_id));
491 491
         }
@@ -516,23 +516,23 @@  discard block
 block discarded – undo
516 516
                 'REG_deleted'=>false
517 517
             );
518 518
             $datatypes = array(
519
-                '%d',// EVT_ID
520
-                '%d',// ATT_ID
521
-                '%d',// TXN_ID
522
-                '%d',// TKT_ID
523
-                '%s',// STS_ID
524
-                '%s',// REG_date
525
-                '%f',// REG_final_price
526
-                '%s',// REG_session
527
-                '%s',// REG_code
528
-                '%s',// REG_url_link
529
-                '%d',// REG_count
530
-                '%d',// REG_group_size
531
-                '%d',// REG_att_is_going
532
-                '%d',// REG_deleted
519
+                '%d', // EVT_ID
520
+                '%d', // ATT_ID
521
+                '%d', // TXN_ID
522
+                '%d', // TKT_ID
523
+                '%s', // STS_ID
524
+                '%s', // REG_date
525
+                '%f', // REG_final_price
526
+                '%s', // REG_session
527
+                '%s', // REG_code
528
+                '%s', // REG_url_link
529
+                '%d', // REG_count
530
+                '%d', // REG_group_size
531
+                '%d', // REG_att_is_going
532
+                '%d', // REG_deleted
533 533
             );
534 534
             $success = $wpdb->insert($this->_new_reg_table, $cols_n_values, $datatypes);
535
-            if (! $success) {
535
+            if ( ! $success) {
536 536
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_reg_table, $cols_n_values, $datatypes));
537 537
                 return 0;
538 538
             }
@@ -564,11 +564,11 @@  discard block
 block discarded – undo
564 564
         $success = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} SET TKT_sold=TKT_sold+%d WHERE TKT_ID=%d", $quantity_sold, $new_ticket_id));
565 565
         if ($success) {
566 566
             // get the ticket's datetimes, and increment them too
567
-            $success_update_dateimtes =  $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
567
+            $success_update_dateimtes = $wpdb->query($wpdb->prepare("UPDATE {$this->_new_ticket_table} TKT
568 568
 				INNER JOIN {$this->_new_ticket_datetime_table} as DTK ON TKT.TKT_ID = DTK.TKT_ID
569 569
 				INNER JOIN {$this->_new_datetime_table} as DTT ON DTK.DTT_ID = DTT.DTT_ID
570 570
 				SET DTT.DTT_sold = DTT.DTT_sold + %d WHERE TKT.TKT_ID = %d", $quantity_sold, $new_ticket_id));
571
-            if (! $success_update_dateimtes) {
571
+            if ( ! $success_update_dateimtes) {
572 572
                 $this->add_error(sprintf(__("Could not update datetimes related to ticket with ID %d's TKT_sold by %d because %s", "event_espresso"), $new_ticket_id, $quantity_sold, $wpdb->last_error));
573 573
             }
574 574
         } else {
@@ -600,10 +600,10 @@  discard block
 block discarded – undo
600 600
         // add all conditions to an array from which we can SHIFT conditions off in order to widen our search
601 601
         // the most important condition should be last, as it will be array_shift'ed off last
602 602
         $conditions = array(
603
-            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime),// times match?
604
-            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price),// prices match?
605
-            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option),// names match?
606
-            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id),// events match?
603
+            $wpdb->prepare("$datetime_table.DTT_EVT_start = %s", $old_att_datetime), // times match?
604
+            $wpdb->prepare("$tickets_table.TKT_price = %f", $old_att_price), // prices match?
605
+            $wpdb->prepare("$tickets_table.TKT_name = %s", $old_att_price_option), // names match?
606
+            $wpdb->prepare("$datetime_table.EVT_ID = %d", $new_event_id), // events match?
607 607
         );
608 608
         $select_and_join_part = "SELECT $tickets_table.TKT_ID FROM $tickets_table INNER JOIN
609 609
 			$datetime_tickets_table ON $tickets_table.TKT_ID = $datetime_tickets_table.TKT_ID INNER JOIN
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
             $full_query = $select_and_join_part." WHERE ".implode(" AND ", $conditions)." LIMIT 1";
614 614
             $ticket_id_found = $wpdb->get_var($full_query);
615 615
             array_shift($conditions);
616
-        } while (! $ticket_id_found && $conditions);
616
+        }while ( ! $ticket_id_found && $conditions);
617 617
         return $ticket_id_found;
618 618
     }
619 619
 
@@ -635,8 +635,8 @@  discard block
 block discarded – undo
635 635
 
636 636
 
637 637
         // insert new datetime unless we find one
638
-        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM " . $this->_new_datetime_table . " WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
639
-        if (! $datetime_id) {
638
+        $datetime_id = $wpdb->get_var($wpdb->prepare("SELECT DTT_ID FROM ".$this->_new_datetime_table." WHERE DTT_EVT_start=%s AND EVT_ID=%d LIMIT 1", $old_att_start_datetime, $new_event_id), ARRAY_A);
639
+        if ( ! $datetime_id) {
640 640
             $old_att_end_date = $old_attendee['start_date'];
641 641
             $old_att_end_time = $this->get_migration_script()->convertTimeFromAMPM($old_attendee['event_time']);
642 642
             $old_att_end_datetime = $this->get_migration_script()->convert_date_string_to_utc($this, $old_attendee, "$old_att_end_date $old_att_end_time:00");
@@ -649,10 +649,10 @@  discard block
 block discarded – undo
649 649
                         'DTT_deleted' => true
650 650
                     ),
651 651
                 array(
652
-                        '%d',// EVT_ID
653
-                        '%s',// DTT_EVT_start
654
-                        '%s',// DTT_EVT_end
655
-                        '%d',// DTT_deleted
652
+                        '%d', // EVT_ID
653
+                        '%s', // DTT_EVT_start
654
+                        '%s', // DTT_EVT_end
655
+                        '%d', // DTT_deleted
656 656
                     )
657 657
             );
658 658
             $datetime_id = $wpdb->insert_id;
@@ -660,21 +660,21 @@  discard block
 block discarded – undo
660 660
 
661 661
         // insert new ticket
662 662
         $success = $wpdb->insert(
663
-            $wpdb->prefix . 'esp_ticket',
663
+            $wpdb->prefix.'esp_ticket',
664 664
             array(
665 665
                     'TKT_name' => $old_att_price_option,
666 666
                     'TKT_qty' => -1,
667 667
                     'TKT_price' => $old_att_price,
668
-                    'TKT_start_date' => $old_att_start_datetime,// we really have no clue what the time should be, but at least it was available when they attended
668
+                    'TKT_start_date' => $old_att_start_datetime, // we really have no clue what the time should be, but at least it was available when they attended
669 669
                     'TKT_end_date' => $old_att_end_datetime,
670 670
 
671 671
                 ),
672 672
             array(
673
-                    '%s',// name
674
-                    '%d',// qty
675
-                    '%d',// price
676
-                    '%s',// start_date
677
-                    '%s',// end_date
673
+                    '%s', // name
674
+                    '%d', // qty
675
+                    '%d', // price
676
+                    '%s', // start_date
677
+                    '%s', // end_date
678 678
                 )
679 679
         );
680 680
         $ticket_id = $wpdb->insert_id;
@@ -686,8 +686,8 @@  discard block
 block discarded – undo
686 686
                     'TKT_ID' => $ticket_id
687 687
                 ),
688 688
             array(
689
-                    '%d',// DTT_ID
690
-                    '%d',// TKT_ID
689
+                    '%d', // DTT_ID
690
+                    '%d', // TKT_ID
691 691
                 )
692 692
         );
693 693
         // insert new price
@@ -700,10 +700,10 @@  discard block
 block discarded – undo
700 700
                     'PRC_deleted' => true
701 701
                 ),
702 702
             array(
703
-                    '%d',// PRC_amount
704
-                    '%d',// PRT_ID
705
-                    '%s',// PRC_name
706
-                    '%d',// PRC_deleted
703
+                    '%d', // PRC_amount
704
+                    '%d', // PRT_ID
705
+                    '%s', // PRC_name
706
+                    '%d', // PRC_deleted
707 707
                 )
708 708
         );
709 709
         $price_id = $wpdb->insert_id;
@@ -715,8 +715,8 @@  discard block
 block discarded – undo
715 715
                     'PRC_ID' => $price_id
716 716
                 ),
717 717
             array(
718
-                    '%d',// TKT_ID
719
-                    '%d',// PRC_ID
718
+                    '%d', // TKT_ID
719
+                    '%d', // PRC_ID
720 720
                 )
721 721
         );
722 722
         return $ticket_id;
@@ -753,7 +753,7 @@  discard block
 block discarded – undo
753 753
     {
754 754
         global $wpdb;
755 755
         // only add a payment for primary attendees
756
-        $old_pay_stati_indicating_no_payment = array('Pending','Incomplete','Not Completed');
756
+        $old_pay_stati_indicating_no_payment = array('Pending', 'Incomplete', 'Not Completed');
757 757
         // if this is for a primary 3.1 attendee which WASN'T free and has a completed, cancelled, or declined payment...
758 758
         if (intval($old_attendee['is_primary']) && floatval($old_attendee['total_cost']) && ! in_array($old_attendee['payment_status'], $old_pay_stati_indicating_no_payment)) {
759 759
             $pay_status_mapping = array(
@@ -763,7 +763,7 @@  discard block
 block discarded – undo
763 763
                 'Declined'=>'PDC'
764 764
             );
765 765
             $by_admin = $old_attendee['payment'] == 'Admin';
766
-            $STS_ID = isset($pay_status_mapping[ $old_attendee['payment_status'] ]) ? $pay_status_mapping[ $old_attendee['payment_status'] ] : 'PFL';// IE, if we don't recognize the status, assume payment failed
766
+            $STS_ID = isset($pay_status_mapping[$old_attendee['payment_status']]) ? $pay_status_mapping[$old_attendee['payment_status']] : 'PFL'; // IE, if we don't recognize the status, assume payment failed
767 767
             $cols_n_values = array(
768 768
                 'TXN_ID'=>$new_txn_id,
769 769
                 'STS_ID'=>$STS_ID,
@@ -778,19 +778,19 @@  discard block
 block discarded – undo
778 778
 
779 779
             );
780 780
             $datatypes = array(
781
-                '%d',// TXN_Id
782
-                '%s',// STS_ID
783
-                '%s',// PAY_timestamp
784
-                '%s',// PAY_method
785
-                '%f',// PAY_amount
786
-                '%s',// PAY_gateway
787
-                '%s',// PAY_gateway_response
788
-                '%s',// PAY_txn_id_chq_nmbr
789
-                '%d',// PAY_via_admin
790
-                '%s',// PAY_details
781
+                '%d', // TXN_Id
782
+                '%s', // STS_ID
783
+                '%s', // PAY_timestamp
784
+                '%s', // PAY_method
785
+                '%f', // PAY_amount
786
+                '%s', // PAY_gateway
787
+                '%s', // PAY_gateway_response
788
+                '%s', // PAY_txn_id_chq_nmbr
789
+                '%d', // PAY_via_admin
790
+                '%s', // PAY_details
791 791
             );
792 792
             $success = $wpdb->insert($this->_new_payment_table, $cols_n_values, $datatypes);
793
-            if (! $success) {
793
+            if ( ! $success) {
794 794
                 $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_attendee, $this->_new_attendee_cpt_table, $cols_n_values, $datatypes));
795 795
                 return 0;
796 796
             }
@@ -809,7 +809,7 @@  discard block
 block discarded – undo
809 809
      */
810 810
     private function _find_mer_primary_attendee_using_mer_tables($old_registration_id)
811 811
     {
812
-        if (! $this->_mer_tables_exist()) {
812
+        if ( ! $this->_mer_tables_exist()) {
813 813
             return false;
814 814
         }
815 815
         global $wpdb;
Please login to merge, or discard this patch.
data_migration_scripts/4_1_0_stages/EE_DMS_4_1_0_event_venue.dmsstage.php 2 patches
Indentation   +87 added lines, -90 removed lines patch added patch discarded remove patch
@@ -25,105 +25,102 @@
 block discarded – undo
25 25
 
26 26
             )
27 27
         );
28
-
29
-
30
-
31 28
  *
32 29
  */
33 30
 class EE_DMS_4_1_0_event_venue extends EE_Data_Migration_Script_Stage
34 31
 {
35
-    private $_old_table;
36
-    private $_new_table;
37
-    public function _migration_step($num_items = 50)
38
-    {
32
+	private $_old_table;
33
+	private $_new_table;
34
+	public function _migration_step($num_items = 50)
35
+	{
39 36
         
40
-        global $wpdb;
41
-        $start_at_record = $this->count_records_migrated();
42
-        $rows = $wpdb->get_results(
43
-            $wpdb->prepare(
44
-                "SELECT * FROM $this->_old_table AS ev 
37
+		global $wpdb;
38
+		$start_at_record = $this->count_records_migrated();
39
+		$rows = $wpdb->get_results(
40
+			$wpdb->prepare(
41
+				"SELECT * FROM $this->_old_table AS ev 
45 42
                     INNER JOIN " . $wpdb->prefix . "events_detail AS e ON ev.event_id=e.id
46 43
                     WHERE e.event_status!='D' LIMIT %d,%d",
47
-                $start_at_record,
48
-                $num_items
49
-            ),
50
-            ARRAY_A
51
-        );
52
-        $items_actually_migrated = 0;
53
-        foreach ($rows as $event_venue_rel) {
54
-            $this->_insert_new_event_to_venue_rel($event_venue_rel);
55
-            $items_actually_migrated++;
56
-        }
57
-        if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
58
-            $this->set_completed();
59
-        }
60
-        return $items_actually_migrated;
61
-    }
62
-    public function _count_records_to_migrate()
63
-    {
64
-        global $wpdb;
65
-        $count = $wpdb->get_var(
66
-            "SELECT COUNT(ev.id) FROM ".$this->_old_table . " AS ev 
44
+				$start_at_record,
45
+				$num_items
46
+			),
47
+			ARRAY_A
48
+		);
49
+		$items_actually_migrated = 0;
50
+		foreach ($rows as $event_venue_rel) {
51
+			$this->_insert_new_event_to_venue_rel($event_venue_rel);
52
+			$items_actually_migrated++;
53
+		}
54
+		if ($this->count_records_migrated() + $items_actually_migrated >= $this->count_records_to_migrate()) {
55
+			$this->set_completed();
56
+		}
57
+		return $items_actually_migrated;
58
+	}
59
+	public function _count_records_to_migrate()
60
+	{
61
+		global $wpdb;
62
+		$count = $wpdb->get_var(
63
+			"SELECT COUNT(ev.id) FROM ".$this->_old_table . " AS ev 
67 64
             INNER JOIN " . $wpdb->prefix . 'events_detail AS e ON ev.event_id=e.id
68 65
             WHERE e.event_status!="D"'
69
-        );
70
-        return $count;
71
-    }
72
-    public function __construct()
73
-    {
74
-        global $wpdb;
75
-        $this->_old_table = $wpdb->prefix."events_venue_rel";
76
-        $this->_new_table = $wpdb->prefix."esp_event_venue";
77
-        $this->_pretty_name = __("Event to Venue Relations", "event_espresso");
78
-        parent::__construct();
79
-    }
66
+		);
67
+		return $count;
68
+	}
69
+	public function __construct()
70
+	{
71
+		global $wpdb;
72
+		$this->_old_table = $wpdb->prefix."events_venue_rel";
73
+		$this->_new_table = $wpdb->prefix."esp_event_venue";
74
+		$this->_pretty_name = __("Event to Venue Relations", "event_espresso");
75
+		parent::__construct();
76
+	}
80 77
     
81
-    /**
82
-     * Attempts to insert a new question group inthe new format given an old one
83
-     * @global type $wpdb
84
-     * @param array $old_event_venue_rel
85
-     * @return int
86
-     */
87
-    private function _insert_new_event_to_venue_rel($old_event_venue_rel)
88
-    {
89
-        global $wpdb;
90
-        $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_detail", $old_event_venue_rel['event_id'], $wpdb->prefix."posts");
91
-        $new_venue_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_venue", $old_event_venue_rel['venue_id'], $wpdb->prefix."posts");
92
-        if (! $new_event_id) {
93
-            $this->add_error(sprintf(__("Could not find 4.1 event id for 3.1 event #%d.", "event_espresso"), $old_event_venue_rel['event_id']));
94
-            return 0;
95
-        }
96
-        if (! $new_venue_id) {
97
-            $this->add_error(sprintf(__("Could not find 4.1 venue id for 3.1 venue #%d.", "event_espresso"), $old_event_venue_rel['venue_id']));
98
-            return 0;
99
-        }
100
-        // first ensure there are no other relation entries for this event
101
-        // because although EE4 supports it, EE3 didn't really
102
-        $wpdb->delete(
103
-            $this->_new_table,
104
-            array(
105
-                    'EVT_ID' => $new_event_id,
106
-                ),
107
-            array(
108
-                    '%d',// EVT_ID
109
-                )
110
-        );
78
+	/**
79
+	 * Attempts to insert a new question group inthe new format given an old one
80
+	 * @global type $wpdb
81
+	 * @param array $old_event_venue_rel
82
+	 * @return int
83
+	 */
84
+	private function _insert_new_event_to_venue_rel($old_event_venue_rel)
85
+	{
86
+		global $wpdb;
87
+		$new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_detail", $old_event_venue_rel['event_id'], $wpdb->prefix."posts");
88
+		$new_venue_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_venue", $old_event_venue_rel['venue_id'], $wpdb->prefix."posts");
89
+		if (! $new_event_id) {
90
+			$this->add_error(sprintf(__("Could not find 4.1 event id for 3.1 event #%d.", "event_espresso"), $old_event_venue_rel['event_id']));
91
+			return 0;
92
+		}
93
+		if (! $new_venue_id) {
94
+			$this->add_error(sprintf(__("Could not find 4.1 venue id for 3.1 venue #%d.", "event_espresso"), $old_event_venue_rel['venue_id']));
95
+			return 0;
96
+		}
97
+		// first ensure there are no other relation entries for this event
98
+		// because although EE4 supports it, EE3 didn't really
99
+		$wpdb->delete(
100
+			$this->_new_table,
101
+			array(
102
+					'EVT_ID' => $new_event_id,
103
+				),
104
+			array(
105
+					'%d',// EVT_ID
106
+				)
107
+		);
111 108
 //      echo "last query". $wpdb->last_query;die;
112
-        $cols_n_values = array(
113
-            'EVT_ID'=>$new_event_id,
114
-            'VNU_ID'=>$new_venue_id,
115
-            'EVV_primary'=>true
116
-        );
117
-        $datatypes = array(
118
-            '%d',// EVT_ID
119
-            '%d',// VNU_ID
120
-            '%d',// EVT_primary
121
-        );
122
-        $success = $wpdb->insert($this->_new_table, $cols_n_values, $datatypes);
123
-        if (! $success) {
124
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_event_venue_rel, $this->_new_table, $cols_n_values, $datatypes));
125
-            return 0;
126
-        }
127
-        return $wpdb->insert_id;
128
-    }
109
+		$cols_n_values = array(
110
+			'EVT_ID'=>$new_event_id,
111
+			'VNU_ID'=>$new_venue_id,
112
+			'EVV_primary'=>true
113
+		);
114
+		$datatypes = array(
115
+			'%d',// EVT_ID
116
+			'%d',// VNU_ID
117
+			'%d',// EVT_primary
118
+		);
119
+		$success = $wpdb->insert($this->_new_table, $cols_n_values, $datatypes);
120
+		if (! $success) {
121
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_event_venue_rel, $this->_new_table, $cols_n_values, $datatypes));
122
+			return 0;
123
+		}
124
+		return $wpdb->insert_id;
125
+	}
129 126
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
         $rows = $wpdb->get_results(
43 43
             $wpdb->prepare(
44 44
                 "SELECT * FROM $this->_old_table AS ev 
45
-                    INNER JOIN " . $wpdb->prefix . "events_detail AS e ON ev.event_id=e.id
45
+                    INNER JOIN ".$wpdb->prefix."events_detail AS e ON ev.event_id=e.id
46 46
                     WHERE e.event_status!='D' LIMIT %d,%d",
47 47
                 $start_at_record,
48 48
                 $num_items
@@ -63,8 +63,8 @@  discard block
 block discarded – undo
63 63
     {
64 64
         global $wpdb;
65 65
         $count = $wpdb->get_var(
66
-            "SELECT COUNT(ev.id) FROM ".$this->_old_table . " AS ev 
67
-            INNER JOIN " . $wpdb->prefix . 'events_detail AS e ON ev.event_id=e.id
66
+            "SELECT COUNT(ev.id) FROM ".$this->_old_table." AS ev 
67
+            INNER JOIN " . $wpdb->prefix.'events_detail AS e ON ev.event_id=e.id
68 68
             WHERE e.event_status!="D"'
69 69
         );
70 70
         return $count;
@@ -89,11 +89,11 @@  discard block
 block discarded – undo
89 89
         global $wpdb;
90 90
         $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_detail", $old_event_venue_rel['event_id'], $wpdb->prefix."posts");
91 91
         $new_venue_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_venue", $old_event_venue_rel['venue_id'], $wpdb->prefix."posts");
92
-        if (! $new_event_id) {
92
+        if ( ! $new_event_id) {
93 93
             $this->add_error(sprintf(__("Could not find 4.1 event id for 3.1 event #%d.", "event_espresso"), $old_event_venue_rel['event_id']));
94 94
             return 0;
95 95
         }
96
-        if (! $new_venue_id) {
96
+        if ( ! $new_venue_id) {
97 97
             $this->add_error(sprintf(__("Could not find 4.1 venue id for 3.1 venue #%d.", "event_espresso"), $old_event_venue_rel['venue_id']));
98 98
             return 0;
99 99
         }
@@ -105,7 +105,7 @@  discard block
 block discarded – undo
105 105
                     'EVT_ID' => $new_event_id,
106 106
                 ),
107 107
             array(
108
-                    '%d',// EVT_ID
108
+                    '%d', // EVT_ID
109 109
                 )
110 110
         );
111 111
 //      echo "last query". $wpdb->last_query;die;
@@ -115,12 +115,12 @@  discard block
 block discarded – undo
115 115
             'EVV_primary'=>true
116 116
         );
117 117
         $datatypes = array(
118
-            '%d',// EVT_ID
119
-            '%d',// VNU_ID
120
-            '%d',// EVT_primary
118
+            '%d', // EVT_ID
119
+            '%d', // VNU_ID
120
+            '%d', // EVT_primary
121 121
         );
122 122
         $success = $wpdb->insert($this->_new_table, $cols_n_values, $datatypes);
123
-        if (! $success) {
123
+        if ( ! $success) {
124 124
             $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_event_venue_rel, $this->_new_table, $cols_n_values, $datatypes));
125 125
             return 0;
126 126
         }
Please login to merge, or discard this patch.
4_1_0_stages/EE_DMS_4_1_0_event_question_group.dmsstage.php 1 patch
Indentation   +75 added lines, -77 removed lines patch added patch discarded remove patch
@@ -16,15 +16,13 @@  discard block
 block discarded – undo
16 16
             'EQG_primary'=>new EE_Boolean_Field('EQG_primary', __('Flag indicating question is only for primary attendees','event_espresso'), false, false)
17 17
         )
18 18
     );
19
-
20
-
21 19
  *
22 20
  */
23 21
 class EE_DMS_4_1_0_event_question_group extends EE_Data_Migration_Script_Stage_Table
24 22
 {
25
-    private $_new_table;
26
-    public function _migrate_old_row($old_row)
27
-    {
23
+	private $_new_table;
24
+	public function _migrate_old_row($old_row)
25
+	{
28 26
 //      $txn_id = $this->get_migration_script()->get_mapping_new_pk($this->_old_table, $old_row['id'], $this->_new_transaction_table);
29 27
 //          if ( ! $txn_id ){
30 28
 //              $this->add_error(sprintf(__("Could not find the transaction for the 3.1 attendee %d from row %s", "event_espresso"),$old_row['id'],$this->_json_encode($old_row)));
@@ -34,8 +32,8 @@  discard block
 block discarded – undo
34 32
 //          $new_line_items = $this->_insert_new_line_items($txn,$old_row);
35 33
 //          $this->get_migration_script()->set_mapping($this->_old_table,$old_row['id'],$this->_new_line_table,$new_line_items);
36 34
 
37
-            $this->_insert_new_event_question_groups($old_row);
38
-    }
35
+			$this->_insert_new_event_question_groups($old_row);
36
+	}
39 37
 //  function _migration_step($num_items=50){
40 38
 //      global $wpdb;
41 39
 //      $start_at_record = $this->count_records_migrated();
@@ -55,79 +53,79 @@  discard block
 block discarded – undo
55 53
 //      $count = $wpdb->get_var("SELECT COUNT(id) FROM ".$this->_old_table);
56 54
 //      return $count;
57 55
 //  }
58
-    public function __construct()
59
-    {
60
-        global $wpdb;
61
-        $this->_old_table = $wpdb->prefix."events_detail";
62
-        $this->_extra_where_sql = 'WHERE event_status!="D"';
63
-        $this->_new_table = $wpdb->prefix."esp_event_question_group";
64
-        $this->_pretty_name = __("Question Groups in each Event", "event_espresso");
65
-        parent::__construct();
66
-    }
56
+	public function __construct()
57
+	{
58
+		global $wpdb;
59
+		$this->_old_table = $wpdb->prefix."events_detail";
60
+		$this->_extra_where_sql = 'WHERE event_status!="D"';
61
+		$this->_new_table = $wpdb->prefix."esp_event_question_group";
62
+		$this->_pretty_name = __("Question Groups in each Event", "event_espresso");
63
+		parent::__construct();
64
+	}
67 65
 
68
-    /**
69
-     * Attempts to insert a new question group inthe new format given an old one
70
-     * @global type $wpdb
71
-     * @param array $old_event
72
-     * @return void
73
-     */
74
-    private function _insert_new_event_question_groups($old_event)
75
-    {
76
-        $new_event_question_group_ids = array();
77
-        $question_groups_for_primary = maybe_unserialize($old_event['question_groups']);
78
-        if (is_array($question_groups_for_primary)) {
79
-            foreach ($question_groups_for_primary as $old_question_group_id) {
80
-                $new_id = $this->_insert_event_question_group($old_event, $old_question_group_id, true);
81
-                if ($new_id) {
82
-                    $new_event_question_group_ids[] = $new_id;
83
-                }
84
-            }
85
-        }
86
-        $event_meta = maybe_unserialize($old_event['event_meta']);
87
-        if (isset($event_meta['add_attendee_question_groups'])) {
88
-            if (is_array($event_meta['add_attendee_question_groups'])) {
89
-                foreach ($event_meta['add_attendee_question_groups'] as $old_question_group_id) {
90
-                    $new_id = $this->_insert_event_question_group($old_event, $old_question_group_id, false);
91
-                    if ($new_id) {
92
-                        $new_event_question_group_ids[] = $new_id;
93
-                    }
94
-                }
95
-            }
96
-        }
66
+	/**
67
+	 * Attempts to insert a new question group inthe new format given an old one
68
+	 * @global type $wpdb
69
+	 * @param array $old_event
70
+	 * @return void
71
+	 */
72
+	private function _insert_new_event_question_groups($old_event)
73
+	{
74
+		$new_event_question_group_ids = array();
75
+		$question_groups_for_primary = maybe_unserialize($old_event['question_groups']);
76
+		if (is_array($question_groups_for_primary)) {
77
+			foreach ($question_groups_for_primary as $old_question_group_id) {
78
+				$new_id = $this->_insert_event_question_group($old_event, $old_question_group_id, true);
79
+				if ($new_id) {
80
+					$new_event_question_group_ids[] = $new_id;
81
+				}
82
+			}
83
+		}
84
+		$event_meta = maybe_unserialize($old_event['event_meta']);
85
+		if (isset($event_meta['add_attendee_question_groups'])) {
86
+			if (is_array($event_meta['add_attendee_question_groups'])) {
87
+				foreach ($event_meta['add_attendee_question_groups'] as $old_question_group_id) {
88
+					$new_id = $this->_insert_event_question_group($old_event, $old_question_group_id, false);
89
+					if ($new_id) {
90
+						$new_event_question_group_ids[] = $new_id;
91
+					}
92
+				}
93
+			}
94
+		}
97 95
 
98 96
 
99
-        $this->get_migration_script()->set_mapping($this->_old_table, $old_event['id'], $this->_new_table, $new_event_question_group_ids);
100
-    }
97
+		$this->get_migration_script()->set_mapping($this->_old_table, $old_event['id'], $this->_new_table, $new_event_question_group_ids);
98
+	}
101 99
 
102
-    private function _insert_event_question_group($old_event, $old_question_group_id, $primary)
103
-    {
104
-        global $wpdb;
105
-        $new_question_group_id =$this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_qst_group", intval($old_question_group_id), $wpdb->prefix."esp_question_group");
100
+	private function _insert_event_question_group($old_event, $old_question_group_id, $primary)
101
+	{
102
+		global $wpdb;
103
+		$new_question_group_id =$this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_qst_group", intval($old_question_group_id), $wpdb->prefix."esp_question_group");
106 104
 
107
-        if (! $new_question_group_id) {
108
-            $this->add_error(sprintf(__("Could not find 4.1 question ID for 3.1 question id #%s on event $%s", "event_espresso"), $old_question_group_id, $old_event['id']));
109
-            return 0;
110
-        }
111
-        $new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_detail", intval($old_event['id']), $wpdb->posts);
112
-        if (! $new_question_group_id) {
113
-            $this->add_error(sprintf(__("Could not find 4.1 event 3.1 event id #%s", "event_espresso"), $old_event['id']));
114
-            return 0;
115
-        }
116
-        $cols_n_values = array(
117
-            'EVT_ID'=>$new_event_id,
118
-            'QSG_ID'=>$new_question_group_id,
119
-            'EQG_primary'=>$primary
120
-        );
121
-        $datatypes = array(
122
-            '%d',// EVT_ID
123
-            '%d',// QSG_ID
124
-            '%d',// EQG_primary
125
-        );
126
-        $success = $wpdb->insert($this->_new_table, $cols_n_values, $datatypes);
127
-        if (! $success) {
128
-            $this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_event, $this->_new_table, $cols_n_values, $datatypes));
129
-            return 0;
130
-        }
131
-        return $wpdb->insert_id;
132
-    }
105
+		if (! $new_question_group_id) {
106
+			$this->add_error(sprintf(__("Could not find 4.1 question ID for 3.1 question id #%s on event $%s", "event_espresso"), $old_question_group_id, $old_event['id']));
107
+			return 0;
108
+		}
109
+		$new_event_id = $this->get_migration_script()->get_mapping_new_pk($wpdb->prefix."events_detail", intval($old_event['id']), $wpdb->posts);
110
+		if (! $new_question_group_id) {
111
+			$this->add_error(sprintf(__("Could not find 4.1 event 3.1 event id #%s", "event_espresso"), $old_event['id']));
112
+			return 0;
113
+		}
114
+		$cols_n_values = array(
115
+			'EVT_ID'=>$new_event_id,
116
+			'QSG_ID'=>$new_question_group_id,
117
+			'EQG_primary'=>$primary
118
+		);
119
+		$datatypes = array(
120
+			'%d',// EVT_ID
121
+			'%d',// QSG_ID
122
+			'%d',// EQG_primary
123
+		);
124
+		$success = $wpdb->insert($this->_new_table, $cols_n_values, $datatypes);
125
+		if (! $success) {
126
+			$this->add_error($this->get_migration_script()->_create_error_message_for_db_insertion($this->_old_table, $old_event, $this->_new_table, $cols_n_values, $datatypes));
127
+			return 0;
128
+		}
129
+		return $wpdb->insert_id;
130
+	}
133 131
 }
Please login to merge, or discard this patch.
core/domain/services/pue/Config.php 1 patch
Indentation   +127 added lines, -127 removed lines patch added patch discarded remove patch
@@ -16,131 +16,131 @@
 block discarded – undo
16 16
  */
17 17
 class Config
18 18
 {
19
-    /**
20
-     * @var EE_Network_Config
21
-     */
22
-    private $network_config;
23
-
24
-
25
-    /**
26
-     * @var EE_Config
27
-     */
28
-    private $ee_config;
29
-
30
-
31
-    public function __construct(EE_Network_Config $network_config, EE_Config $ee_config)
32
-    {
33
-        $this->network_config = $network_config;
34
-        $this->ee_config = $ee_config;
35
-    }
36
-
37
-
38
-    /**
39
-     * Get the site license key for the site.
40
-     */
41
-    public function siteLicenseKey()
42
-    {
43
-        return $this->network_config->core->site_license_key;
44
-    }
45
-
46
-
47
-    public function i18nDomain()
48
-    {
49
-        return 'event_espresso';
50
-    }
51
-
52
-
53
-    public function checkPeriod()
54
-    {
55
-        return 24;
56
-    }
57
-
58
-
59
-    public function optionKey()
60
-    {
61
-        return 'ee_site_license_key';
62
-    }
63
-
64
-
65
-    public function optionsPageSlug()
66
-    {
67
-        return 'espresso_general_settings';
68
-    }
69
-
70
-
71
-    public function hostServerUrl()
72
-    {
73
-        return defined('PUE_UPDATES_ENDPOINT')
74
-            ? PUE_UPDATES_ENDPOINT
75
-            : 'https://eventespresso.com';
76
-    }
77
-
78
-
79
-    public function pluginSlug()
80
-    {
81
-        // Note: PUE uses a simple preg_match to determine what type is currently installed based on version number.
82
-        //  So it's important that you use a key for the version type that is unique and not found in another key.
83
-        // For example:
84
-        // $plugin_slug['premium']['p'] = 'some-premium-slug';
85
-        // $plugin_slug['prerelease']['pr'] = 'some-pre-release-slug';
86
-        // The above would not work because "p" is found in both keys for the version type. ( i.e 1.0.p vs 1.0.pr )
87
-        // so doing something like:
88
-        // $plugin_slug['premium']['p'] = 'some-premium-slug';
89
-        // $plugin_slug['prerelease']['b'] = 'some-pre-release-slug';
90
-        // ..WOULD work!
91
-        return array(
92
-            'free'       => array('decaf' => 'event-espresso-core-decaf'),
93
-            'premium'    => array('p' => 'event-espresso-core-reg'),
94
-            'prerelease' => array('beta' => 'event-espresso-core-pr'),
95
-        );
96
-    }
97
-
98
-
99
-    /**
100
-     * Return whether the site is opted in for UXIP or not.
101
-     *
102
-     * @return bool
103
-     */
104
-    public function isOptedInForUxip()
105
-    {
106
-        return filter_var($this->ee_config->core->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN);
107
-    }
108
-
109
-
110
-    /**
111
-     * Return whether the site has been notified about UXIP or not.
112
-     *
113
-     * @return bool
114
-     */
115
-    public function hasNotifiedForUxip()
116
-    {
117
-        return filter_var($this->ee_config->core->ee_ueip_has_notified, FILTER_VALIDATE_BOOLEAN);
118
-    }
119
-
120
-
121
-    /**
122
-     * Set the site opted in for UXIP.
123
-     */
124
-    public function setHasOptedInForUxip()
125
-    {
126
-        $this->ee_config->core->ee_ueip_optin = true;
127
-        $this->ee_config->update_espresso_config(false, false);
128
-    }
129
-
130
-
131
-    /**
132
-     * Set the site opted out for UXIP
133
-     */
134
-    public function setHasOptedOutForUxip()
135
-    {
136
-        $this->ee_config->core->ee_ueip_optin = false;
137
-        $this->ee_config->update_espresso_config(false, false);
138
-    }
139
-
140
-
141
-    public function setHasNotifiedAboutUxip()
142
-    {
143
-        $this->ee_config->core->ee_ueip_has_notified = true;
144
-        $this->ee_config->update_espresso_config(false, false);
145
-    }
19
+	/**
20
+	 * @var EE_Network_Config
21
+	 */
22
+	private $network_config;
23
+
24
+
25
+	/**
26
+	 * @var EE_Config
27
+	 */
28
+	private $ee_config;
29
+
30
+
31
+	public function __construct(EE_Network_Config $network_config, EE_Config $ee_config)
32
+	{
33
+		$this->network_config = $network_config;
34
+		$this->ee_config = $ee_config;
35
+	}
36
+
37
+
38
+	/**
39
+	 * Get the site license key for the site.
40
+	 */
41
+	public function siteLicenseKey()
42
+	{
43
+		return $this->network_config->core->site_license_key;
44
+	}
45
+
46
+
47
+	public function i18nDomain()
48
+	{
49
+		return 'event_espresso';
50
+	}
51
+
52
+
53
+	public function checkPeriod()
54
+	{
55
+		return 24;
56
+	}
57
+
58
+
59
+	public function optionKey()
60
+	{
61
+		return 'ee_site_license_key';
62
+	}
63
+
64
+
65
+	public function optionsPageSlug()
66
+	{
67
+		return 'espresso_general_settings';
68
+	}
69
+
70
+
71
+	public function hostServerUrl()
72
+	{
73
+		return defined('PUE_UPDATES_ENDPOINT')
74
+			? PUE_UPDATES_ENDPOINT
75
+			: 'https://eventespresso.com';
76
+	}
77
+
78
+
79
+	public function pluginSlug()
80
+	{
81
+		// Note: PUE uses a simple preg_match to determine what type is currently installed based on version number.
82
+		//  So it's important that you use a key for the version type that is unique and not found in another key.
83
+		// For example:
84
+		// $plugin_slug['premium']['p'] = 'some-premium-slug';
85
+		// $plugin_slug['prerelease']['pr'] = 'some-pre-release-slug';
86
+		// The above would not work because "p" is found in both keys for the version type. ( i.e 1.0.p vs 1.0.pr )
87
+		// so doing something like:
88
+		// $plugin_slug['premium']['p'] = 'some-premium-slug';
89
+		// $plugin_slug['prerelease']['b'] = 'some-pre-release-slug';
90
+		// ..WOULD work!
91
+		return array(
92
+			'free'       => array('decaf' => 'event-espresso-core-decaf'),
93
+			'premium'    => array('p' => 'event-espresso-core-reg'),
94
+			'prerelease' => array('beta' => 'event-espresso-core-pr'),
95
+		);
96
+	}
97
+
98
+
99
+	/**
100
+	 * Return whether the site is opted in for UXIP or not.
101
+	 *
102
+	 * @return bool
103
+	 */
104
+	public function isOptedInForUxip()
105
+	{
106
+		return filter_var($this->ee_config->core->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN);
107
+	}
108
+
109
+
110
+	/**
111
+	 * Return whether the site has been notified about UXIP or not.
112
+	 *
113
+	 * @return bool
114
+	 */
115
+	public function hasNotifiedForUxip()
116
+	{
117
+		return filter_var($this->ee_config->core->ee_ueip_has_notified, FILTER_VALIDATE_BOOLEAN);
118
+	}
119
+
120
+
121
+	/**
122
+	 * Set the site opted in for UXIP.
123
+	 */
124
+	public function setHasOptedInForUxip()
125
+	{
126
+		$this->ee_config->core->ee_ueip_optin = true;
127
+		$this->ee_config->update_espresso_config(false, false);
128
+	}
129
+
130
+
131
+	/**
132
+	 * Set the site opted out for UXIP
133
+	 */
134
+	public function setHasOptedOutForUxip()
135
+	{
136
+		$this->ee_config->core->ee_ueip_optin = false;
137
+		$this->ee_config->update_espresso_config(false, false);
138
+	}
139
+
140
+
141
+	public function setHasNotifiedAboutUxip()
142
+	{
143
+		$this->ee_config->core->ee_ueip_has_notified = true;
144
+		$this->ee_config->update_espresso_config(false, false);
145
+	}
146 146
 }
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Addon.lib.php 2 patches
Indentation   +1161 added lines, -1161 removed lines patch added patch discarded remove patch
@@ -22,1225 +22,1225 @@
 block discarded – undo
22 22
 class EE_Register_Addon implements EEI_Plugin_API
23 23
 {
24 24
 
25
-    /**
26
-     * possibly truncated version of the EE core version string
27
-     *
28
-     * @var string
29
-     */
30
-    protected static $_core_version = '';
25
+	/**
26
+	 * possibly truncated version of the EE core version string
27
+	 *
28
+	 * @var string
29
+	 */
30
+	protected static $_core_version = '';
31 31
 
32
-    /**
33
-     * Holds values for registered addons
34
-     *
35
-     * @var array
36
-     */
37
-    protected static $_settings = array();
32
+	/**
33
+	 * Holds values for registered addons
34
+	 *
35
+	 * @var array
36
+	 */
37
+	protected static $_settings = array();
38 38
 
39
-    /**
40
-     * @var  array $_incompatible_addons keys are addon SLUGS
41
-     * (first argument passed to EE_Register_Addon::register()), keys are
42
-     * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
43
-     * Generally this should be used sparingly, as we don't want to muddle up
44
-     * EE core with knowledge of ALL the addons out there.
45
-     * If you want NO versions of an addon to run with a certain version of core,
46
-     * it's usually best to define the addon's "min_core_version" as part of its call
47
-     * to EE_Register_Addon::register(), rather than using this array with a super high value for its
48
-     * minimum plugin version.
49
-     * @access    protected
50
-     */
51
-    protected static $_incompatible_addons = array(
52
-        'Multi_Event_Registration' => '2.0.11.rc.002',
53
-        'Promotions'               => '1.0.0.rc.084',
54
-    );
39
+	/**
40
+	 * @var  array $_incompatible_addons keys are addon SLUGS
41
+	 * (first argument passed to EE_Register_Addon::register()), keys are
42
+	 * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
43
+	 * Generally this should be used sparingly, as we don't want to muddle up
44
+	 * EE core with knowledge of ALL the addons out there.
45
+	 * If you want NO versions of an addon to run with a certain version of core,
46
+	 * it's usually best to define the addon's "min_core_version" as part of its call
47
+	 * to EE_Register_Addon::register(), rather than using this array with a super high value for its
48
+	 * minimum plugin version.
49
+	 * @access    protected
50
+	 */
51
+	protected static $_incompatible_addons = array(
52
+		'Multi_Event_Registration' => '2.0.11.rc.002',
53
+		'Promotions'               => '1.0.0.rc.084',
54
+	);
55 55
 
56 56
 
57
-    /**
58
-     * We should always be comparing core to a version like '4.3.0.rc.000',
59
-     * not just '4.3.0'.
60
-     * So if the addon developer doesn't provide that full version string,
61
-     * fill in the blanks for them
62
-     *
63
-     * @param string $min_core_version
64
-     * @return string always like '4.3.0.rc.000'
65
-     */
66
-    protected static function _effective_version($min_core_version)
67
-    {
68
-        // versions: 4 . 3 . 1 . p . 123
69
-        // offsets:    0 . 1 . 2 . 3 . 4
70
-        $version_parts = explode('.', $min_core_version);
71
-        // check they specified the micro version (after 2nd period)
72
-        if (! isset($version_parts[2])) {
73
-            $version_parts[2] = '0';
74
-        }
75
-        // if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76
-        // soon we can assume that's 'rc', but this current version is 'alpha'
77
-        if (! isset($version_parts[3])) {
78
-            $version_parts[3] = 'dev';
79
-        }
80
-        if (! isset($version_parts[4])) {
81
-            $version_parts[4] = '000';
82
-        }
83
-        return implode('.', $version_parts);
84
-    }
57
+	/**
58
+	 * We should always be comparing core to a version like '4.3.0.rc.000',
59
+	 * not just '4.3.0'.
60
+	 * So if the addon developer doesn't provide that full version string,
61
+	 * fill in the blanks for them
62
+	 *
63
+	 * @param string $min_core_version
64
+	 * @return string always like '4.3.0.rc.000'
65
+	 */
66
+	protected static function _effective_version($min_core_version)
67
+	{
68
+		// versions: 4 . 3 . 1 . p . 123
69
+		// offsets:    0 . 1 . 2 . 3 . 4
70
+		$version_parts = explode('.', $min_core_version);
71
+		// check they specified the micro version (after 2nd period)
72
+		if (! isset($version_parts[2])) {
73
+			$version_parts[2] = '0';
74
+		}
75
+		// if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76
+		// soon we can assume that's 'rc', but this current version is 'alpha'
77
+		if (! isset($version_parts[3])) {
78
+			$version_parts[3] = 'dev';
79
+		}
80
+		if (! isset($version_parts[4])) {
81
+			$version_parts[4] = '000';
82
+		}
83
+		return implode('.', $version_parts);
84
+	}
85 85
 
86 86
 
87
-    /**
88
-     * Returns whether or not the min core version requirement of the addon is met
89
-     *
90
-     * @param string $min_core_version    the minimum core version required by the addon
91
-     * @param string $actual_core_version the actual core version, optional
92
-     * @return boolean
93
-     */
94
-    public static function _meets_min_core_version_requirement(
95
-        $min_core_version,
96
-        $actual_core_version = EVENT_ESPRESSO_VERSION
97
-    ) {
98
-        return version_compare(
99
-            self::_effective_version($actual_core_version),
100
-            self::_effective_version($min_core_version),
101
-            '>='
102
-        );
103
-    }
87
+	/**
88
+	 * Returns whether or not the min core version requirement of the addon is met
89
+	 *
90
+	 * @param string $min_core_version    the minimum core version required by the addon
91
+	 * @param string $actual_core_version the actual core version, optional
92
+	 * @return boolean
93
+	 */
94
+	public static function _meets_min_core_version_requirement(
95
+		$min_core_version,
96
+		$actual_core_version = EVENT_ESPRESSO_VERSION
97
+	) {
98
+		return version_compare(
99
+			self::_effective_version($actual_core_version),
100
+			self::_effective_version($min_core_version),
101
+			'>='
102
+		);
103
+	}
104 104
 
105 105
 
106
-    /**
107
-     * Method for registering new EE_Addons.
108
-     * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
109
-     * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
110
-     * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
111
-     * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
112
-     * 'activate_plugin', it registers the addon still, but its components are not registered
113
-     * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
114
-     * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
115
-     * (so that we can detect that the addon has activated on the subsequent request)
116
-     *
117
-     * @since    4.3.0
118
-     * @param string                  $addon_name                       [Required] the EE_Addon's name.
119
-     * @param  array                  $setup_args                       {
120
-     *                                                                  An array of arguments provided for registering
121
-     *                                                                  the message type.
122
-     * @type  string                  $class_name                       the addon's main file name.
123
-     *                                                                  If left blank, generated from the addon name,
124
-     *                                                                  changes something like "calendar" to
125
-     *                                                                  "EE_Calendar"
126
-     * @type string                   $min_core_version                 the minimum version of EE Core that the
127
-     *                                                                  addon will work with. eg "4.8.1.rc.084"
128
-     * @type string                   $version                          the "software" version for the addon. eg
129
-     *                                                                  "1.0.0.p" for a first stable release, or
130
-     *                                                                  "1.0.0.rc.043" for a version in progress
131
-     * @type string                   $main_file_path                   the full server path to the main file
132
-     *                                                                  loaded directly by WP
133
-     * @type DomainInterface $domain                                    child class of
134
-     *                                                                  EventEspresso\core\domain\DomainBase
135
-     * @type string                   $domain_fqcn                      Fully Qualified Class Name
136
-     *                                                                  for the addon's Domain class
137
-     *                                                                  (see EventEspresso\core\domain\Domain)
138
-     * @type string                   $admin_path                       full server path to the folder where the
139
-     *                                                                  addon\'s admin files reside
140
-     * @type string                   $admin_callback                   a method to be called when the EE Admin is
141
-     *                                                                  first invoked, can be used for hooking into
142
-     *                                                                  any admin page
143
-     * @type string                   $config_section                   the section name for this addon's
144
-     *                                                                  configuration settings section
145
-     *                                                                  (defaults to "addons")
146
-     * @type string                   $config_class                     the class name for this addon's
147
-     *                                                                  configuration settings object
148
-     * @type string                   $config_name                      the class name for this addon's
149
-     *                                                                  configuration settings object
150
-     * @type string                   $autoloader_paths                 [Required] an array of class names and the full
151
-     *                                                                  server paths to those files.
152
-     * @type string                   $autoloader_folders               an array of  "full server paths" for any
153
-     *                                                                  folders containing classes that might be
154
-     *                                                                  invoked by the addon
155
-     * @type string                   $dms_paths                        [Required] an array of full server paths to
156
-     *                                                                  folders that contain data migration scripts.
157
-     *                                                                  The key should be the EE_Addon class name that
158
-     *                                                                  this set of data migration scripts belongs to.
159
-     *                                                                  If the EE_Addon class is namespaced, then this
160
-     *                                                                  needs to be the Fully Qualified Class Name
161
-     * @type string                   $module_paths                     an array of full server paths to any
162
-     *                                                                  EED_Modules used by the addon
163
-     * @type string                   $shortcode_paths                  an array of full server paths to folders
164
-     *                                                                  that contain EES_Shortcodes
165
-     * @type string                   $widget_paths                     an array of full server paths to folders
166
-     *                                                                  that contain WP_Widgets
167
-     * @type string                   $pue_options
168
-     * @type array                    $capabilities                     an array indexed by role name
169
-     *                                                                  (i.e administrator,author ) and the values
170
-     *                                                                  are an array of caps to add to the role.
171
-     *                                                                  'administrator' => array(
172
-     *                                                                  'read_addon',
173
-     *                                                                  'edit_addon',
174
-     *                                                                  etc.
175
-     *                                                                  ).
176
-     * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
177
-     *                                                                  for any addons that need to register any
178
-     *                                                                  special meta mapped capabilities.  Should
179
-     *                                                                  be indexed where the key is the
180
-     *                                                                  EE_Meta_Capability_Map class name and the
181
-     *                                                                  values are the arguments sent to the class.
182
-     * @type array                    $model_paths                      array of folders containing DB models
183
-     * @see      EE_Register_Model
184
-     * @type array                    $class_paths                      array of folders containing DB classes
185
-     * @see      EE_Register_Model
186
-     * @type array                    $model_extension_paths            array of folders containing DB model
187
-     *                                                                  extensions
188
-     * @see      EE_Register_Model_Extension
189
-     * @type array                    $class_extension_paths            array of folders containing DB class
190
-     *                                                                  extensions
191
-     * @see      EE_Register_Model_Extension
192
-     * @type array message_types {
193
-     *                                                                  An array of message types with the key as
194
-     *                                                                  the message type name and the values as
195
-     *                                                                  below:
196
-     * @type string                   $mtfilename                       [Required] The filename of the message type
197
-     *                                                                  being registered. This will be the main
198
-     *                                                                  EE_{Message Type Name}_message_type class.
199
-     *                                                                  for example:
200
-     *                                                                  EE_Declined_Registration_message_type.class.php
201
-     * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
202
-     *                                                                  messages autoloader for the new message type.
203
-     * @type array                    $messengers_to_activate_with      An array of messengers that this message
204
-     *                                                                  type should activate with. Each value in
205
-     *                                                                  the
206
-     *                                                                  array
207
-     *                                                                  should match the name property of a
208
-     *                                                                  EE_messenger. Optional.
209
-     * @type array                    $messengers_to_validate_with      An array of messengers that this message
210
-     *                                                                  type should validate with. Each value in
211
-     *                                                                  the
212
-     *                                                                  array
213
-     *                                                                  should match the name property of an
214
-     *                                                                  EE_messenger.
215
-     *                                                                  Optional.
216
-     *                                                                  }
217
-     * @type array                    $custom_post_types
218
-     * @type array                    $custom_taxonomies
219
-     * @type array                    $payment_method_paths             each element is the folder containing the
220
-     *                                                                  EE_PMT_Base child class
221
-     *                                                                  (eg,
222
-     *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
223
-     *                                                                  which contains the files
224
-     *                                                                  EE_PMT_Payomatic.pm.php)
225
-     * @type array                    $default_terms
226
-     * @type array                    $namespace                        {
227
-     *                                                                  An array with two items for registering the
228
-     *                                                                  addon's namespace. (If, for some reason, you
229
-     *                                                                  require additional namespaces,
230
-     *                                                                  use
231
-     *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
232
-     *                                                                  directly)
233
-     * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
234
-     * @type string                   $FQNS                             the namespace prefix
235
-     * @type string                   $DIR                              a base directory for class files in the
236
-     *                                                                  namespace.
237
-     *                                                                  }
238
-     *                                                                  }
239
-     * @type string                   $privacy_policies                 FQNSs (namespaces, each of which contains only
240
-     *                                                                  privacy policy classes) or FQCNs (specific
241
-     *                                                                  classnames of privacy policy classes)
242
-     * @type string                   $personal_data_exporters          FQNSs (namespaces, each of which contains only
243
-     *                                                                  privacy policy classes) or FQCNs (specific
244
-     *                                                                  classnames of privacy policy classes)
245
-     * @type string                   $personal_data_erasers            FQNSs (namespaces, each of which contains only
246
-     *                                                                  privacy policy classes) or FQCNs (specific
247
-     *                                                                  classnames of privacy policy classes)
248
-     * @return void
249
-     * @throws DomainException
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws ReflectionException
253
-     * @throws InvalidDataTypeException
254
-     * @throws InvalidInterfaceException
255
-     */
256
-    public static function register($addon_name = '', $setup_args = array())
257
-    {
258
-        // required fields MUST be present, so let's make sure they are.
259
-        EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
260
-        // get class name for addon
261
-        $class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
262
-        // setup $_settings array from incoming values.
263
-        $addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
264
-        // setup PUE
265
-        EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
266
-        // does this addon work with this version of core or WordPress ?
267
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268
-            return;
269
-        }
270
-        // register namespaces
271
-        EE_Register_Addon::_setup_namespaces($addon_settings);
272
-        // check if this is an activation request
273
-        if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
274
-            // dont bother setting up the rest of the addon atm
275
-            return;
276
-        }
277
-        // we need cars
278
-        EE_Register_Addon::_setup_autoloaders($addon_name);
279
-        // register new models and extensions
280
-        EE_Register_Addon::_register_models_and_extensions($addon_name);
281
-        // setup DMS
282
-        EE_Register_Addon::_register_data_migration_scripts($addon_name);
283
-        // if config_class is present let's register config.
284
-        EE_Register_Addon::_register_config($addon_name);
285
-        // register admin pages
286
-        EE_Register_Addon::_register_admin_pages($addon_name);
287
-        // add to list of modules to be registered
288
-        EE_Register_Addon::_register_modules($addon_name);
289
-        // add to list of shortcodes to be registered
290
-        EE_Register_Addon::_register_shortcodes($addon_name);
291
-        // add to list of widgets to be registered
292
-        EE_Register_Addon::_register_widgets($addon_name);
293
-        // register capability related stuff.
294
-        EE_Register_Addon::_register_capabilities($addon_name);
295
-        // any message type to register?
296
-        EE_Register_Addon::_register_message_types($addon_name);
297
-        // any custom post type/ custom capabilities or default terms to register
298
-        EE_Register_Addon::_register_custom_post_types($addon_name);
299
-        // and any payment methods
300
-        EE_Register_Addon::_register_payment_methods($addon_name);
301
-        // and privacy policy generators
302
-        EE_Register_Addon::registerPrivacyPolicies($addon_name);
303
-        // and privacy policy generators
304
-        EE_Register_Addon::registerPersonalDataExporters($addon_name);
305
-        // and privacy policy generators
306
-        EE_Register_Addon::registerPersonalDataErasers($addon_name);
307
-        // load and instantiate main addon class
308
-        $addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
309
-        // delay calling after_registration hook on each addon until after all add-ons have been registered.
310
-        add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
311
-    }
106
+	/**
107
+	 * Method for registering new EE_Addons.
108
+	 * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
109
+	 * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
110
+	 * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
111
+	 * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
112
+	 * 'activate_plugin', it registers the addon still, but its components are not registered
113
+	 * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
114
+	 * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
115
+	 * (so that we can detect that the addon has activated on the subsequent request)
116
+	 *
117
+	 * @since    4.3.0
118
+	 * @param string                  $addon_name                       [Required] the EE_Addon's name.
119
+	 * @param  array                  $setup_args                       {
120
+	 *                                                                  An array of arguments provided for registering
121
+	 *                                                                  the message type.
122
+	 * @type  string                  $class_name                       the addon's main file name.
123
+	 *                                                                  If left blank, generated from the addon name,
124
+	 *                                                                  changes something like "calendar" to
125
+	 *                                                                  "EE_Calendar"
126
+	 * @type string                   $min_core_version                 the minimum version of EE Core that the
127
+	 *                                                                  addon will work with. eg "4.8.1.rc.084"
128
+	 * @type string                   $version                          the "software" version for the addon. eg
129
+	 *                                                                  "1.0.0.p" for a first stable release, or
130
+	 *                                                                  "1.0.0.rc.043" for a version in progress
131
+	 * @type string                   $main_file_path                   the full server path to the main file
132
+	 *                                                                  loaded directly by WP
133
+	 * @type DomainInterface $domain                                    child class of
134
+	 *                                                                  EventEspresso\core\domain\DomainBase
135
+	 * @type string                   $domain_fqcn                      Fully Qualified Class Name
136
+	 *                                                                  for the addon's Domain class
137
+	 *                                                                  (see EventEspresso\core\domain\Domain)
138
+	 * @type string                   $admin_path                       full server path to the folder where the
139
+	 *                                                                  addon\'s admin files reside
140
+	 * @type string                   $admin_callback                   a method to be called when the EE Admin is
141
+	 *                                                                  first invoked, can be used for hooking into
142
+	 *                                                                  any admin page
143
+	 * @type string                   $config_section                   the section name for this addon's
144
+	 *                                                                  configuration settings section
145
+	 *                                                                  (defaults to "addons")
146
+	 * @type string                   $config_class                     the class name for this addon's
147
+	 *                                                                  configuration settings object
148
+	 * @type string                   $config_name                      the class name for this addon's
149
+	 *                                                                  configuration settings object
150
+	 * @type string                   $autoloader_paths                 [Required] an array of class names and the full
151
+	 *                                                                  server paths to those files.
152
+	 * @type string                   $autoloader_folders               an array of  "full server paths" for any
153
+	 *                                                                  folders containing classes that might be
154
+	 *                                                                  invoked by the addon
155
+	 * @type string                   $dms_paths                        [Required] an array of full server paths to
156
+	 *                                                                  folders that contain data migration scripts.
157
+	 *                                                                  The key should be the EE_Addon class name that
158
+	 *                                                                  this set of data migration scripts belongs to.
159
+	 *                                                                  If the EE_Addon class is namespaced, then this
160
+	 *                                                                  needs to be the Fully Qualified Class Name
161
+	 * @type string                   $module_paths                     an array of full server paths to any
162
+	 *                                                                  EED_Modules used by the addon
163
+	 * @type string                   $shortcode_paths                  an array of full server paths to folders
164
+	 *                                                                  that contain EES_Shortcodes
165
+	 * @type string                   $widget_paths                     an array of full server paths to folders
166
+	 *                                                                  that contain WP_Widgets
167
+	 * @type string                   $pue_options
168
+	 * @type array                    $capabilities                     an array indexed by role name
169
+	 *                                                                  (i.e administrator,author ) and the values
170
+	 *                                                                  are an array of caps to add to the role.
171
+	 *                                                                  'administrator' => array(
172
+	 *                                                                  'read_addon',
173
+	 *                                                                  'edit_addon',
174
+	 *                                                                  etc.
175
+	 *                                                                  ).
176
+	 * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
177
+	 *                                                                  for any addons that need to register any
178
+	 *                                                                  special meta mapped capabilities.  Should
179
+	 *                                                                  be indexed where the key is the
180
+	 *                                                                  EE_Meta_Capability_Map class name and the
181
+	 *                                                                  values are the arguments sent to the class.
182
+	 * @type array                    $model_paths                      array of folders containing DB models
183
+	 * @see      EE_Register_Model
184
+	 * @type array                    $class_paths                      array of folders containing DB classes
185
+	 * @see      EE_Register_Model
186
+	 * @type array                    $model_extension_paths            array of folders containing DB model
187
+	 *                                                                  extensions
188
+	 * @see      EE_Register_Model_Extension
189
+	 * @type array                    $class_extension_paths            array of folders containing DB class
190
+	 *                                                                  extensions
191
+	 * @see      EE_Register_Model_Extension
192
+	 * @type array message_types {
193
+	 *                                                                  An array of message types with the key as
194
+	 *                                                                  the message type name and the values as
195
+	 *                                                                  below:
196
+	 * @type string                   $mtfilename                       [Required] The filename of the message type
197
+	 *                                                                  being registered. This will be the main
198
+	 *                                                                  EE_{Message Type Name}_message_type class.
199
+	 *                                                                  for example:
200
+	 *                                                                  EE_Declined_Registration_message_type.class.php
201
+	 * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
202
+	 *                                                                  messages autoloader for the new message type.
203
+	 * @type array                    $messengers_to_activate_with      An array of messengers that this message
204
+	 *                                                                  type should activate with. Each value in
205
+	 *                                                                  the
206
+	 *                                                                  array
207
+	 *                                                                  should match the name property of a
208
+	 *                                                                  EE_messenger. Optional.
209
+	 * @type array                    $messengers_to_validate_with      An array of messengers that this message
210
+	 *                                                                  type should validate with. Each value in
211
+	 *                                                                  the
212
+	 *                                                                  array
213
+	 *                                                                  should match the name property of an
214
+	 *                                                                  EE_messenger.
215
+	 *                                                                  Optional.
216
+	 *                                                                  }
217
+	 * @type array                    $custom_post_types
218
+	 * @type array                    $custom_taxonomies
219
+	 * @type array                    $payment_method_paths             each element is the folder containing the
220
+	 *                                                                  EE_PMT_Base child class
221
+	 *                                                                  (eg,
222
+	 *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
223
+	 *                                                                  which contains the files
224
+	 *                                                                  EE_PMT_Payomatic.pm.php)
225
+	 * @type array                    $default_terms
226
+	 * @type array                    $namespace                        {
227
+	 *                                                                  An array with two items for registering the
228
+	 *                                                                  addon's namespace. (If, for some reason, you
229
+	 *                                                                  require additional namespaces,
230
+	 *                                                                  use
231
+	 *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
232
+	 *                                                                  directly)
233
+	 * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
234
+	 * @type string                   $FQNS                             the namespace prefix
235
+	 * @type string                   $DIR                              a base directory for class files in the
236
+	 *                                                                  namespace.
237
+	 *                                                                  }
238
+	 *                                                                  }
239
+	 * @type string                   $privacy_policies                 FQNSs (namespaces, each of which contains only
240
+	 *                                                                  privacy policy classes) or FQCNs (specific
241
+	 *                                                                  classnames of privacy policy classes)
242
+	 * @type string                   $personal_data_exporters          FQNSs (namespaces, each of which contains only
243
+	 *                                                                  privacy policy classes) or FQCNs (specific
244
+	 *                                                                  classnames of privacy policy classes)
245
+	 * @type string                   $personal_data_erasers            FQNSs (namespaces, each of which contains only
246
+	 *                                                                  privacy policy classes) or FQCNs (specific
247
+	 *                                                                  classnames of privacy policy classes)
248
+	 * @return void
249
+	 * @throws DomainException
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws ReflectionException
253
+	 * @throws InvalidDataTypeException
254
+	 * @throws InvalidInterfaceException
255
+	 */
256
+	public static function register($addon_name = '', $setup_args = array())
257
+	{
258
+		// required fields MUST be present, so let's make sure they are.
259
+		EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
260
+		// get class name for addon
261
+		$class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
262
+		// setup $_settings array from incoming values.
263
+		$addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
264
+		// setup PUE
265
+		EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
266
+		// does this addon work with this version of core or WordPress ?
267
+		if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268
+			return;
269
+		}
270
+		// register namespaces
271
+		EE_Register_Addon::_setup_namespaces($addon_settings);
272
+		// check if this is an activation request
273
+		if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
274
+			// dont bother setting up the rest of the addon atm
275
+			return;
276
+		}
277
+		// we need cars
278
+		EE_Register_Addon::_setup_autoloaders($addon_name);
279
+		// register new models and extensions
280
+		EE_Register_Addon::_register_models_and_extensions($addon_name);
281
+		// setup DMS
282
+		EE_Register_Addon::_register_data_migration_scripts($addon_name);
283
+		// if config_class is present let's register config.
284
+		EE_Register_Addon::_register_config($addon_name);
285
+		// register admin pages
286
+		EE_Register_Addon::_register_admin_pages($addon_name);
287
+		// add to list of modules to be registered
288
+		EE_Register_Addon::_register_modules($addon_name);
289
+		// add to list of shortcodes to be registered
290
+		EE_Register_Addon::_register_shortcodes($addon_name);
291
+		// add to list of widgets to be registered
292
+		EE_Register_Addon::_register_widgets($addon_name);
293
+		// register capability related stuff.
294
+		EE_Register_Addon::_register_capabilities($addon_name);
295
+		// any message type to register?
296
+		EE_Register_Addon::_register_message_types($addon_name);
297
+		// any custom post type/ custom capabilities or default terms to register
298
+		EE_Register_Addon::_register_custom_post_types($addon_name);
299
+		// and any payment methods
300
+		EE_Register_Addon::_register_payment_methods($addon_name);
301
+		// and privacy policy generators
302
+		EE_Register_Addon::registerPrivacyPolicies($addon_name);
303
+		// and privacy policy generators
304
+		EE_Register_Addon::registerPersonalDataExporters($addon_name);
305
+		// and privacy policy generators
306
+		EE_Register_Addon::registerPersonalDataErasers($addon_name);
307
+		// load and instantiate main addon class
308
+		$addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
309
+		// delay calling after_registration hook on each addon until after all add-ons have been registered.
310
+		add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
311
+	}
312 312
 
313 313
 
314
-    /**
315
-     * @param string $addon_name
316
-     * @param array  $setup_args
317
-     * @return void
318
-     * @throws EE_Error
319
-     */
320
-    private static function _verify_parameters($addon_name, array $setup_args)
321
-    {
322
-        // required fields MUST be present, so let's make sure they are.
323
-        if (empty($addon_name) || ! is_array($setup_args)) {
324
-            throw new EE_Error(
325
-                __(
326
-                    'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
327
-                    'event_espresso'
328
-                )
329
-            );
330
-        }
331
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332
-            throw new EE_Error(
333
-                sprintf(
334
-                    __(
335
-                        'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
336
-                        'event_espresso'
337
-                    ),
338
-                    implode(',', array_keys($setup_args))
339
-                )
340
-            );
341
-        }
342
-        // check that addon has not already been registered with that name
343
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
344
-            throw new EE_Error(
345
-                sprintf(
346
-                    __(
347
-                        'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
348
-                        'event_espresso'
349
-                    ),
350
-                    $addon_name
351
-                )
352
-            );
353
-        }
354
-    }
314
+	/**
315
+	 * @param string $addon_name
316
+	 * @param array  $setup_args
317
+	 * @return void
318
+	 * @throws EE_Error
319
+	 */
320
+	private static function _verify_parameters($addon_name, array $setup_args)
321
+	{
322
+		// required fields MUST be present, so let's make sure they are.
323
+		if (empty($addon_name) || ! is_array($setup_args)) {
324
+			throw new EE_Error(
325
+				__(
326
+					'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
327
+					'event_espresso'
328
+				)
329
+			);
330
+		}
331
+		if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332
+			throw new EE_Error(
333
+				sprintf(
334
+					__(
335
+						'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
336
+						'event_espresso'
337
+					),
338
+					implode(',', array_keys($setup_args))
339
+				)
340
+			);
341
+		}
342
+		// check that addon has not already been registered with that name
343
+		if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
344
+			throw new EE_Error(
345
+				sprintf(
346
+					__(
347
+						'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
348
+						'event_espresso'
349
+					),
350
+					$addon_name
351
+				)
352
+			);
353
+		}
354
+	}
355 355
 
356 356
 
357
-    /**
358
-     * @param string $addon_name
359
-     * @param array  $setup_args
360
-     * @return string
361
-     */
362
-    private static function _parse_class_name($addon_name, array $setup_args)
363
-    {
364
-        if (empty($setup_args['class_name'])) {
365
-            // generate one by first separating name with spaces
366
-            $class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
367
-            // capitalize, then replace spaces with underscores
368
-            $class_name = str_replace(' ', '_', ucwords($class_name));
369
-        } else {
370
-            $class_name = $setup_args['class_name'];
371
-        }
372
-        // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373
-        return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374
-            ? $class_name
375
-            : 'EE_' . $class_name;
376
-    }
357
+	/**
358
+	 * @param string $addon_name
359
+	 * @param array  $setup_args
360
+	 * @return string
361
+	 */
362
+	private static function _parse_class_name($addon_name, array $setup_args)
363
+	{
364
+		if (empty($setup_args['class_name'])) {
365
+			// generate one by first separating name with spaces
366
+			$class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
367
+			// capitalize, then replace spaces with underscores
368
+			$class_name = str_replace(' ', '_', ucwords($class_name));
369
+		} else {
370
+			$class_name = $setup_args['class_name'];
371
+		}
372
+		// check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373
+		return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374
+			? $class_name
375
+			: 'EE_' . $class_name;
376
+	}
377 377
 
378 378
 
379
-    /**
380
-     * @param string $class_name
381
-     * @param array  $setup_args
382
-     * @return array
383
-     */
384
-    private static function _get_addon_settings($class_name, array $setup_args)
385
-    {
386
-        // setup $_settings array from incoming values.
387
-        $addon_settings = array(
388
-            // generated from the addon name, changes something like "calendar" to "EE_Calendar"
389
-            'class_name'            => $class_name,
390
-            // the addon slug for use in URLs, etc
391
-            'plugin_slug'           => isset($setup_args['plugin_slug'])
392
-                ? (string) $setup_args['plugin_slug']
393
-                : '',
394
-            // page slug to be used when generating the "Settings" link on the WP plugin page
395
-            'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
396
-                ? (string) $setup_args['plugin_action_slug']
397
-                : '',
398
-            // the "software" version for the addon
399
-            'version'               => isset($setup_args['version'])
400
-                ? (string) $setup_args['version']
401
-                : '',
402
-            // the minimum version of EE Core that the addon will work with
403
-            'min_core_version'      => isset($setup_args['min_core_version'])
404
-                ? (string) $setup_args['min_core_version']
405
-                : '',
406
-            // the minimum version of WordPress that the addon will work with
407
-            'min_wp_version'        => isset($setup_args['min_wp_version'])
408
-                ? (string) $setup_args['min_wp_version']
409
-                : EE_MIN_WP_VER_REQUIRED,
410
-            // full server path to main file (file loaded directly by WP)
411
-            'main_file_path'        => isset($setup_args['main_file_path'])
412
-                ? (string) $setup_args['main_file_path']
413
-                : '',
414
-            // instance of \EventEspresso\core\domain\DomainInterface
415
-            'domain'                => isset($setup_args['domain']) && $setup_args['domain'] instanceof DomainInterface
416
-                ? $setup_args['domain']
417
-                : null,
418
-            // Fully Qualified Class Name for the addon's Domain class
419
-            'domain_fqcn'           => isset($setup_args['domain_fqcn'])
420
-                ? (string) $setup_args['domain_fqcn']
421
-                : '',
422
-            // path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
423
-            'admin_path'            => isset($setup_args['admin_path'])
424
-                ? (string) $setup_args['admin_path'] : '',
425
-            // a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
426
-            'admin_callback'        => isset($setup_args['admin_callback'])
427
-                ? (string) $setup_args['admin_callback']
428
-                : '',
429
-            // the section name for this addon's configuration settings section (defaults to "addons")
430
-            'config_section'        => isset($setup_args['config_section'])
431
-                ? (string) $setup_args['config_section']
432
-                : 'addons',
433
-            // the class name for this addon's configuration settings object
434
-            'config_class'          => isset($setup_args['config_class'])
435
-                ? (string) $setup_args['config_class'] : '',
436
-            // the name given to the config for this addons' configuration settings object (optional)
437
-            'config_name'           => isset($setup_args['config_name'])
438
-                ? (string) $setup_args['config_name'] : '',
439
-            // an array of "class names" => "full server paths" for any classes that might be invoked by the addon
440
-            'autoloader_paths'      => isset($setup_args['autoloader_paths'])
441
-                ? (array) $setup_args['autoloader_paths']
442
-                : array(),
443
-            // an array of  "full server paths" for any folders containing classes that might be invoked by the addon
444
-            'autoloader_folders'    => isset($setup_args['autoloader_folders'])
445
-                ? (array) $setup_args['autoloader_folders']
446
-                : array(),
447
-            // array of full server paths to any EE_DMS data migration scripts used by the addon.
448
-            // The key should be the EE_Addon class name that this set of data migration scripts belongs to.
449
-            // If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
450
-            'dms_paths'             => isset($setup_args['dms_paths'])
451
-                ? (array) $setup_args['dms_paths']
452
-                : array(),
453
-            // array of full server paths to any EED_Modules used by the addon
454
-            'module_paths'          => isset($setup_args['module_paths'])
455
-                ? (array) $setup_args['module_paths']
456
-                : array(),
457
-            // array of full server paths to any EES_Shortcodes used by the addon
458
-            'shortcode_paths'       => isset($setup_args['shortcode_paths'])
459
-                ? (array) $setup_args['shortcode_paths']
460
-                : array(),
461
-            'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
462
-                ? (array) $setup_args['shortcode_fqcns']
463
-                : array(),
464
-            // array of full server paths to any WP_Widgets used by the addon
465
-            'widget_paths'          => isset($setup_args['widget_paths'])
466
-                ? (array) $setup_args['widget_paths']
467
-                : array(),
468
-            // array of PUE options used by the addon
469
-            'pue_options'           => isset($setup_args['pue_options'])
470
-                ? (array) $setup_args['pue_options']
471
-                : array(),
472
-            'message_types'         => isset($setup_args['message_types'])
473
-                ? (array) $setup_args['message_types']
474
-                : array(),
475
-            'capabilities'          => isset($setup_args['capabilities'])
476
-                ? (array) $setup_args['capabilities']
477
-                : array(),
478
-            'capability_maps'       => isset($setup_args['capability_maps'])
479
-                ? (array) $setup_args['capability_maps']
480
-                : array(),
481
-            'model_paths'           => isset($setup_args['model_paths'])
482
-                ? (array) $setup_args['model_paths']
483
-                : array(),
484
-            'class_paths'           => isset($setup_args['class_paths'])
485
-                ? (array) $setup_args['class_paths']
486
-                : array(),
487
-            'model_extension_paths' => isset($setup_args['model_extension_paths'])
488
-                ? (array) $setup_args['model_extension_paths']
489
-                : array(),
490
-            'class_extension_paths' => isset($setup_args['class_extension_paths'])
491
-                ? (array) $setup_args['class_extension_paths']
492
-                : array(),
493
-            'custom_post_types'     => isset($setup_args['custom_post_types'])
494
-                ? (array) $setup_args['custom_post_types']
495
-                : array(),
496
-            'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
497
-                ? (array) $setup_args['custom_taxonomies']
498
-                : array(),
499
-            'payment_method_paths'  => isset($setup_args['payment_method_paths'])
500
-                ? (array) $setup_args['payment_method_paths']
501
-                : array(),
502
-            'default_terms'         => isset($setup_args['default_terms'])
503
-                ? (array) $setup_args['default_terms']
504
-                : array(),
505
-            // if not empty, inserts a new table row after this plugin's row on the WP Plugins page
506
-            // that can be used for adding upgrading/marketing info
507
-            'plugins_page_row'      => isset($setup_args['plugins_page_row'])
508
-                ? $setup_args['plugins_page_row']
509
-                : '',
510
-            'namespace'             => isset(
511
-                $setup_args['namespace']['FQNS'],
512
-                $setup_args['namespace']['DIR']
513
-            )
514
-                ? (array) $setup_args['namespace']
515
-                : array(),
516
-            'privacy_policies'      => isset($setup_args['privacy_policies'])
517
-                ? (array) $setup_args['privacy_policies']
518
-                : '',
519
-        );
520
-        // if plugin_action_slug is NOT set, but an admin page path IS set,
521
-        // then let's just use the plugin_slug since that will be used for linking to the admin page
522
-        $addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
523
-                                                && ! empty($addon_settings['admin_path'])
524
-            ? $addon_settings['plugin_slug']
525
-            : $addon_settings['plugin_action_slug'];
526
-        // full server path to main file (file loaded directly by WP)
527
-        $addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
528
-        return $addon_settings;
529
-    }
379
+	/**
380
+	 * @param string $class_name
381
+	 * @param array  $setup_args
382
+	 * @return array
383
+	 */
384
+	private static function _get_addon_settings($class_name, array $setup_args)
385
+	{
386
+		// setup $_settings array from incoming values.
387
+		$addon_settings = array(
388
+			// generated from the addon name, changes something like "calendar" to "EE_Calendar"
389
+			'class_name'            => $class_name,
390
+			// the addon slug for use in URLs, etc
391
+			'plugin_slug'           => isset($setup_args['plugin_slug'])
392
+				? (string) $setup_args['plugin_slug']
393
+				: '',
394
+			// page slug to be used when generating the "Settings" link on the WP plugin page
395
+			'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
396
+				? (string) $setup_args['plugin_action_slug']
397
+				: '',
398
+			// the "software" version for the addon
399
+			'version'               => isset($setup_args['version'])
400
+				? (string) $setup_args['version']
401
+				: '',
402
+			// the minimum version of EE Core that the addon will work with
403
+			'min_core_version'      => isset($setup_args['min_core_version'])
404
+				? (string) $setup_args['min_core_version']
405
+				: '',
406
+			// the minimum version of WordPress that the addon will work with
407
+			'min_wp_version'        => isset($setup_args['min_wp_version'])
408
+				? (string) $setup_args['min_wp_version']
409
+				: EE_MIN_WP_VER_REQUIRED,
410
+			// full server path to main file (file loaded directly by WP)
411
+			'main_file_path'        => isset($setup_args['main_file_path'])
412
+				? (string) $setup_args['main_file_path']
413
+				: '',
414
+			// instance of \EventEspresso\core\domain\DomainInterface
415
+			'domain'                => isset($setup_args['domain']) && $setup_args['domain'] instanceof DomainInterface
416
+				? $setup_args['domain']
417
+				: null,
418
+			// Fully Qualified Class Name for the addon's Domain class
419
+			'domain_fqcn'           => isset($setup_args['domain_fqcn'])
420
+				? (string) $setup_args['domain_fqcn']
421
+				: '',
422
+			// path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
423
+			'admin_path'            => isset($setup_args['admin_path'])
424
+				? (string) $setup_args['admin_path'] : '',
425
+			// a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
426
+			'admin_callback'        => isset($setup_args['admin_callback'])
427
+				? (string) $setup_args['admin_callback']
428
+				: '',
429
+			// the section name for this addon's configuration settings section (defaults to "addons")
430
+			'config_section'        => isset($setup_args['config_section'])
431
+				? (string) $setup_args['config_section']
432
+				: 'addons',
433
+			// the class name for this addon's configuration settings object
434
+			'config_class'          => isset($setup_args['config_class'])
435
+				? (string) $setup_args['config_class'] : '',
436
+			// the name given to the config for this addons' configuration settings object (optional)
437
+			'config_name'           => isset($setup_args['config_name'])
438
+				? (string) $setup_args['config_name'] : '',
439
+			// an array of "class names" => "full server paths" for any classes that might be invoked by the addon
440
+			'autoloader_paths'      => isset($setup_args['autoloader_paths'])
441
+				? (array) $setup_args['autoloader_paths']
442
+				: array(),
443
+			// an array of  "full server paths" for any folders containing classes that might be invoked by the addon
444
+			'autoloader_folders'    => isset($setup_args['autoloader_folders'])
445
+				? (array) $setup_args['autoloader_folders']
446
+				: array(),
447
+			// array of full server paths to any EE_DMS data migration scripts used by the addon.
448
+			// The key should be the EE_Addon class name that this set of data migration scripts belongs to.
449
+			// If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
450
+			'dms_paths'             => isset($setup_args['dms_paths'])
451
+				? (array) $setup_args['dms_paths']
452
+				: array(),
453
+			// array of full server paths to any EED_Modules used by the addon
454
+			'module_paths'          => isset($setup_args['module_paths'])
455
+				? (array) $setup_args['module_paths']
456
+				: array(),
457
+			// array of full server paths to any EES_Shortcodes used by the addon
458
+			'shortcode_paths'       => isset($setup_args['shortcode_paths'])
459
+				? (array) $setup_args['shortcode_paths']
460
+				: array(),
461
+			'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
462
+				? (array) $setup_args['shortcode_fqcns']
463
+				: array(),
464
+			// array of full server paths to any WP_Widgets used by the addon
465
+			'widget_paths'          => isset($setup_args['widget_paths'])
466
+				? (array) $setup_args['widget_paths']
467
+				: array(),
468
+			// array of PUE options used by the addon
469
+			'pue_options'           => isset($setup_args['pue_options'])
470
+				? (array) $setup_args['pue_options']
471
+				: array(),
472
+			'message_types'         => isset($setup_args['message_types'])
473
+				? (array) $setup_args['message_types']
474
+				: array(),
475
+			'capabilities'          => isset($setup_args['capabilities'])
476
+				? (array) $setup_args['capabilities']
477
+				: array(),
478
+			'capability_maps'       => isset($setup_args['capability_maps'])
479
+				? (array) $setup_args['capability_maps']
480
+				: array(),
481
+			'model_paths'           => isset($setup_args['model_paths'])
482
+				? (array) $setup_args['model_paths']
483
+				: array(),
484
+			'class_paths'           => isset($setup_args['class_paths'])
485
+				? (array) $setup_args['class_paths']
486
+				: array(),
487
+			'model_extension_paths' => isset($setup_args['model_extension_paths'])
488
+				? (array) $setup_args['model_extension_paths']
489
+				: array(),
490
+			'class_extension_paths' => isset($setup_args['class_extension_paths'])
491
+				? (array) $setup_args['class_extension_paths']
492
+				: array(),
493
+			'custom_post_types'     => isset($setup_args['custom_post_types'])
494
+				? (array) $setup_args['custom_post_types']
495
+				: array(),
496
+			'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
497
+				? (array) $setup_args['custom_taxonomies']
498
+				: array(),
499
+			'payment_method_paths'  => isset($setup_args['payment_method_paths'])
500
+				? (array) $setup_args['payment_method_paths']
501
+				: array(),
502
+			'default_terms'         => isset($setup_args['default_terms'])
503
+				? (array) $setup_args['default_terms']
504
+				: array(),
505
+			// if not empty, inserts a new table row after this plugin's row on the WP Plugins page
506
+			// that can be used for adding upgrading/marketing info
507
+			'plugins_page_row'      => isset($setup_args['plugins_page_row'])
508
+				? $setup_args['plugins_page_row']
509
+				: '',
510
+			'namespace'             => isset(
511
+				$setup_args['namespace']['FQNS'],
512
+				$setup_args['namespace']['DIR']
513
+			)
514
+				? (array) $setup_args['namespace']
515
+				: array(),
516
+			'privacy_policies'      => isset($setup_args['privacy_policies'])
517
+				? (array) $setup_args['privacy_policies']
518
+				: '',
519
+		);
520
+		// if plugin_action_slug is NOT set, but an admin page path IS set,
521
+		// then let's just use the plugin_slug since that will be used for linking to the admin page
522
+		$addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
523
+												&& ! empty($addon_settings['admin_path'])
524
+			? $addon_settings['plugin_slug']
525
+			: $addon_settings['plugin_action_slug'];
526
+		// full server path to main file (file loaded directly by WP)
527
+		$addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
528
+		return $addon_settings;
529
+	}
530 530
 
531 531
 
532
-    /**
533
-     * @param string $addon_name
534
-     * @param array  $addon_settings
535
-     * @return boolean
536
-     */
537
-    private static function _addon_is_compatible($addon_name, array $addon_settings)
538
-    {
539
-        global $wp_version;
540
-        $incompatibility_message = '';
541
-        // check whether this addon version is compatible with EE core
542
-        if (isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
543
-            && ! self::_meets_min_core_version_requirement(
544
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
545
-                $addon_settings['version']
546
-            )
547
-        ) {
548
-            $incompatibility_message = sprintf(
549
-                __(
550
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.',
551
-                    'event_espresso'
552
-                ),
553
-                $addon_name,
554
-                '<br />',
555
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
556
-                '<span style="font-weight: bold; color: #D54E21;">',
557
-                '</span><br />'
558
-            );
559
-        } elseif (! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
560
-        ) {
561
-            $incompatibility_message = sprintf(
562
-                __(
563
-                    '%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
564
-                    'event_espresso'
565
-                ),
566
-                $addon_name,
567
-                self::_effective_version($addon_settings['min_core_version']),
568
-                self::_effective_version(espresso_version()),
569
-                '<br />',
570
-                '<span style="font-weight: bold; color: #D54E21;">',
571
-                '</span><br />'
572
-            );
573
-        } elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
574
-            $incompatibility_message = sprintf(
575
-                __(
576
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
577
-                    'event_espresso'
578
-                ),
579
-                $addon_name,
580
-                $addon_settings['min_wp_version'],
581
-                '<br />',
582
-                '<span style="font-weight: bold; color: #D54E21;">',
583
-                '</span><br />'
584
-            );
585
-        }
586
-        if (! empty($incompatibility_message)) {
587
-            // remove 'activate' from the REQUEST
588
-            // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589
-            unset($_GET['activate'], $_REQUEST['activate']);
590
-            if (current_user_can('activate_plugins')) {
591
-                // show an error message indicating the plugin didn't activate properly
592
-                EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
593
-            }
594
-            // BAIL FROM THE ADDON REGISTRATION PROCESS
595
-            return false;
596
-        }
597
-        // addon IS compatible
598
-        return true;
599
-    }
532
+	/**
533
+	 * @param string $addon_name
534
+	 * @param array  $addon_settings
535
+	 * @return boolean
536
+	 */
537
+	private static function _addon_is_compatible($addon_name, array $addon_settings)
538
+	{
539
+		global $wp_version;
540
+		$incompatibility_message = '';
541
+		// check whether this addon version is compatible with EE core
542
+		if (isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
543
+			&& ! self::_meets_min_core_version_requirement(
544
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
545
+				$addon_settings['version']
546
+			)
547
+		) {
548
+			$incompatibility_message = sprintf(
549
+				__(
550
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.',
551
+					'event_espresso'
552
+				),
553
+				$addon_name,
554
+				'<br />',
555
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
556
+				'<span style="font-weight: bold; color: #D54E21;">',
557
+				'</span><br />'
558
+			);
559
+		} elseif (! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
560
+		) {
561
+			$incompatibility_message = sprintf(
562
+				__(
563
+					'%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
564
+					'event_espresso'
565
+				),
566
+				$addon_name,
567
+				self::_effective_version($addon_settings['min_core_version']),
568
+				self::_effective_version(espresso_version()),
569
+				'<br />',
570
+				'<span style="font-weight: bold; color: #D54E21;">',
571
+				'</span><br />'
572
+			);
573
+		} elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
574
+			$incompatibility_message = sprintf(
575
+				__(
576
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
577
+					'event_espresso'
578
+				),
579
+				$addon_name,
580
+				$addon_settings['min_wp_version'],
581
+				'<br />',
582
+				'<span style="font-weight: bold; color: #D54E21;">',
583
+				'</span><br />'
584
+			);
585
+		}
586
+		if (! empty($incompatibility_message)) {
587
+			// remove 'activate' from the REQUEST
588
+			// so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589
+			unset($_GET['activate'], $_REQUEST['activate']);
590
+			if (current_user_can('activate_plugins')) {
591
+				// show an error message indicating the plugin didn't activate properly
592
+				EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
593
+			}
594
+			// BAIL FROM THE ADDON REGISTRATION PROCESS
595
+			return false;
596
+		}
597
+		// addon IS compatible
598
+		return true;
599
+	}
600 600
 
601 601
 
602
-    /**
603
-     * if plugin update engine is being used for auto-updates,
604
-     * then let's set that up now before going any further so that ALL addons can be updated
605
-     * (not needed if PUE is not being used)
606
-     *
607
-     * @param string $addon_name
608
-     * @param string $class_name
609
-     * @param array  $setup_args
610
-     * @return void
611
-     */
612
-    private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
613
-    {
614
-        if (! empty($setup_args['pue_options'])) {
615
-            self::$_settings[ $addon_name ]['pue_options'] = array(
616
-                'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
617
-                    ? (string) $setup_args['pue_options']['pue_plugin_slug']
618
-                    : 'espresso_' . strtolower($class_name),
619
-                'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
620
-                    ? (string) $setup_args['pue_options']['plugin_basename']
621
-                    : plugin_basename($setup_args['main_file_path']),
622
-                'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
623
-                    ? (string) $setup_args['pue_options']['checkPeriod']
624
-                    : '24',
625
-                'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
626
-                    ? (string) $setup_args['pue_options']['use_wp_update']
627
-                    : false,
628
-            );
629
-            add_action(
630
-                'AHEE__EE_System__brew_espresso__after_pue_init',
631
-                array('EE_Register_Addon', 'load_pue_update')
632
-            );
633
-        }
634
-    }
602
+	/**
603
+	 * if plugin update engine is being used for auto-updates,
604
+	 * then let's set that up now before going any further so that ALL addons can be updated
605
+	 * (not needed if PUE is not being used)
606
+	 *
607
+	 * @param string $addon_name
608
+	 * @param string $class_name
609
+	 * @param array  $setup_args
610
+	 * @return void
611
+	 */
612
+	private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
613
+	{
614
+		if (! empty($setup_args['pue_options'])) {
615
+			self::$_settings[ $addon_name ]['pue_options'] = array(
616
+				'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
617
+					? (string) $setup_args['pue_options']['pue_plugin_slug']
618
+					: 'espresso_' . strtolower($class_name),
619
+				'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
620
+					? (string) $setup_args['pue_options']['plugin_basename']
621
+					: plugin_basename($setup_args['main_file_path']),
622
+				'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
623
+					? (string) $setup_args['pue_options']['checkPeriod']
624
+					: '24',
625
+				'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
626
+					? (string) $setup_args['pue_options']['use_wp_update']
627
+					: false,
628
+			);
629
+			add_action(
630
+				'AHEE__EE_System__brew_espresso__after_pue_init',
631
+				array('EE_Register_Addon', 'load_pue_update')
632
+			);
633
+		}
634
+	}
635 635
 
636 636
 
637
-    /**
638
-     * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
639
-     *
640
-     * @param array $addon_settings
641
-     * @return void
642
-     */
643
-    private static function _setup_namespaces(array $addon_settings)
644
-    {
645
-        //
646
-        if (isset(
647
-            $addon_settings['namespace']['FQNS'],
648
-            $addon_settings['namespace']['DIR']
649
-        )) {
650
-            EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
651
-                $addon_settings['namespace']['FQNS'],
652
-                $addon_settings['namespace']['DIR']
653
-            );
654
-        }
655
-    }
637
+	/**
638
+	 * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
639
+	 *
640
+	 * @param array $addon_settings
641
+	 * @return void
642
+	 */
643
+	private static function _setup_namespaces(array $addon_settings)
644
+	{
645
+		//
646
+		if (isset(
647
+			$addon_settings['namespace']['FQNS'],
648
+			$addon_settings['namespace']['DIR']
649
+		)) {
650
+			EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
651
+				$addon_settings['namespace']['FQNS'],
652
+				$addon_settings['namespace']['DIR']
653
+			);
654
+		}
655
+	}
656 656
 
657 657
 
658
-    /**
659
-     * @param string $addon_name
660
-     * @param array  $addon_settings
661
-     * @return bool
662
-     * @throws EE_Error
663
-     * @throws InvalidArgumentException
664
-     * @throws ReflectionException
665
-     * @throws InvalidDataTypeException
666
-     * @throws InvalidInterfaceException
667
-     */
668
-    private static function _addon_activation($addon_name, array $addon_settings)
669
-    {
670
-        // this is an activation request
671
-        if (did_action(
672
-            'activate_plugin'
673
-        )) {// to find if THIS is the addon that was activated, just check if we have already registered it or not
674
-            // (as the newly-activated addon wasn't around the first time addons were registered).
675
-            // Note: the presence of pue_options in the addon registration options will initialize the $_settings
676
-            // property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
677
-            if (! isset(self::$_settings[ $addon_name ])
678
-                || (isset(self::$_settings[ $addon_name ])
679
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
680
-                )
681
-            ) {
682
-                self::$_settings[ $addon_name ] = $addon_settings;
683
-                $addon = self::_load_and_init_addon_class($addon_name);
684
-                $addon->set_activation_indicator_option();
685
-                // dont bother setting up the rest of the addon.
686
-                // we know it was just activated and the request will end soon
687
-            }
688
-            return true;
689
-        }
690
-        // make sure this was called in the right place!
691
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
692
-            || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
693
-        ) {
694
-            EE_Error::doing_it_wrong(
695
-                __METHOD__,
696
-                sprintf(
697
-                    __(
698
-                        'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
699
-                        'event_espresso'
700
-                    ),
701
-                    $addon_name
702
-                ),
703
-                '4.3.0'
704
-            );
705
-        }
706
-        // make sure addon settings are set correctly without overwriting anything existing
707
-        if (isset(self::$_settings[ $addon_name ])) {
708
-            self::$_settings[ $addon_name ] += $addon_settings;
709
-        } else {
710
-            self::$_settings[ $addon_name ] = $addon_settings;
711
-        }
712
-        return false;
713
-    }
658
+	/**
659
+	 * @param string $addon_name
660
+	 * @param array  $addon_settings
661
+	 * @return bool
662
+	 * @throws EE_Error
663
+	 * @throws InvalidArgumentException
664
+	 * @throws ReflectionException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws InvalidInterfaceException
667
+	 */
668
+	private static function _addon_activation($addon_name, array $addon_settings)
669
+	{
670
+		// this is an activation request
671
+		if (did_action(
672
+			'activate_plugin'
673
+		)) {// to find if THIS is the addon that was activated, just check if we have already registered it or not
674
+			// (as the newly-activated addon wasn't around the first time addons were registered).
675
+			// Note: the presence of pue_options in the addon registration options will initialize the $_settings
676
+			// property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
677
+			if (! isset(self::$_settings[ $addon_name ])
678
+				|| (isset(self::$_settings[ $addon_name ])
679
+					&& ! isset(self::$_settings[ $addon_name ]['class_name'])
680
+				)
681
+			) {
682
+				self::$_settings[ $addon_name ] = $addon_settings;
683
+				$addon = self::_load_and_init_addon_class($addon_name);
684
+				$addon->set_activation_indicator_option();
685
+				// dont bother setting up the rest of the addon.
686
+				// we know it was just activated and the request will end soon
687
+			}
688
+			return true;
689
+		}
690
+		// make sure this was called in the right place!
691
+		if (! did_action('AHEE__EE_System__load_espresso_addons')
692
+			|| did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
693
+		) {
694
+			EE_Error::doing_it_wrong(
695
+				__METHOD__,
696
+				sprintf(
697
+					__(
698
+						'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
699
+						'event_espresso'
700
+					),
701
+					$addon_name
702
+				),
703
+				'4.3.0'
704
+			);
705
+		}
706
+		// make sure addon settings are set correctly without overwriting anything existing
707
+		if (isset(self::$_settings[ $addon_name ])) {
708
+			self::$_settings[ $addon_name ] += $addon_settings;
709
+		} else {
710
+			self::$_settings[ $addon_name ] = $addon_settings;
711
+		}
712
+		return false;
713
+	}
714 714
 
715 715
 
716
-    /**
717
-     * @param string $addon_name
718
-     * @return void
719
-     * @throws EE_Error
720
-     */
721
-    private static function _setup_autoloaders($addon_name)
722
-    {
723
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
724
-            // setup autoloader for single file
725
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
726
-        }
727
-        // setup autoloaders for folders
728
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
729
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
730
-                EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
731
-            }
732
-        }
733
-    }
716
+	/**
717
+	 * @param string $addon_name
718
+	 * @return void
719
+	 * @throws EE_Error
720
+	 */
721
+	private static function _setup_autoloaders($addon_name)
722
+	{
723
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
724
+			// setup autoloader for single file
725
+			EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
726
+		}
727
+		// setup autoloaders for folders
728
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
729
+			foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
730
+				EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
731
+			}
732
+		}
733
+	}
734 734
 
735 735
 
736
-    /**
737
-     * register new models and extensions
738
-     *
739
-     * @param string $addon_name
740
-     * @return void
741
-     * @throws EE_Error
742
-     */
743
-    private static function _register_models_and_extensions($addon_name)
744
-    {
745
-        // register new models
746
-        if (! empty(self::$_settings[ $addon_name ]['model_paths'])
747
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
748
-        ) {
749
-            EE_Register_Model::register(
750
-                $addon_name,
751
-                array(
752
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
753
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
754
-                )
755
-            );
756
-        }
757
-        // register model extensions
758
-        if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
759
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
760
-        ) {
761
-            EE_Register_Model_Extensions::register(
762
-                $addon_name,
763
-                array(
764
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
765
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
766
-                )
767
-            );
768
-        }
769
-    }
736
+	/**
737
+	 * register new models and extensions
738
+	 *
739
+	 * @param string $addon_name
740
+	 * @return void
741
+	 * @throws EE_Error
742
+	 */
743
+	private static function _register_models_and_extensions($addon_name)
744
+	{
745
+		// register new models
746
+		if (! empty(self::$_settings[ $addon_name ]['model_paths'])
747
+			|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
748
+		) {
749
+			EE_Register_Model::register(
750
+				$addon_name,
751
+				array(
752
+					'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
753
+					'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
754
+				)
755
+			);
756
+		}
757
+		// register model extensions
758
+		if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
759
+			|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
760
+		) {
761
+			EE_Register_Model_Extensions::register(
762
+				$addon_name,
763
+				array(
764
+					'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
765
+					'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
766
+				)
767
+			);
768
+		}
769
+	}
770 770
 
771 771
 
772
-    /**
773
-     * @param string $addon_name
774
-     * @return void
775
-     * @throws EE_Error
776
-     */
777
-    private static function _register_data_migration_scripts($addon_name)
778
-    {
779
-        // setup DMS
780
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
781
-            EE_Register_Data_Migration_Scripts::register(
782
-                $addon_name,
783
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
784
-            );
785
-        }
786
-    }
772
+	/**
773
+	 * @param string $addon_name
774
+	 * @return void
775
+	 * @throws EE_Error
776
+	 */
777
+	private static function _register_data_migration_scripts($addon_name)
778
+	{
779
+		// setup DMS
780
+		if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
781
+			EE_Register_Data_Migration_Scripts::register(
782
+				$addon_name,
783
+				array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
784
+			);
785
+		}
786
+	}
787 787
 
788 788
 
789
-    /**
790
-     * @param string $addon_name
791
-     * @return void
792
-     * @throws EE_Error
793
-     */
794
-    private static function _register_config($addon_name)
795
-    {
796
-        // if config_class is present let's register config.
797
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
798
-            EE_Register_Config::register(
799
-                self::$_settings[ $addon_name ]['config_class'],
800
-                array(
801
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
802
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
803
-                )
804
-            );
805
-        }
806
-    }
789
+	/**
790
+	 * @param string $addon_name
791
+	 * @return void
792
+	 * @throws EE_Error
793
+	 */
794
+	private static function _register_config($addon_name)
795
+	{
796
+		// if config_class is present let's register config.
797
+		if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
798
+			EE_Register_Config::register(
799
+				self::$_settings[ $addon_name ]['config_class'],
800
+				array(
801
+					'config_section' => self::$_settings[ $addon_name ]['config_section'],
802
+					'config_name'    => self::$_settings[ $addon_name ]['config_name'],
803
+				)
804
+			);
805
+		}
806
+	}
807 807
 
808 808
 
809
-    /**
810
-     * @param string $addon_name
811
-     * @return void
812
-     * @throws EE_Error
813
-     */
814
-    private static function _register_admin_pages($addon_name)
815
-    {
816
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
817
-            EE_Register_Admin_Page::register(
818
-                $addon_name,
819
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
820
-            );
821
-        }
822
-    }
809
+	/**
810
+	 * @param string $addon_name
811
+	 * @return void
812
+	 * @throws EE_Error
813
+	 */
814
+	private static function _register_admin_pages($addon_name)
815
+	{
816
+		if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
817
+			EE_Register_Admin_Page::register(
818
+				$addon_name,
819
+				array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
820
+			);
821
+		}
822
+	}
823 823
 
824 824
 
825
-    /**
826
-     * @param string $addon_name
827
-     * @return void
828
-     * @throws EE_Error
829
-     */
830
-    private static function _register_modules($addon_name)
831
-    {
832
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
833
-            EE_Register_Module::register(
834
-                $addon_name,
835
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
836
-            );
837
-        }
838
-    }
825
+	/**
826
+	 * @param string $addon_name
827
+	 * @return void
828
+	 * @throws EE_Error
829
+	 */
830
+	private static function _register_modules($addon_name)
831
+	{
832
+		if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
833
+			EE_Register_Module::register(
834
+				$addon_name,
835
+				array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
836
+			);
837
+		}
838
+	}
839 839
 
840 840
 
841
-    /**
842
-     * @param string $addon_name
843
-     * @return void
844
-     * @throws EE_Error
845
-     */
846
-    private static function _register_shortcodes($addon_name)
847
-    {
848
-        if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
849
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
850
-        ) {
851
-            EE_Register_Shortcode::register(
852
-                $addon_name,
853
-                array(
854
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
855
-                        ? self::$_settings[ $addon_name ]['shortcode_paths']
856
-                        : array(),
857
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
858
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns']
859
-                        : array(),
860
-                )
861
-            );
862
-        }
863
-    }
841
+	/**
842
+	 * @param string $addon_name
843
+	 * @return void
844
+	 * @throws EE_Error
845
+	 */
846
+	private static function _register_shortcodes($addon_name)
847
+	{
848
+		if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
849
+			|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
850
+		) {
851
+			EE_Register_Shortcode::register(
852
+				$addon_name,
853
+				array(
854
+					'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
855
+						? self::$_settings[ $addon_name ]['shortcode_paths']
856
+						: array(),
857
+					'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
858
+						? self::$_settings[ $addon_name ]['shortcode_fqcns']
859
+						: array(),
860
+				)
861
+			);
862
+		}
863
+	}
864 864
 
865 865
 
866
-    /**
867
-     * @param string $addon_name
868
-     * @return void
869
-     * @throws EE_Error
870
-     */
871
-    private static function _register_widgets($addon_name)
872
-    {
873
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
874
-            EE_Register_Widget::register(
875
-                $addon_name,
876
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
877
-            );
878
-        }
879
-    }
866
+	/**
867
+	 * @param string $addon_name
868
+	 * @return void
869
+	 * @throws EE_Error
870
+	 */
871
+	private static function _register_widgets($addon_name)
872
+	{
873
+		if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
874
+			EE_Register_Widget::register(
875
+				$addon_name,
876
+				array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
877
+			);
878
+		}
879
+	}
880 880
 
881 881
 
882
-    /**
883
-     * @param string $addon_name
884
-     * @return void
885
-     * @throws EE_Error
886
-     */
887
-    private static function _register_capabilities($addon_name)
888
-    {
889
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
890
-            EE_Register_Capabilities::register(
891
-                $addon_name,
892
-                array(
893
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
894
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
895
-                )
896
-            );
897
-        }
898
-    }
882
+	/**
883
+	 * @param string $addon_name
884
+	 * @return void
885
+	 * @throws EE_Error
886
+	 */
887
+	private static function _register_capabilities($addon_name)
888
+	{
889
+		if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
890
+			EE_Register_Capabilities::register(
891
+				$addon_name,
892
+				array(
893
+					'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
894
+					'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
895
+				)
896
+			);
897
+		}
898
+	}
899 899
 
900 900
 
901
-    /**
902
-     * @param string $addon_name
903
-     * @return void
904
-     * @throws EE_Error
905
-     */
906
-    private static function _register_message_types($addon_name)
907
-    {
908
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
909
-            add_action(
910
-                'EE_Brewing_Regular___messages_caf',
911
-                array('EE_Register_Addon', 'register_message_types')
912
-            );
913
-        }
914
-    }
901
+	/**
902
+	 * @param string $addon_name
903
+	 * @return void
904
+	 * @throws EE_Error
905
+	 */
906
+	private static function _register_message_types($addon_name)
907
+	{
908
+		if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
909
+			add_action(
910
+				'EE_Brewing_Regular___messages_caf',
911
+				array('EE_Register_Addon', 'register_message_types')
912
+			);
913
+		}
914
+	}
915 915
 
916 916
 
917
-    /**
918
-     * @param string $addon_name
919
-     * @return void
920
-     * @throws EE_Error
921
-     */
922
-    private static function _register_custom_post_types($addon_name)
923
-    {
924
-        if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])
925
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
926
-        ) {
927
-            EE_Register_CPT::register(
928
-                $addon_name,
929
-                array(
930
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
931
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
932
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
933
-                )
934
-            );
935
-        }
936
-    }
917
+	/**
918
+	 * @param string $addon_name
919
+	 * @return void
920
+	 * @throws EE_Error
921
+	 */
922
+	private static function _register_custom_post_types($addon_name)
923
+	{
924
+		if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])
925
+			|| ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
926
+		) {
927
+			EE_Register_CPT::register(
928
+				$addon_name,
929
+				array(
930
+					'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
931
+					'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
932
+					'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
933
+				)
934
+			);
935
+		}
936
+	}
937 937
 
938 938
 
939
-    /**
940
-     * @param string $addon_name
941
-     * @return void
942
-     * @throws InvalidArgumentException
943
-     * @throws InvalidInterfaceException
944
-     * @throws InvalidDataTypeException
945
-     * @throws DomainException
946
-     * @throws EE_Error
947
-     */
948
-    private static function _register_payment_methods($addon_name)
949
-    {
950
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
951
-            EE_Register_Payment_Method::register(
952
-                $addon_name,
953
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
954
-            );
955
-        }
956
-    }
939
+	/**
940
+	 * @param string $addon_name
941
+	 * @return void
942
+	 * @throws InvalidArgumentException
943
+	 * @throws InvalidInterfaceException
944
+	 * @throws InvalidDataTypeException
945
+	 * @throws DomainException
946
+	 * @throws EE_Error
947
+	 */
948
+	private static function _register_payment_methods($addon_name)
949
+	{
950
+		if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
951
+			EE_Register_Payment_Method::register(
952
+				$addon_name,
953
+				array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
954
+			);
955
+		}
956
+	}
957 957
 
958 958
 
959
-    /**
960
-     * @param string $addon_name
961
-     * @return void
962
-     * @throws InvalidArgumentException
963
-     * @throws InvalidInterfaceException
964
-     * @throws InvalidDataTypeException
965
-     * @throws DomainException
966
-     * @throws EE_Error
967
-     */
968
-    private static function registerPrivacyPolicies($addon_name)
969
-    {
970
-        if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
971
-            EE_Register_Privacy_Policy::register(
972
-                $addon_name,
973
-                self::$_settings[ $addon_name ]['privacy_policies']
974
-            );
975
-        }
976
-    }
959
+	/**
960
+	 * @param string $addon_name
961
+	 * @return void
962
+	 * @throws InvalidArgumentException
963
+	 * @throws InvalidInterfaceException
964
+	 * @throws InvalidDataTypeException
965
+	 * @throws DomainException
966
+	 * @throws EE_Error
967
+	 */
968
+	private static function registerPrivacyPolicies($addon_name)
969
+	{
970
+		if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
971
+			EE_Register_Privacy_Policy::register(
972
+				$addon_name,
973
+				self::$_settings[ $addon_name ]['privacy_policies']
974
+			);
975
+		}
976
+	}
977 977
 
978 978
 
979
-    /**
980
-     * @param string $addon_name
981
-     * @return void
982
-     */
983
-    private static function registerPersonalDataExporters($addon_name)
984
-    {
985
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
986
-            EE_Register_Personal_Data_Eraser::register(
987
-                $addon_name,
988
-                self::$_settings[ $addon_name ]['personal_data_exporters']
989
-            );
990
-        }
991
-    }
979
+	/**
980
+	 * @param string $addon_name
981
+	 * @return void
982
+	 */
983
+	private static function registerPersonalDataExporters($addon_name)
984
+	{
985
+		if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
986
+			EE_Register_Personal_Data_Eraser::register(
987
+				$addon_name,
988
+				self::$_settings[ $addon_name ]['personal_data_exporters']
989
+			);
990
+		}
991
+	}
992 992
 
993 993
 
994
-    /**
995
-     * @param string $addon_name
996
-     * @return void
997
-     */
998
-    private static function registerPersonalDataErasers($addon_name)
999
-    {
1000
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1001
-            EE_Register_Personal_Data_Eraser::register(
1002
-                $addon_name,
1003
-                self::$_settings[ $addon_name ]['personal_data_erasers']
1004
-            );
1005
-        }
1006
-    }
994
+	/**
995
+	 * @param string $addon_name
996
+	 * @return void
997
+	 */
998
+	private static function registerPersonalDataErasers($addon_name)
999
+	{
1000
+		if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1001
+			EE_Register_Personal_Data_Eraser::register(
1002
+				$addon_name,
1003
+				self::$_settings[ $addon_name ]['personal_data_erasers']
1004
+			);
1005
+		}
1006
+	}
1007 1007
 
1008 1008
 
1009
-    /**
1010
-     * Loads and instantiates the EE_Addon class and adds it onto the registry
1011
-     *
1012
-     * @param string $addon_name
1013
-     * @return EE_Addon
1014
-     * @throws InvalidArgumentException
1015
-     * @throws InvalidInterfaceException
1016
-     * @throws InvalidDataTypeException
1017
-     * @throws ReflectionException
1018
-     * @throws EE_Error
1019
-     */
1020
-    private static function _load_and_init_addon_class($addon_name)
1021
-    {
1022
-        $loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
1023
-        $addon = $loader->getShared(
1024
-            self::$_settings[ $addon_name ]['class_name'],
1025
-            array('EE_Registry::create(addon)' => true)
1026
-        );
1027
-        // setter inject dep map if required
1028
-        if ($addon instanceof RequiresDependencyMapInterface && $addon->dependencyMap() === null) {
1029
-            $addon->setDependencyMap($loader->getShared('EE_Dependency_Map'));
1030
-        }
1031
-        // setter inject domain if required
1032
-        if ($addon instanceof RequiresDomainInterface
1033
-            && $addon->domain() === null
1034
-        ) {
1035
-            // using supplied Domain object
1036
-            $domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1037
-                ? self::$_settings[ $addon_name ]['domain']
1038
-                : null;
1039
-            // or construct one using Domain FQCN
1040
-            if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1041
-                $domain = $loader->getShared(
1042
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
1043
-                    array(
1044
-                        new EventEspresso\core\domain\values\FilePath(
1045
-                            self::$_settings[ $addon_name ]['main_file_path']
1046
-                        ),
1047
-                        EventEspresso\core\domain\values\Version::fromString(
1048
-                            self::$_settings[ $addon_name ]['version']
1049
-                        ),
1050
-                    )
1051
-                );
1052
-            }
1053
-            if ($domain instanceof DomainInterface) {
1054
-                $addon->setDomain($domain);
1055
-            }
1056
-        }
1057
-        $addon->set_name($addon_name);
1058
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1059
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1060
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1061
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1062
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1063
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
1064
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1065
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1066
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1067
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1068
-        // unfortunately this can't be hooked in upon construction, because we don't have
1069
-        // the plugin mainfile's path upon construction.
1070
-        register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1071
-        // call any additional admin_callback functions during load_admin_controller hook
1072
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1073
-            add_action(
1074
-                'AHEE__EE_System__load_controllers__load_admin_controllers',
1075
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1076
-            );
1077
-        }
1078
-        return $addon;
1079
-    }
1009
+	/**
1010
+	 * Loads and instantiates the EE_Addon class and adds it onto the registry
1011
+	 *
1012
+	 * @param string $addon_name
1013
+	 * @return EE_Addon
1014
+	 * @throws InvalidArgumentException
1015
+	 * @throws InvalidInterfaceException
1016
+	 * @throws InvalidDataTypeException
1017
+	 * @throws ReflectionException
1018
+	 * @throws EE_Error
1019
+	 */
1020
+	private static function _load_and_init_addon_class($addon_name)
1021
+	{
1022
+		$loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
1023
+		$addon = $loader->getShared(
1024
+			self::$_settings[ $addon_name ]['class_name'],
1025
+			array('EE_Registry::create(addon)' => true)
1026
+		);
1027
+		// setter inject dep map if required
1028
+		if ($addon instanceof RequiresDependencyMapInterface && $addon->dependencyMap() === null) {
1029
+			$addon->setDependencyMap($loader->getShared('EE_Dependency_Map'));
1030
+		}
1031
+		// setter inject domain if required
1032
+		if ($addon instanceof RequiresDomainInterface
1033
+			&& $addon->domain() === null
1034
+		) {
1035
+			// using supplied Domain object
1036
+			$domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1037
+				? self::$_settings[ $addon_name ]['domain']
1038
+				: null;
1039
+			// or construct one using Domain FQCN
1040
+			if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1041
+				$domain = $loader->getShared(
1042
+					self::$_settings[ $addon_name ]['domain_fqcn'],
1043
+					array(
1044
+						new EventEspresso\core\domain\values\FilePath(
1045
+							self::$_settings[ $addon_name ]['main_file_path']
1046
+						),
1047
+						EventEspresso\core\domain\values\Version::fromString(
1048
+							self::$_settings[ $addon_name ]['version']
1049
+						),
1050
+					)
1051
+				);
1052
+			}
1053
+			if ($domain instanceof DomainInterface) {
1054
+				$addon->setDomain($domain);
1055
+			}
1056
+		}
1057
+		$addon->set_name($addon_name);
1058
+		$addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1059
+		$addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1060
+		$addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1061
+		$addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1062
+		$addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1063
+		$addon->set_version(self::$_settings[ $addon_name ]['version']);
1064
+		$addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1065
+		$addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1066
+		$addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1067
+		$addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1068
+		// unfortunately this can't be hooked in upon construction, because we don't have
1069
+		// the plugin mainfile's path upon construction.
1070
+		register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1071
+		// call any additional admin_callback functions during load_admin_controller hook
1072
+		if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1073
+			add_action(
1074
+				'AHEE__EE_System__load_controllers__load_admin_controllers',
1075
+				array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1076
+			);
1077
+		}
1078
+		return $addon;
1079
+	}
1080 1080
 
1081 1081
 
1082
-    /**
1083
-     *    load_pue_update - Update notifications
1084
-     *
1085
-     * @return void
1086
-     * @throws InvalidArgumentException
1087
-     * @throws InvalidDataTypeException
1088
-     * @throws InvalidInterfaceException
1089
-     */
1090
-    public static function load_pue_update()
1091
-    {
1092
-        // load PUE client
1093
-        require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1094
-        $license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1095
-        // cycle thru settings
1096
-        foreach (self::$_settings as $settings) {
1097
-            if (! empty($settings['pue_options'])) {
1098
-                // initiate the class and start the plugin update engine!
1099
-                new PluginUpdateEngineChecker(
1100
-                    // host file URL
1101
-                    $license_server,
1102
-                    // plugin slug(s)
1103
-                    array(
1104
-                        'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1105
-                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1106
-                    ),
1107
-                    // options
1108
-                    array(
1109
-                        'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1110
-                        'lang_domain'       => 'event_espresso',
1111
-                        'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1112
-                        'option_key'        => 'ee_site_license_key',
1113
-                        'options_page_slug' => 'event_espresso',
1114
-                        'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1115
-                        // if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1116
-                        'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1117
-                    )
1118
-                );
1119
-            }
1120
-        }
1121
-    }
1082
+	/**
1083
+	 *    load_pue_update - Update notifications
1084
+	 *
1085
+	 * @return void
1086
+	 * @throws InvalidArgumentException
1087
+	 * @throws InvalidDataTypeException
1088
+	 * @throws InvalidInterfaceException
1089
+	 */
1090
+	public static function load_pue_update()
1091
+	{
1092
+		// load PUE client
1093
+		require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1094
+		$license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1095
+		// cycle thru settings
1096
+		foreach (self::$_settings as $settings) {
1097
+			if (! empty($settings['pue_options'])) {
1098
+				// initiate the class and start the plugin update engine!
1099
+				new PluginUpdateEngineChecker(
1100
+					// host file URL
1101
+					$license_server,
1102
+					// plugin slug(s)
1103
+					array(
1104
+						'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1105
+						'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1106
+					),
1107
+					// options
1108
+					array(
1109
+						'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1110
+						'lang_domain'       => 'event_espresso',
1111
+						'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1112
+						'option_key'        => 'ee_site_license_key',
1113
+						'options_page_slug' => 'event_espresso',
1114
+						'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1115
+						// if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1116
+						'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1117
+					)
1118
+				);
1119
+			}
1120
+		}
1121
+	}
1122 1122
 
1123 1123
 
1124
-    /**
1125
-     * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1126
-     *
1127
-     * @since 4.4.0
1128
-     * @return void
1129
-     * @throws EE_Error
1130
-     */
1131
-    public static function register_message_types()
1132
-    {
1133
-        foreach (self::$_settings as $addon_name => $settings) {
1134
-            if (! empty($settings['message_types'])) {
1135
-                foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1136
-                    EE_Register_Message_Type::register($message_type, $message_type_settings);
1137
-                }
1138
-            }
1139
-        }
1140
-    }
1124
+	/**
1125
+	 * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1126
+	 *
1127
+	 * @since 4.4.0
1128
+	 * @return void
1129
+	 * @throws EE_Error
1130
+	 */
1131
+	public static function register_message_types()
1132
+	{
1133
+		foreach (self::$_settings as $addon_name => $settings) {
1134
+			if (! empty($settings['message_types'])) {
1135
+				foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1136
+					EE_Register_Message_Type::register($message_type, $message_type_settings);
1137
+				}
1138
+			}
1139
+		}
1140
+	}
1141 1141
 
1142 1142
 
1143
-    /**
1144
-     * This deregisters an addon that was previously registered with a specific addon_name.
1145
-     *
1146
-     * @since    4.3.0
1147
-     * @param string $addon_name the name for the addon that was previously registered
1148
-     * @throws DomainException
1149
-     * @throws EE_Error
1150
-     * @throws InvalidArgumentException
1151
-     * @throws InvalidDataTypeException
1152
-     * @throws InvalidInterfaceException
1153
-     */
1154
-    public static function deregister($addon_name = null)
1155
-    {
1156
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1157
-            try {
1158
-                do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1159
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1160
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1161
-                    // setup DMS
1162
-                    EE_Register_Data_Migration_Scripts::deregister($addon_name);
1163
-                }
1164
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1165
-                    // register admin page
1166
-                    EE_Register_Admin_Page::deregister($addon_name);
1167
-                }
1168
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1169
-                    // add to list of modules to be registered
1170
-                    EE_Register_Module::deregister($addon_name);
1171
-                }
1172
-                if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1173
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1174
-                ) {
1175
-                    // add to list of shortcodes to be registered
1176
-                    EE_Register_Shortcode::deregister($addon_name);
1177
-                }
1178
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1179
-                    // if config_class present let's register config.
1180
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1181
-                }
1182
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1183
-                    // add to list of widgets to be registered
1184
-                    EE_Register_Widget::deregister($addon_name);
1185
-                }
1186
-                if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1187
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1188
-                ) {
1189
-                    // add to list of shortcodes to be registered
1190
-                    EE_Register_Model::deregister($addon_name);
1191
-                }
1192
-                if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1193
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1194
-                ) {
1195
-                    // add to list of shortcodes to be registered
1196
-                    EE_Register_Model_Extensions::deregister($addon_name);
1197
-                }
1198
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1199
-                    foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1200
-                        EE_Register_Message_Type::deregister($message_type);
1201
-                    }
1202
-                }
1203
-                // deregister capabilities for addon
1204
-                if (! empty(self::$_settings[ $addon_name ]['capabilities'])
1205
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1206
-                ) {
1207
-                    EE_Register_Capabilities::deregister($addon_name);
1208
-                }
1209
-                // deregister custom_post_types for addon
1210
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1211
-                    EE_Register_CPT::deregister($addon_name);
1212
-                }
1213
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1214
-                    EE_Register_Payment_Method::deregister($addon_name);
1215
-                }
1216
-                $addon = EE_Registry::instance()->getAddon($class_name);
1217
-                if ($addon instanceof EE_Addon) {
1218
-                    remove_action(
1219
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1220
-                        array($addon, 'deactivation')
1221
-                    );
1222
-                    remove_action(
1223
-                        'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1224
-                        array($addon, 'initialize_db_if_no_migrations_required')
1225
-                    );
1226
-                    // remove `after_registration` call
1227
-                    remove_action(
1228
-                        'AHEE__EE_System__load_espresso_addons__complete',
1229
-                        array($addon, 'after_registration'),
1230
-                        999
1231
-                    );
1232
-                }
1233
-                EE_Registry::instance()->removeAddon($class_name);
1234
-            } catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1235
-                // the add-on was not yet registered in the registry,
1236
-                // so RegistryContainer::__get() throws this exception.
1237
-                // also no need to worry about this or log it,
1238
-                // it's ok to deregister an add-on before its registered in the registry
1239
-            } catch (Exception $e) {
1240
-                new ExceptionLogger($e);
1241
-            }
1242
-            unset(self::$_settings[ $addon_name ]);
1243
-            do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1244
-        }
1245
-    }
1143
+	/**
1144
+	 * This deregisters an addon that was previously registered with a specific addon_name.
1145
+	 *
1146
+	 * @since    4.3.0
1147
+	 * @param string $addon_name the name for the addon that was previously registered
1148
+	 * @throws DomainException
1149
+	 * @throws EE_Error
1150
+	 * @throws InvalidArgumentException
1151
+	 * @throws InvalidDataTypeException
1152
+	 * @throws InvalidInterfaceException
1153
+	 */
1154
+	public static function deregister($addon_name = null)
1155
+	{
1156
+		if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1157
+			try {
1158
+				do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1159
+				$class_name = self::$_settings[ $addon_name ]['class_name'];
1160
+				if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1161
+					// setup DMS
1162
+					EE_Register_Data_Migration_Scripts::deregister($addon_name);
1163
+				}
1164
+				if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1165
+					// register admin page
1166
+					EE_Register_Admin_Page::deregister($addon_name);
1167
+				}
1168
+				if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1169
+					// add to list of modules to be registered
1170
+					EE_Register_Module::deregister($addon_name);
1171
+				}
1172
+				if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1173
+					|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1174
+				) {
1175
+					// add to list of shortcodes to be registered
1176
+					EE_Register_Shortcode::deregister($addon_name);
1177
+				}
1178
+				if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1179
+					// if config_class present let's register config.
1180
+					EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1181
+				}
1182
+				if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1183
+					// add to list of widgets to be registered
1184
+					EE_Register_Widget::deregister($addon_name);
1185
+				}
1186
+				if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1187
+					|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
1188
+				) {
1189
+					// add to list of shortcodes to be registered
1190
+					EE_Register_Model::deregister($addon_name);
1191
+				}
1192
+				if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1193
+					|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1194
+				) {
1195
+					// add to list of shortcodes to be registered
1196
+					EE_Register_Model_Extensions::deregister($addon_name);
1197
+				}
1198
+				if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1199
+					foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1200
+						EE_Register_Message_Type::deregister($message_type);
1201
+					}
1202
+				}
1203
+				// deregister capabilities for addon
1204
+				if (! empty(self::$_settings[ $addon_name ]['capabilities'])
1205
+					|| ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1206
+				) {
1207
+					EE_Register_Capabilities::deregister($addon_name);
1208
+				}
1209
+				// deregister custom_post_types for addon
1210
+				if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1211
+					EE_Register_CPT::deregister($addon_name);
1212
+				}
1213
+				if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1214
+					EE_Register_Payment_Method::deregister($addon_name);
1215
+				}
1216
+				$addon = EE_Registry::instance()->getAddon($class_name);
1217
+				if ($addon instanceof EE_Addon) {
1218
+					remove_action(
1219
+						'deactivate_' . $addon->get_main_plugin_file_basename(),
1220
+						array($addon, 'deactivation')
1221
+					);
1222
+					remove_action(
1223
+						'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1224
+						array($addon, 'initialize_db_if_no_migrations_required')
1225
+					);
1226
+					// remove `after_registration` call
1227
+					remove_action(
1228
+						'AHEE__EE_System__load_espresso_addons__complete',
1229
+						array($addon, 'after_registration'),
1230
+						999
1231
+					);
1232
+				}
1233
+				EE_Registry::instance()->removeAddon($class_name);
1234
+			} catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1235
+				// the add-on was not yet registered in the registry,
1236
+				// so RegistryContainer::__get() throws this exception.
1237
+				// also no need to worry about this or log it,
1238
+				// it's ok to deregister an add-on before its registered in the registry
1239
+			} catch (Exception $e) {
1240
+				new ExceptionLogger($e);
1241
+			}
1242
+			unset(self::$_settings[ $addon_name ]);
1243
+			do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1244
+		}
1245
+	}
1246 1246
 }
Please login to merge, or discard this patch.
Spacing   +115 added lines, -115 removed lines patch added patch discarded remove patch
@@ -69,15 +69,15 @@  discard block
 block discarded – undo
69 69
         // offsets:    0 . 1 . 2 . 3 . 4
70 70
         $version_parts = explode('.', $min_core_version);
71 71
         // check they specified the micro version (after 2nd period)
72
-        if (! isset($version_parts[2])) {
72
+        if ( ! isset($version_parts[2])) {
73 73
             $version_parts[2] = '0';
74 74
         }
75 75
         // if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76 76
         // soon we can assume that's 'rc', but this current version is 'alpha'
77
-        if (! isset($version_parts[3])) {
77
+        if ( ! isset($version_parts[3])) {
78 78
             $version_parts[3] = 'dev';
79 79
         }
80
-        if (! isset($version_parts[4])) {
80
+        if ( ! isset($version_parts[4])) {
81 81
             $version_parts[4] = '000';
82 82
         }
83 83
         return implode('.', $version_parts);
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
         // setup PUE
265 265
         EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
266 266
         // does this addon work with this version of core or WordPress ?
267
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
267
+        if ( ! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268 268
             return;
269 269
         }
270 270
         // register namespaces
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
                 )
329 329
             );
330 330
         }
331
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
331
+        if ( ! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332 332
             throw new EE_Error(
333 333
                 sprintf(
334 334
                     __(
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
             );
341 341
         }
342 342
         // check that addon has not already been registered with that name
343
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
343
+        if (isset(self::$_settings[$addon_name]) && ! did_action('activate_plugin')) {
344 344
             throw new EE_Error(
345 345
                 sprintf(
346 346
                     __(
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
         // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373 373
         return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374 374
             ? $class_name
375
-            : 'EE_' . $class_name;
375
+            : 'EE_'.$class_name;
376 376
     }
377 377
 
378 378
 
@@ -539,9 +539,9 @@  discard block
 block discarded – undo
539 539
         global $wp_version;
540 540
         $incompatibility_message = '';
541 541
         // check whether this addon version is compatible with EE core
542
-        if (isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
542
+        if (isset(EE_Register_Addon::$_incompatible_addons[$addon_name])
543 543
             && ! self::_meets_min_core_version_requirement(
544
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
544
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
545 545
                 $addon_settings['version']
546 546
             )
547 547
         ) {
@@ -552,11 +552,11 @@  discard block
 block discarded – undo
552 552
                 ),
553 553
                 $addon_name,
554 554
                 '<br />',
555
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
555
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
556 556
                 '<span style="font-weight: bold; color: #D54E21;">',
557 557
                 '</span><br />'
558 558
             );
559
-        } elseif (! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
559
+        } elseif ( ! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
560 560
         ) {
561 561
             $incompatibility_message = sprintf(
562 562
                 __(
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
                 '</span><br />'
584 584
             );
585 585
         }
586
-        if (! empty($incompatibility_message)) {
586
+        if ( ! empty($incompatibility_message)) {
587 587
             // remove 'activate' from the REQUEST
588 588
             // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589 589
             unset($_GET['activate'], $_REQUEST['activate']);
@@ -611,11 +611,11 @@  discard block
 block discarded – undo
611 611
      */
612 612
     private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
613 613
     {
614
-        if (! empty($setup_args['pue_options'])) {
615
-            self::$_settings[ $addon_name ]['pue_options'] = array(
614
+        if ( ! empty($setup_args['pue_options'])) {
615
+            self::$_settings[$addon_name]['pue_options'] = array(
616 616
                 'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
617 617
                     ? (string) $setup_args['pue_options']['pue_plugin_slug']
618
-                    : 'espresso_' . strtolower($class_name),
618
+                    : 'espresso_'.strtolower($class_name),
619 619
                 'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
620 620
                     ? (string) $setup_args['pue_options']['plugin_basename']
621 621
                     : plugin_basename($setup_args['main_file_path']),
@@ -674,12 +674,12 @@  discard block
 block discarded – undo
674 674
             // (as the newly-activated addon wasn't around the first time addons were registered).
675 675
             // Note: the presence of pue_options in the addon registration options will initialize the $_settings
676 676
             // property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
677
-            if (! isset(self::$_settings[ $addon_name ])
678
-                || (isset(self::$_settings[ $addon_name ])
679
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
677
+            if ( ! isset(self::$_settings[$addon_name])
678
+                || (isset(self::$_settings[$addon_name])
679
+                    && ! isset(self::$_settings[$addon_name]['class_name'])
680 680
                 )
681 681
             ) {
682
-                self::$_settings[ $addon_name ] = $addon_settings;
682
+                self::$_settings[$addon_name] = $addon_settings;
683 683
                 $addon = self::_load_and_init_addon_class($addon_name);
684 684
                 $addon->set_activation_indicator_option();
685 685
                 // dont bother setting up the rest of the addon.
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
             return true;
689 689
         }
690 690
         // make sure this was called in the right place!
691
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
691
+        if ( ! did_action('AHEE__EE_System__load_espresso_addons')
692 692
             || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
693 693
         ) {
694 694
             EE_Error::doing_it_wrong(
@@ -704,10 +704,10 @@  discard block
 block discarded – undo
704 704
             );
705 705
         }
706 706
         // make sure addon settings are set correctly without overwriting anything existing
707
-        if (isset(self::$_settings[ $addon_name ])) {
708
-            self::$_settings[ $addon_name ] += $addon_settings;
707
+        if (isset(self::$_settings[$addon_name])) {
708
+            self::$_settings[$addon_name] += $addon_settings;
709 709
         } else {
710
-            self::$_settings[ $addon_name ] = $addon_settings;
710
+            self::$_settings[$addon_name] = $addon_settings;
711 711
         }
712 712
         return false;
713 713
     }
@@ -720,13 +720,13 @@  discard block
 block discarded – undo
720 720
      */
721 721
     private static function _setup_autoloaders($addon_name)
722 722
     {
723
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
723
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_paths'])) {
724 724
             // setup autoloader for single file
725
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
725
+            EEH_Autoloader::instance()->register_autoloader(self::$_settings[$addon_name]['autoloader_paths']);
726 726
         }
727 727
         // setup autoloaders for folders
728
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
729
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
728
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_folders'])) {
729
+            foreach ((array) self::$_settings[$addon_name]['autoloader_folders'] as $autoloader_folder) {
730 730
                 EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
731 731
             }
732 732
         }
@@ -743,26 +743,26 @@  discard block
 block discarded – undo
743 743
     private static function _register_models_and_extensions($addon_name)
744 744
     {
745 745
         // register new models
746
-        if (! empty(self::$_settings[ $addon_name ]['model_paths'])
747
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
746
+        if ( ! empty(self::$_settings[$addon_name]['model_paths'])
747
+            || ! empty(self::$_settings[$addon_name]['class_paths'])
748 748
         ) {
749 749
             EE_Register_Model::register(
750 750
                 $addon_name,
751 751
                 array(
752
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
753
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
752
+                    'model_paths' => self::$_settings[$addon_name]['model_paths'],
753
+                    'class_paths' => self::$_settings[$addon_name]['class_paths'],
754 754
                 )
755 755
             );
756 756
         }
757 757
         // register model extensions
758
-        if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
759
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
758
+        if ( ! empty(self::$_settings[$addon_name]['model_extension_paths'])
759
+            || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
760 760
         ) {
761 761
             EE_Register_Model_Extensions::register(
762 762
                 $addon_name,
763 763
                 array(
764
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
765
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
764
+                    'model_extension_paths' => self::$_settings[$addon_name]['model_extension_paths'],
765
+                    'class_extension_paths' => self::$_settings[$addon_name]['class_extension_paths'],
766 766
                 )
767 767
             );
768 768
         }
@@ -777,10 +777,10 @@  discard block
 block discarded – undo
777 777
     private static function _register_data_migration_scripts($addon_name)
778 778
     {
779 779
         // setup DMS
780
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
780
+        if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
781 781
             EE_Register_Data_Migration_Scripts::register(
782 782
                 $addon_name,
783
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
783
+                array('dms_paths' => self::$_settings[$addon_name]['dms_paths'])
784 784
             );
785 785
         }
786 786
     }
@@ -794,12 +794,12 @@  discard block
 block discarded – undo
794 794
     private static function _register_config($addon_name)
795 795
     {
796 796
         // if config_class is present let's register config.
797
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
797
+        if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
798 798
             EE_Register_Config::register(
799
-                self::$_settings[ $addon_name ]['config_class'],
799
+                self::$_settings[$addon_name]['config_class'],
800 800
                 array(
801
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
802
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
801
+                    'config_section' => self::$_settings[$addon_name]['config_section'],
802
+                    'config_name'    => self::$_settings[$addon_name]['config_name'],
803 803
                 )
804 804
             );
805 805
         }
@@ -813,10 +813,10 @@  discard block
 block discarded – undo
813 813
      */
814 814
     private static function _register_admin_pages($addon_name)
815 815
     {
816
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
816
+        if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
817 817
             EE_Register_Admin_Page::register(
818 818
                 $addon_name,
819
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
819
+                array('page_path' => self::$_settings[$addon_name]['admin_path'])
820 820
             );
821 821
         }
822 822
     }
@@ -829,10 +829,10 @@  discard block
 block discarded – undo
829 829
      */
830 830
     private static function _register_modules($addon_name)
831 831
     {
832
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
832
+        if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
833 833
             EE_Register_Module::register(
834 834
                 $addon_name,
835
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
835
+                array('module_paths' => self::$_settings[$addon_name]['module_paths'])
836 836
             );
837 837
         }
838 838
     }
@@ -845,17 +845,17 @@  discard block
 block discarded – undo
845 845
      */
846 846
     private static function _register_shortcodes($addon_name)
847 847
     {
848
-        if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
849
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
848
+        if ( ! empty(self::$_settings[$addon_name]['shortcode_paths'])
849
+            || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
850 850
         ) {
851 851
             EE_Register_Shortcode::register(
852 852
                 $addon_name,
853 853
                 array(
854
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
855
-                        ? self::$_settings[ $addon_name ]['shortcode_paths']
854
+                    'shortcode_paths' => isset(self::$_settings[$addon_name]['shortcode_paths'])
855
+                        ? self::$_settings[$addon_name]['shortcode_paths']
856 856
                         : array(),
857
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
858
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns']
857
+                    'shortcode_fqcns' => isset(self::$_settings[$addon_name]['shortcode_fqcns'])
858
+                        ? self::$_settings[$addon_name]['shortcode_fqcns']
859 859
                         : array(),
860 860
                 )
861 861
             );
@@ -870,10 +870,10 @@  discard block
 block discarded – undo
870 870
      */
871 871
     private static function _register_widgets($addon_name)
872 872
     {
873
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
873
+        if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
874 874
             EE_Register_Widget::register(
875 875
                 $addon_name,
876
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
876
+                array('widget_paths' => self::$_settings[$addon_name]['widget_paths'])
877 877
             );
878 878
         }
879 879
     }
@@ -886,12 +886,12 @@  discard block
 block discarded – undo
886 886
      */
887 887
     private static function _register_capabilities($addon_name)
888 888
     {
889
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
889
+        if ( ! empty(self::$_settings[$addon_name]['capabilities'])) {
890 890
             EE_Register_Capabilities::register(
891 891
                 $addon_name,
892 892
                 array(
893
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
894
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
893
+                    'capabilities'    => self::$_settings[$addon_name]['capabilities'],
894
+                    'capability_maps' => self::$_settings[$addon_name]['capability_maps'],
895 895
                 )
896 896
             );
897 897
         }
@@ -905,7 +905,7 @@  discard block
 block discarded – undo
905 905
      */
906 906
     private static function _register_message_types($addon_name)
907 907
     {
908
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
908
+        if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
909 909
             add_action(
910 910
                 'EE_Brewing_Regular___messages_caf',
911 911
                 array('EE_Register_Addon', 'register_message_types')
@@ -921,15 +921,15 @@  discard block
 block discarded – undo
921 921
      */
922 922
     private static function _register_custom_post_types($addon_name)
923 923
     {
924
-        if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])
925
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
924
+        if ( ! empty(self::$_settings[$addon_name]['custom_post_types'])
925
+            || ! empty(self::$_settings[$addon_name]['custom_taxonomies'])
926 926
         ) {
927 927
             EE_Register_CPT::register(
928 928
                 $addon_name,
929 929
                 array(
930
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
931
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
932
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
930
+                    'cpts'          => self::$_settings[$addon_name]['custom_post_types'],
931
+                    'cts'           => self::$_settings[$addon_name]['custom_taxonomies'],
932
+                    'default_terms' => self::$_settings[$addon_name]['default_terms'],
933 933
                 )
934 934
             );
935 935
         }
@@ -947,10 +947,10 @@  discard block
 block discarded – undo
947 947
      */
948 948
     private static function _register_payment_methods($addon_name)
949 949
     {
950
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
950
+        if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
951 951
             EE_Register_Payment_Method::register(
952 952
                 $addon_name,
953
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
953
+                array('payment_method_paths' => self::$_settings[$addon_name]['payment_method_paths'])
954 954
             );
955 955
         }
956 956
     }
@@ -967,10 +967,10 @@  discard block
 block discarded – undo
967 967
      */
968 968
     private static function registerPrivacyPolicies($addon_name)
969 969
     {
970
-        if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
970
+        if ( ! empty(self::$_settings[$addon_name]['privacy_policies'])) {
971 971
             EE_Register_Privacy_Policy::register(
972 972
                 $addon_name,
973
-                self::$_settings[ $addon_name ]['privacy_policies']
973
+                self::$_settings[$addon_name]['privacy_policies']
974 974
             );
975 975
         }
976 976
     }
@@ -982,10 +982,10 @@  discard block
 block discarded – undo
982 982
      */
983 983
     private static function registerPersonalDataExporters($addon_name)
984 984
     {
985
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
985
+        if ( ! empty(self::$_settings[$addon_name]['personal_data_exporters'])) {
986 986
             EE_Register_Personal_Data_Eraser::register(
987 987
                 $addon_name,
988
-                self::$_settings[ $addon_name ]['personal_data_exporters']
988
+                self::$_settings[$addon_name]['personal_data_exporters']
989 989
             );
990 990
         }
991 991
     }
@@ -997,10 +997,10 @@  discard block
 block discarded – undo
997 997
      */
998 998
     private static function registerPersonalDataErasers($addon_name)
999 999
     {
1000
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1000
+        if ( ! empty(self::$_settings[$addon_name]['personal_data_erasers'])) {
1001 1001
             EE_Register_Personal_Data_Eraser::register(
1002 1002
                 $addon_name,
1003
-                self::$_settings[ $addon_name ]['personal_data_erasers']
1003
+                self::$_settings[$addon_name]['personal_data_erasers']
1004 1004
             );
1005 1005
         }
1006 1006
     }
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
     {
1022 1022
         $loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
1023 1023
         $addon = $loader->getShared(
1024
-            self::$_settings[ $addon_name ]['class_name'],
1024
+            self::$_settings[$addon_name]['class_name'],
1025 1025
             array('EE_Registry::create(addon)' => true)
1026 1026
         );
1027 1027
         // setter inject dep map if required
@@ -1033,19 +1033,19 @@  discard block
 block discarded – undo
1033 1033
             && $addon->domain() === null
1034 1034
         ) {
1035 1035
             // using supplied Domain object
1036
-            $domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1037
-                ? self::$_settings[ $addon_name ]['domain']
1036
+            $domain = self::$_settings[$addon_name]['domain'] instanceof DomainInterface
1037
+                ? self::$_settings[$addon_name]['domain']
1038 1038
                 : null;
1039 1039
             // or construct one using Domain FQCN
1040
-            if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1040
+            if ($domain === null && self::$_settings[$addon_name]['domain_fqcn'] !== '') {
1041 1041
                 $domain = $loader->getShared(
1042
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
1042
+                    self::$_settings[$addon_name]['domain_fqcn'],
1043 1043
                     array(
1044 1044
                         new EventEspresso\core\domain\values\FilePath(
1045
-                            self::$_settings[ $addon_name ]['main_file_path']
1045
+                            self::$_settings[$addon_name]['main_file_path']
1046 1046
                         ),
1047 1047
                         EventEspresso\core\domain\values\Version::fromString(
1048
-                            self::$_settings[ $addon_name ]['version']
1048
+                            self::$_settings[$addon_name]['version']
1049 1049
                         ),
1050 1050
                     )
1051 1051
                 );
@@ -1055,24 +1055,24 @@  discard block
 block discarded – undo
1055 1055
             }
1056 1056
         }
1057 1057
         $addon->set_name($addon_name);
1058
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1059
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1060
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1061
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1062
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1063
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
1064
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1065
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1066
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1067
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1058
+        $addon->set_plugin_slug(self::$_settings[$addon_name]['plugin_slug']);
1059
+        $addon->set_plugin_basename(self::$_settings[$addon_name]['plugin_basename']);
1060
+        $addon->set_main_plugin_file(self::$_settings[$addon_name]['main_file_path']);
1061
+        $addon->set_plugin_action_slug(self::$_settings[$addon_name]['plugin_action_slug']);
1062
+        $addon->set_plugins_page_row(self::$_settings[$addon_name]['plugins_page_row']);
1063
+        $addon->set_version(self::$_settings[$addon_name]['version']);
1064
+        $addon->set_min_core_version(self::_effective_version(self::$_settings[$addon_name]['min_core_version']));
1065
+        $addon->set_config_section(self::$_settings[$addon_name]['config_section']);
1066
+        $addon->set_config_class(self::$_settings[$addon_name]['config_class']);
1067
+        $addon->set_config_name(self::$_settings[$addon_name]['config_name']);
1068 1068
         // unfortunately this can't be hooked in upon construction, because we don't have
1069 1069
         // the plugin mainfile's path upon construction.
1070 1070
         register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1071 1071
         // call any additional admin_callback functions during load_admin_controller hook
1072
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1072
+        if ( ! empty(self::$_settings[$addon_name]['admin_callback'])) {
1073 1073
             add_action(
1074 1074
                 'AHEE__EE_System__load_controllers__load_admin_controllers',
1075
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1075
+                array($addon, self::$_settings[$addon_name]['admin_callback'])
1076 1076
             );
1077 1077
         }
1078 1078
         return $addon;
@@ -1090,11 +1090,11 @@  discard block
 block discarded – undo
1090 1090
     public static function load_pue_update()
1091 1091
     {
1092 1092
         // load PUE client
1093
-        require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1093
+        require_once EE_THIRD_PARTY.'pue'.DS.'pue-client.php';
1094 1094
         $license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1095 1095
         // cycle thru settings
1096 1096
         foreach (self::$_settings as $settings) {
1097
-            if (! empty($settings['pue_options'])) {
1097
+            if ( ! empty($settings['pue_options'])) {
1098 1098
                 // initiate the class and start the plugin update engine!
1099 1099
                 new PluginUpdateEngineChecker(
1100 1100
                     // host file URL
@@ -1102,7 +1102,7 @@  discard block
 block discarded – undo
1102 1102
                     // plugin slug(s)
1103 1103
                     array(
1104 1104
                         'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1105
-                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1105
+                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'].'-pr'),
1106 1106
                     ),
1107 1107
                     // options
1108 1108
                     array(
@@ -1131,7 +1131,7 @@  discard block
 block discarded – undo
1131 1131
     public static function register_message_types()
1132 1132
     {
1133 1133
         foreach (self::$_settings as $addon_name => $settings) {
1134
-            if (! empty($settings['message_types'])) {
1134
+            if ( ! empty($settings['message_types'])) {
1135 1135
                 foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1136 1136
                     EE_Register_Message_Type::register($message_type, $message_type_settings);
1137 1137
                 }
@@ -1153,70 +1153,70 @@  discard block
 block discarded – undo
1153 1153
      */
1154 1154
     public static function deregister($addon_name = null)
1155 1155
     {
1156
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1156
+        if (isset(self::$_settings[$addon_name]['class_name'])) {
1157 1157
             try {
1158 1158
                 do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1159
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1160
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1159
+                $class_name = self::$_settings[$addon_name]['class_name'];
1160
+                if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
1161 1161
                     // setup DMS
1162 1162
                     EE_Register_Data_Migration_Scripts::deregister($addon_name);
1163 1163
                 }
1164
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1164
+                if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
1165 1165
                     // register admin page
1166 1166
                     EE_Register_Admin_Page::deregister($addon_name);
1167 1167
                 }
1168
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1168
+                if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
1169 1169
                     // add to list of modules to be registered
1170 1170
                     EE_Register_Module::deregister($addon_name);
1171 1171
                 }
1172
-                if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1173
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1172
+                if ( ! empty(self::$_settings[$addon_name]['shortcode_paths'])
1173
+                    || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
1174 1174
                 ) {
1175 1175
                     // add to list of shortcodes to be registered
1176 1176
                     EE_Register_Shortcode::deregister($addon_name);
1177 1177
                 }
1178
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1178
+                if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
1179 1179
                     // if config_class present let's register config.
1180
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1180
+                    EE_Register_Config::deregister(self::$_settings[$addon_name]['config_class']);
1181 1181
                 }
1182
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1182
+                if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
1183 1183
                     // add to list of widgets to be registered
1184 1184
                     EE_Register_Widget::deregister($addon_name);
1185 1185
                 }
1186
-                if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1187
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1186
+                if ( ! empty(self::$_settings[$addon_name]['model_paths'])
1187
+                    || ! empty(self::$_settings[$addon_name]['class_paths'])
1188 1188
                 ) {
1189 1189
                     // add to list of shortcodes to be registered
1190 1190
                     EE_Register_Model::deregister($addon_name);
1191 1191
                 }
1192
-                if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1193
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1192
+                if ( ! empty(self::$_settings[$addon_name]['model_extension_paths'])
1193
+                    || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
1194 1194
                 ) {
1195 1195
                     // add to list of shortcodes to be registered
1196 1196
                     EE_Register_Model_Extensions::deregister($addon_name);
1197 1197
                 }
1198
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1199
-                    foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1198
+                if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
1199
+                    foreach ((array) self::$_settings[$addon_name]['message_types'] as $message_type => $message_type_settings) {
1200 1200
                         EE_Register_Message_Type::deregister($message_type);
1201 1201
                     }
1202 1202
                 }
1203 1203
                 // deregister capabilities for addon
1204
-                if (! empty(self::$_settings[ $addon_name ]['capabilities'])
1205
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1204
+                if ( ! empty(self::$_settings[$addon_name]['capabilities'])
1205
+                    || ! empty(self::$_settings[$addon_name]['capability_maps'])
1206 1206
                 ) {
1207 1207
                     EE_Register_Capabilities::deregister($addon_name);
1208 1208
                 }
1209 1209
                 // deregister custom_post_types for addon
1210
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1210
+                if ( ! empty(self::$_settings[$addon_name]['custom_post_types'])) {
1211 1211
                     EE_Register_CPT::deregister($addon_name);
1212 1212
                 }
1213
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1213
+                if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
1214 1214
                     EE_Register_Payment_Method::deregister($addon_name);
1215 1215
                 }
1216 1216
                 $addon = EE_Registry::instance()->getAddon($class_name);
1217 1217
                 if ($addon instanceof EE_Addon) {
1218 1218
                     remove_action(
1219
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1219
+                        'deactivate_'.$addon->get_main_plugin_file_basename(),
1220 1220
                         array($addon, 'deactivation')
1221 1221
                     );
1222 1222
                     remove_action(
@@ -1239,7 +1239,7 @@  discard block
 block discarded – undo
1239 1239
             } catch (Exception $e) {
1240 1240
                 new ExceptionLogger($e);
1241 1241
             }
1242
-            unset(self::$_settings[ $addon_name ]);
1242
+            unset(self::$_settings[$addon_name]);
1243 1243
             do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1244 1244
         }
1245 1245
     }
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/model/Read.php 2 patches
Spacing   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -64,7 +64,7 @@  discard block
 block discarded – undo
64 64
         $controller = new Read();
65 65
         try {
66 66
             $controller->setRequestedVersion($version);
67
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
67
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
68 68
                 return $controller->sendResponse(
69 69
                     new WP_Error(
70 70
                         'endpoint_parsing_error',
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
         $controller = new Read();
103 103
         try {
104 104
             $controller->setRequestedVersion($version);
105
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
105
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
106 106
                 return array();
107 107
             }
108 108
             // get the model for this version
@@ -159,11 +159,11 @@  discard block
 block discarded – undo
159 159
      */
160 160
     protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
161 161
     {
162
-        if (isset($schema['properties'][ $field_name ]['default'])) {
163
-            if (is_array($schema['properties'][ $field_name ]['default'])) {
164
-                foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
162
+        if (isset($schema['properties'][$field_name]['default'])) {
163
+            if (is_array($schema['properties'][$field_name]['default'])) {
164
+                foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
165 165
                     if ($default_key === 'raw') {
166
-                        $schema['properties'][ $field_name ]['default'][ $default_key ] =
166
+                        $schema['properties'][$field_name]['default'][$default_key] =
167 167
                             ModelDataTranslator::prepareFieldValueForJson(
168 168
                                 $field,
169 169
                                 $default_value,
@@ -172,9 +172,9 @@  discard block
 block discarded – undo
172 172
                     }
173 173
                 }
174 174
             } else {
175
-                $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
175
+                $schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson(
176 176
                     $field,
177
-                    $schema['properties'][ $field_name ]['default'],
177
+                    $schema['properties'][$field_name]['default'],
178 178
                     $this->getModelVersionInfo()->requestedVersion()
179 179
                 );
180 180
             }
@@ -196,9 +196,9 @@  discard block
 block discarded – undo
196 196
     protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
197 197
     {
198 198
         if ($field instanceof EE_Datetime_Field) {
199
-            $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
199
+            $schema['properties'][$field_name.'_gmt'] = $field->getSchema();
200 200
             // modify the description
201
-            $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
201
+            $schema['properties'][$field_name.'_gmt']['description'] = sprintf(
202 202
                 esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
203 203
                 wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
204 204
             );
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
         $controller = new Read();
239 239
         try {
240 240
             $controller->setRequestedVersion($version);
241
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
241
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
242 242
                 return $controller->sendResponse(
243 243
                     new WP_Error(
244 244
                         'endpoint_parsing_error',
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
         $controller = new Read();
284 284
         try {
285 285
             $controller->setRequestedVersion($version);
286
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
286
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
287 287
                 return $controller->sendResponse(
288 288
                     new WP_Error(
289 289
                         'endpoint_parsing_error',
@@ -298,7 +298,7 @@  discard block
 block discarded – undo
298 298
                 );
299 299
             }
300 300
             $main_model = $controller->getModelVersionInfo()->loadModel($model_name);
301
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
301
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
302 302
                 return $controller->sendResponse(
303 303
                     new WP_Error(
304 304
                         'endpoint_parsing_error',
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
     public function getEntitiesFromModel($model, $request)
336 336
     {
337 337
         $query_params = $this->createModelQueryParams($model, $request->get_params());
338
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
338
+        if ( ! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
339 339
             $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
340 340
             return new WP_Error(
341 341
                 sprintf('rest_%s_cannot_list', $model_name_plural),
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
                 array('status' => 403)
348 348
             );
349 349
         }
350
-        if (! $request->get_header('no_rest_headers')) {
350
+        if ( ! $request->get_header('no_rest_headers')) {
351 351
             $this->setHeadersFromQueryParams($model, $query_params);
352 352
         }
353 353
         /** @type array $results */
@@ -382,7 +382,7 @@  discard block
 block discarded – undo
382 382
         $context = $this->validateContext($request->get_param('caps'));
383 383
         $model = $relation->get_this_model();
384 384
         $related_model = $relation->get_other_model();
385
-        if (! isset($primary_model_query_params[0])) {
385
+        if ( ! isset($primary_model_query_params[0])) {
386 386
             $primary_model_query_params[0] = array();
387 387
         }
388 388
         // check if they can access the 1st model object
@@ -399,7 +399,7 @@  discard block
 block discarded – undo
399 399
         $restricted_query_params['caps'] = $context;
400 400
         $this->setDebugInfo('main model query params', $restricted_query_params);
401 401
         $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
402
-        if (! (
402
+        if ( ! (
403 403
             Capabilities::currentUserHasPartialAccessTo($related_model, $context)
404 404
             && $model->exists($restricted_query_params)
405 405
         )
@@ -432,13 +432,13 @@  discard block
 block discarded – undo
432 432
         }
433 433
         $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
434 434
         foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
435
-            $query_params[0][ $relation->get_this_model()->get_this_model_name()
435
+            $query_params[0][$relation->get_this_model()->get_this_model_name()
436 436
                               . '.'
437
-                              . $where_condition_key ] = $where_condition_value;
437
+                              . $where_condition_key] = $where_condition_value;
438 438
         }
439 439
         $query_params['default_where_conditions'] = 'none';
440 440
         $query_params['caps'] = $context;
441
-        if (! $request->get_header('no_rest_headers')) {
441
+        if ( ! $request->get_header('no_rest_headers')) {
442 442
             $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
443 443
         }
444 444
         /** @type array $results */
@@ -489,7 +489,7 @@  discard block
 block discarded – undo
489 489
      */
490 490
     public function getEntitiesFromRelation($id, $relation, $request)
491 491
     {
492
-        if (! $relation->get_this_model()->has_primary_key_field()) {
492
+        if ( ! $relation->get_this_model()->has_primary_key_field()) {
493 493
             throw new EE_Error(
494 494
                 sprintf(
495 495
                     __(
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
             Capabilities::getMissingPermissionsString($model, $query_params['caps'])
532 532
         );
533 533
         // normally the limit to a 2-part array, where the 2nd item is the limit
534
-        if (! isset($query_params['limit'])) {
534
+        if ( ! isset($query_params['limit'])) {
535 535
             $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
536 536
         }
537 537
         if (is_array($query_params['limit'])) {
@@ -564,7 +564,7 @@  discard block
 block discarded – undo
564 564
      */
565 565
     public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
566 566
     {
567
-        if (! $rest_request instanceof WP_REST_Request) {
567
+        if ( ! $rest_request instanceof WP_REST_Request) {
568 568
             // ok so this was called in the old style, where the 3rd arg was
569 569
             // $include, and the 4th arg was $context
570 570
             // now setup the request just to avoid fatal errors, although we won't be able
@@ -645,8 +645,8 @@  discard block
 block discarded – undo
645 645
         if ($do_chevy_shuffle) {
646 646
             global $post;
647 647
             $old_post = $post;
648
-            $post = get_post($result[ $model->primary_key_name() ]);
649
-            if (! $post instanceof \WP_Post) {
648
+            $post = get_post($result[$model->primary_key_name()]);
649
+            if ( ! $post instanceof \WP_Post) {
650 650
                 // well that's weird, because $result is what we JUST fetched from the database
651 651
                 throw new RestException(
652 652
                     'error_fetching_post_from_database_results',
@@ -656,7 +656,7 @@  discard block
 block discarded – undo
656 656
                     )
657 657
                 );
658 658
             }
659
-            $model_object_classname = 'EE_' . $model->get_this_model_name();
659
+            $model_object_classname = 'EE_'.$model->get_this_model_name();
660 660
             $post->{$model_object_classname} = \EE_Registry::instance()->load_class(
661 661
                 $model_object_classname,
662 662
                 $result,
@@ -667,13 +667,13 @@  discard block
 block discarded – undo
667 667
         foreach ($result as $field_name => $field_value) {
668 668
             $field_obj = $model->field_settings_for($field_name);
669 669
             if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
670
-                unset($result[ $field_name ]);
670
+                unset($result[$field_name]);
671 671
             } elseif ($this->isSubclassOfOne(
672 672
                 $field_obj,
673 673
                 $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
674 674
             )
675 675
             ) {
676
-                $result[ $field_name ] = array(
676
+                $result[$field_name] = array(
677 677
                     'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
678 678
                     'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
679 679
                 );
@@ -682,7 +682,7 @@  discard block
 block discarded – undo
682 682
                 $this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
683 683
             )
684 684
             ) {
685
-                $result[ $field_name ] = array(
685
+                $result[$field_name] = array(
686 686
                     'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
687 687
                     'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
688 688
                 );
@@ -709,10 +709,10 @@  discard block
 block discarded – undo
709 709
                         $this->getModelVersionInfo()->requestedVersion()
710 710
                     );
711 711
                 }
712
-                $result[ $field_name . '_gmt' ] = $gmt_date;
713
-                $result[ $field_name ] = $local_date;
712
+                $result[$field_name.'_gmt'] = $gmt_date;
713
+                $result[$field_name] = $local_date;
714 714
             } else {
715
-                $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
715
+                $result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
716 716
             }
717 717
         }
718 718
         if ($do_chevy_shuffle) {
@@ -764,7 +764,7 @@  discard block
 block discarded – undo
764 764
     protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
765 765
     {
766 766
         if ($model instanceof EEM_CPT_Base) {
767
-            $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
767
+            $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
768 768
         }
769 769
         return $entity_array;
770 770
     }
@@ -789,7 +789,7 @@  discard block
 block discarded – undo
789 789
                     'href' => $this->getVersionedLinkTo(
790 790
                         EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
791 791
                         . '/'
792
-                        . $entity_array[ $model->primary_key_name() ]
792
+                        . $entity_array[$model->primary_key_name()]
793 793
                     ),
794 794
                 ),
795 795
             );
@@ -805,12 +805,12 @@  discard block
 block discarded – undo
805 805
         if ($model->has_primary_key_field()) {
806 806
             foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
807 807
                 $related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
808
-                $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = array(
808
+                $links[EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = array(
809 809
                     array(
810 810
                         'href'   => $this->getVersionedLinkTo(
811 811
                             EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
812 812
                             . '/'
813
-                            . $entity_array[ $model->primary_key_name() ]
813
+                            . $entity_array[$model->primary_key_name()]
814 814
                             . '/'
815 815
                             . $related_model_part
816 816
                         ),
@@ -839,13 +839,13 @@  discard block
 block discarded – undo
839 839
         $db_row = array()
840 840
     ) {
841 841
         // if $db_row not included, hope the entity array has what we need
842
-        if (! $db_row) {
842
+        if ( ! $db_row) {
843 843
             $db_row = $entity_array;
844 844
         }
845 845
         $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
846 846
         $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
847 847
         // if they passed in * or didn't specify any includes, return everything
848
-        if (! in_array('*', $includes_for_this_model)
848
+        if ( ! in_array('*', $includes_for_this_model)
849 849
             && ! empty($includes_for_this_model)
850 850
         ) {
851 851
             if ($model->has_primary_key_field()) {
@@ -891,7 +891,7 @@  discard block
 block discarded – undo
891 891
                     $relation_obj,
892 892
                     $pretend_related_request
893 893
                 );
894
-                $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results
894
+                $entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results
895 895
                                                                                              instanceof
896 896
                                                                                              WP_Error
897 897
                     ? null
@@ -1023,7 +1023,7 @@  discard block
 block discarded – undo
1023 1023
      */
1024 1024
     public function validateContext($context)
1025 1025
     {
1026
-        if (! $context) {
1026
+        if ( ! $context) {
1027 1027
             $context = EEM_Base::caps_read;
1028 1028
         }
1029 1029
         $valid_contexts = EEM_Base::valid_cap_contexts();
@@ -1048,7 +1048,7 @@  discard block
 block discarded – undo
1048 1048
             EEM_Base::default_where_conditions_minimum_all,
1049 1049
             EEM_Base::default_where_conditions_minimum_others,
1050 1050
         );
1051
-        if (! $default_query_params) {
1051
+        if ( ! $default_query_params) {
1052 1052
             $default_query_params = EEM_Base::default_where_conditions_all;
1053 1053
         }
1054 1054
         if (in_array(
@@ -1131,14 +1131,14 @@  discard block
 block discarded – undo
1131 1131
         }
1132 1132
         if (isset($query_parameters['limit'])) {
1133 1133
             // limit should be either a string like '23' or '23,43', or an array with two items in it
1134
-            if (! is_array($query_parameters['limit'])) {
1134
+            if ( ! is_array($query_parameters['limit'])) {
1135 1135
                 $limit_array = explode(',', (string) $query_parameters['limit']);
1136 1136
             } else {
1137 1137
                 $limit_array = $query_parameters['limit'];
1138 1138
             }
1139 1139
             $sanitized_limit = array();
1140 1140
             foreach ($limit_array as $key => $limit_part) {
1141
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1141
+                if ($this->debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1142 1142
                     throw new EE_Error(
1143 1143
                         sprintf(
1144 1144
                             __(
@@ -1184,9 +1184,9 @@  discard block
 block discarded – undo
1184 1184
         $model_ready_query_params = array();
1185 1185
         foreach ($query_params as $key => $value) {
1186 1186
             if (is_array($value)) {
1187
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1187
+                $model_ready_query_params[$key] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1188 1188
             } else {
1189
-                $model_ready_query_params[ $key ] = $value;
1189
+                $model_ready_query_params[$key] = $value;
1190 1190
             }
1191 1191
         }
1192 1192
         return $model_ready_query_params;
@@ -1204,9 +1204,9 @@  discard block
 block discarded – undo
1204 1204
         $model_ready_query_params = array();
1205 1205
         foreach ($query_params as $key => $value) {
1206 1206
             if (is_array($value)) {
1207
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1207
+                $model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1208 1208
             } else {
1209
-                $model_ready_query_params[ $key ] = $value;
1209
+                $model_ready_query_params[$key] = $value;
1210 1210
             }
1211 1211
         }
1212 1212
         return $model_ready_query_params;
@@ -1238,17 +1238,17 @@  discard block
 block discarded – undo
1238 1238
         foreach ($exploded_contents as $item) {
1239 1239
             $item = trim($item);
1240 1240
             // if no prefix was provided, so we look for items with no "." in them
1241
-            if (! $prefix) {
1241
+            if ( ! $prefix) {
1242 1242
                 // does this item have a period?
1243 1243
                 if (strpos($item, '.') === false) {
1244 1244
                     // if not, then its what we're looking for
1245 1245
                     $contents_with_prefix[] = $item;
1246 1246
                 }
1247
-            } elseif (strpos($item, $prefix . '.') === 0) {
1247
+            } elseif (strpos($item, $prefix.'.') === 0) {
1248 1248
                 // this item has the prefix and a period, grab it
1249 1249
                 $contents_with_prefix[] = substr(
1250 1250
                     $item,
1251
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1251
+                    strpos($item, $prefix.'.') + strlen($prefix.'.')
1252 1252
                 );
1253 1253
             } elseif ($item === $prefix) {
1254 1254
                 // this item is JUST the prefix
@@ -1287,9 +1287,9 @@  discard block
 block discarded – undo
1287 1287
         if ($model_name) {
1288 1288
             foreach ($includes as $field_to_include) {
1289 1289
                 $field_to_include = trim($field_to_include);
1290
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1290
+                if (strpos($field_to_include, $model_name.'.') === 0) {
1291 1291
                     // found the model name at the exact start
1292
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1292
+                    $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include);
1293 1293
                     $extracted_fields_to_include[] = $field_sans_model_name;
1294 1294
                 } elseif ($field_to_include == $model_name) {
1295 1295
                     $extracted_fields_to_include[] = '*';
@@ -1329,7 +1329,7 @@  discard block
 block discarded – undo
1329 1329
         $restricted_query_params['caps'] = $context;
1330 1330
         $this->setDebugInfo('model query params', $restricted_query_params);
1331 1331
         $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1332
-        if (! empty($model_rows)) {
1332
+        if ( ! empty($model_rows)) {
1333 1333
             return $this->createEntityFromWpdbResult(
1334 1334
                 $model,
1335 1335
                 array_shift($model_rows),
@@ -1339,10 +1339,10 @@  discard block
 block discarded – undo
1339 1339
             // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1340 1340
             $lowercase_model_name = strtolower($model->get_this_model_name());
1341 1341
             $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1342
-            if (! empty($model_rows_found_sans_restrictions)) {
1342
+            if ( ! empty($model_rows_found_sans_restrictions)) {
1343 1343
                 // you got shafted- it existed but we didn't want to tell you!
1344 1344
                 return new WP_Error(
1345
-                    'rest_user_cannot_' . $context,
1345
+                    'rest_user_cannot_'.$context,
1346 1346
                     sprintf(
1347 1347
                         __('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1348 1348
                         $context,
Please login to merge, or discard this patch.
Indentation   +1333 added lines, -1333 removed lines patch added patch discarded remove patch
@@ -35,1337 +35,1337 @@
 block discarded – undo
35 35
 {
36 36
 
37 37
 
38
-    /**
39
-     * @var CalculatedModelFields
40
-     */
41
-    protected $fields_calculator;
42
-
43
-
44
-    /**
45
-     * Read constructor.
46
-     */
47
-    public function __construct()
48
-    {
49
-        parent::__construct();
50
-        $this->fields_calculator = new CalculatedModelFields();
51
-    }
52
-
53
-
54
-    /**
55
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
56
-     *
57
-     * @param WP_REST_Request $request
58
-     * @param string          $version
59
-     * @param string          $model_name
60
-     * @return \WP_REST_Response|WP_Error
61
-     */
62
-    public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
63
-    {
64
-        $controller = new Read();
65
-        try {
66
-            $controller->setRequestedVersion($version);
67
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
68
-                return $controller->sendResponse(
69
-                    new WP_Error(
70
-                        'endpoint_parsing_error',
71
-                        sprintf(
72
-                            __(
73
-                                'There is no model for endpoint %s. Please contact event espresso support',
74
-                                'event_espresso'
75
-                            ),
76
-                            $model_name
77
-                        )
78
-                    )
79
-                );
80
-            }
81
-            return $controller->sendResponse(
82
-                $controller->getEntitiesFromModel(
83
-                    $controller->getModelVersionInfo()->loadModel($model_name),
84
-                    $request
85
-                )
86
-            );
87
-        } catch (Exception $e) {
88
-            return $controller->sendResponse($e);
89
-        }
90
-    }
91
-
92
-
93
-    /**
94
-     * Prepares and returns schema for any OPTIONS request.
95
-     *
96
-     * @param string $version    The API endpoint version being used.
97
-     * @param string $model_name Something like `Event` or `Registration`
98
-     * @return array
99
-     */
100
-    public static function handleSchemaRequest($version, $model_name)
101
-    {
102
-        $controller = new Read();
103
-        try {
104
-            $controller->setRequestedVersion($version);
105
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
106
-                return array();
107
-            }
108
-            // get the model for this version
109
-            $model = $controller->getModelVersionInfo()->loadModel($model_name);
110
-            $model_schema = new JsonModelSchema($model);
111
-            return $model_schema->getModelSchemaForRelations(
112
-                $controller->getModelVersionInfo()->relationSettings($model),
113
-                $controller->customizeSchemaForRestResponse(
114
-                    $model,
115
-                    $model_schema->getModelSchemaForFields(
116
-                        $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
117
-                        $model_schema->getInitialSchemaStructure()
118
-                    )
119
-                )
120
-            );
121
-        } catch (Exception $e) {
122
-            return array();
123
-        }
124
-    }
125
-
126
-
127
-    /**
128
-     * This loops through each field in the given schema for the model and does the following:
129
-     * - add any extra fields that are REST API specific and related to existing fields.
130
-     * - transform default values into the correct format for a REST API response.
131
-     *
132
-     * @param EEM_Base $model
133
-     * @param array    $schema
134
-     * @return array  The final schema.
135
-     */
136
-    protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
137
-    {
138
-        foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
139
-            $schema = $this->translateDefaultsForRestResponse(
140
-                $field_name,
141
-                $field,
142
-                $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
143
-            );
144
-        }
145
-        return $schema;
146
-    }
147
-
148
-
149
-    /**
150
-     * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
151
-     * response.
152
-     *
153
-     * @param                      $field_name
154
-     * @param EE_Model_Field_Base  $field
155
-     * @param array                $schema
156
-     * @return array
157
-     * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
158
-     * did, let's know about it ASAP, so let the exception bubble up)
159
-     */
160
-    protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
161
-    {
162
-        if (isset($schema['properties'][ $field_name ]['default'])) {
163
-            if (is_array($schema['properties'][ $field_name ]['default'])) {
164
-                foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
165
-                    if ($default_key === 'raw') {
166
-                        $schema['properties'][ $field_name ]['default'][ $default_key ] =
167
-                            ModelDataTranslator::prepareFieldValueForJson(
168
-                                $field,
169
-                                $default_value,
170
-                                $this->getModelVersionInfo()->requestedVersion()
171
-                            );
172
-                    }
173
-                }
174
-            } else {
175
-                $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
176
-                    $field,
177
-                    $schema['properties'][ $field_name ]['default'],
178
-                    $this->getModelVersionInfo()->requestedVersion()
179
-                );
180
-            }
181
-        }
182
-        return $schema;
183
-    }
184
-
185
-
186
-    /**
187
-     * Adds additional fields to the schema
188
-     * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
189
-     * needs to be added to the schema.
190
-     *
191
-     * @param                      $field_name
192
-     * @param EE_Model_Field_Base  $field
193
-     * @param array                $schema
194
-     * @return array
195
-     */
196
-    protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
197
-    {
198
-        if ($field instanceof EE_Datetime_Field) {
199
-            $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
200
-            // modify the description
201
-            $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
202
-                esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
203
-                wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
204
-            );
205
-        }
206
-        return $schema;
207
-    }
208
-
209
-
210
-    /**
211
-     * Used to figure out the route from the request when a `WP_REST_Request` object is not available
212
-     *
213
-     * @return string
214
-     */
215
-    protected function getRouteFromRequest()
216
-    {
217
-        if (isset($GLOBALS['wp'])
218
-            && $GLOBALS['wp'] instanceof \WP
219
-            && isset($GLOBALS['wp']->query_vars['rest_route'])
220
-        ) {
221
-            return $GLOBALS['wp']->query_vars['rest_route'];
222
-        } else {
223
-            return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
224
-        }
225
-    }
226
-
227
-
228
-    /**
229
-     * Gets a single entity related to the model indicated in the path and its id
230
-     *
231
-     * @param WP_REST_Request $request
232
-     * @param string          $version
233
-     * @param string          $model_name
234
-     * @return \WP_REST_Response|WP_Error
235
-     */
236
-    public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
237
-    {
238
-        $controller = new Read();
239
-        try {
240
-            $controller->setRequestedVersion($version);
241
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
242
-                return $controller->sendResponse(
243
-                    new WP_Error(
244
-                        'endpoint_parsing_error',
245
-                        sprintf(
246
-                            __(
247
-                                'There is no model for endpoint %s. Please contact event espresso support',
248
-                                'event_espresso'
249
-                            ),
250
-                            $model_name
251
-                        )
252
-                    )
253
-                );
254
-            }
255
-            return $controller->sendResponse(
256
-                $controller->getEntityFromModel(
257
-                    $controller->getModelVersionInfo()->loadModel($model_name),
258
-                    $request
259
-                )
260
-            );
261
-        } catch (Exception $e) {
262
-            return $controller->sendResponse($e);
263
-        }
264
-    }
265
-
266
-
267
-    /**
268
-     * Gets all the related entities (or if its a belongs-to relation just the one)
269
-     * to the item with the given id
270
-     *
271
-     * @param WP_REST_Request $request
272
-     * @param string          $version
273
-     * @param string          $model_name
274
-     * @param string          $related_model_name
275
-     * @return \WP_REST_Response|WP_Error
276
-     */
277
-    public static function handleRequestGetRelated(
278
-        WP_REST_Request $request,
279
-        $version,
280
-        $model_name,
281
-        $related_model_name
282
-    ) {
283
-        $controller = new Read();
284
-        try {
285
-            $controller->setRequestedVersion($version);
286
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
287
-                return $controller->sendResponse(
288
-                    new WP_Error(
289
-                        'endpoint_parsing_error',
290
-                        sprintf(
291
-                            __(
292
-                                'There is no model for endpoint %s. Please contact event espresso support',
293
-                                'event_espresso'
294
-                            ),
295
-                            $model_name
296
-                        )
297
-                    )
298
-                );
299
-            }
300
-            $main_model = $controller->getModelVersionInfo()->loadModel($model_name);
301
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
302
-                return $controller->sendResponse(
303
-                    new WP_Error(
304
-                        'endpoint_parsing_error',
305
-                        sprintf(
306
-                            __(
307
-                                'There is no model for endpoint %s. Please contact event espresso support',
308
-                                'event_espresso'
309
-                            ),
310
-                            $related_model_name
311
-                        )
312
-                    )
313
-                );
314
-            }
315
-            return $controller->sendResponse(
316
-                $controller->getEntitiesFromRelation(
317
-                    $request->get_param('id'),
318
-                    $main_model->related_settings_for($related_model_name),
319
-                    $request
320
-                )
321
-            );
322
-        } catch (Exception $e) {
323
-            return $controller->sendResponse($e);
324
-        }
325
-    }
326
-
327
-
328
-    /**
329
-     * Gets a collection for the given model and filters
330
-     *
331
-     * @param EEM_Base        $model
332
-     * @param WP_REST_Request $request
333
-     * @return array|WP_Error
334
-     */
335
-    public function getEntitiesFromModel($model, $request)
336
-    {
337
-        $query_params = $this->createModelQueryParams($model, $request->get_params());
338
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
339
-            $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
340
-            return new WP_Error(
341
-                sprintf('rest_%s_cannot_list', $model_name_plural),
342
-                sprintf(
343
-                    __('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
344
-                    $model_name_plural,
345
-                    Capabilities::getMissingPermissionsString($model, $query_params['caps'])
346
-                ),
347
-                array('status' => 403)
348
-            );
349
-        }
350
-        if (! $request->get_header('no_rest_headers')) {
351
-            $this->setHeadersFromQueryParams($model, $query_params);
352
-        }
353
-        /** @type array $results */
354
-        $results = $model->get_all_wpdb_results($query_params);
355
-        $nice_results = array();
356
-        foreach ($results as $result) {
357
-            $nice_results[] = $this->createEntityFromWpdbResult(
358
-                $model,
359
-                $result,
360
-                $request
361
-            );
362
-        }
363
-        return $nice_results;
364
-    }
365
-
366
-
367
-    /**
368
-     * Gets the collection for given relation object
369
-     * The same as Read::get_entities_from_model(), except if the relation
370
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
371
-     * the join-model-object into the results
372
-     *
373
-     * @param array                   $primary_model_query_params query params for finding the item from which
374
-     *                                                            relations will be based
375
-     * @param \EE_Model_Relation_Base $relation
376
-     * @param WP_REST_Request         $request
377
-     * @return WP_Error|array
378
-     * @throws RestException
379
-     */
380
-    protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
381
-    {
382
-        $context = $this->validateContext($request->get_param('caps'));
383
-        $model = $relation->get_this_model();
384
-        $related_model = $relation->get_other_model();
385
-        if (! isset($primary_model_query_params[0])) {
386
-            $primary_model_query_params[0] = array();
387
-        }
388
-        // check if they can access the 1st model object
389
-        $primary_model_query_params = array(
390
-            0       => $primary_model_query_params[0],
391
-            'limit' => 1,
392
-        );
393
-        if ($model instanceof \EEM_Soft_Delete_Base) {
394
-            $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
395
-                $primary_model_query_params
396
-            );
397
-        }
398
-        $restricted_query_params = $primary_model_query_params;
399
-        $restricted_query_params['caps'] = $context;
400
-        $this->setDebugInfo('main model query params', $restricted_query_params);
401
-        $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
402
-        if (! (
403
-            Capabilities::currentUserHasPartialAccessTo($related_model, $context)
404
-            && $model->exists($restricted_query_params)
405
-        )
406
-        ) {
407
-            if ($relation instanceof EE_Belongs_To_Relation) {
408
-                $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
409
-            } else {
410
-                $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
411
-                    $related_model->get_this_model_name()
412
-                );
413
-            }
414
-            return new WP_Error(
415
-                sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
416
-                sprintf(
417
-                    __(
418
-                        'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
419
-                        'event_espresso'
420
-                    ),
421
-                    $related_model_name_maybe_plural,
422
-                    $relation->get_this_model()->get_this_model_name(),
423
-                    implode(
424
-                        ',',
425
-                        array_keys(
426
-                            Capabilities::getMissingPermissions($related_model, $context)
427
-                        )
428
-                    )
429
-                ),
430
-                array('status' => 403)
431
-            );
432
-        }
433
-        $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
434
-        foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
435
-            $query_params[0][ $relation->get_this_model()->get_this_model_name()
436
-                              . '.'
437
-                              . $where_condition_key ] = $where_condition_value;
438
-        }
439
-        $query_params['default_where_conditions'] = 'none';
440
-        $query_params['caps'] = $context;
441
-        if (! $request->get_header('no_rest_headers')) {
442
-            $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
443
-        }
444
-        /** @type array $results */
445
-        $results = $relation->get_other_model()->get_all_wpdb_results($query_params);
446
-        $nice_results = array();
447
-        foreach ($results as $result) {
448
-            $nice_result = $this->createEntityFromWpdbResult(
449
-                $relation->get_other_model(),
450
-                $result,
451
-                $request
452
-            );
453
-            if ($relation instanceof \EE_HABTM_Relation) {
454
-                // put the unusual stuff (properties from the HABTM relation) first, and make sure
455
-                // if there are conflicts we prefer the properties from the main model
456
-                $join_model_result = $this->createEntityFromWpdbResult(
457
-                    $relation->get_join_model(),
458
-                    $result,
459
-                    $request
460
-                );
461
-                $joined_result = array_merge($nice_result, $join_model_result);
462
-                // but keep the meta stuff from the main model
463
-                if (isset($nice_result['meta'])) {
464
-                    $joined_result['meta'] = $nice_result['meta'];
465
-                }
466
-                $nice_result = $joined_result;
467
-            }
468
-            $nice_results[] = $nice_result;
469
-        }
470
-        if ($relation instanceof EE_Belongs_To_Relation) {
471
-            return array_shift($nice_results);
472
-        } else {
473
-            return $nice_results;
474
-        }
475
-    }
476
-
477
-
478
-    /**
479
-     * Gets the collection for given relation object
480
-     * The same as Read::get_entities_from_model(), except if the relation
481
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
482
-     * the join-model-object into the results
483
-     *
484
-     * @param string                  $id the ID of the thing we are fetching related stuff from
485
-     * @param \EE_Model_Relation_Base $relation
486
-     * @param WP_REST_Request         $request
487
-     * @return array|WP_Error
488
-     * @throws EE_Error
489
-     */
490
-    public function getEntitiesFromRelation($id, $relation, $request)
491
-    {
492
-        if (! $relation->get_this_model()->has_primary_key_field()) {
493
-            throw new EE_Error(
494
-                sprintf(
495
-                    __(
496
-                    // @codingStandardsIgnoreStart
497
-                        'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
498
-                        // @codingStandardsIgnoreEnd
499
-                        'event_espresso'
500
-                    ),
501
-                    $relation->get_this_model()->get_this_model_name()
502
-                )
503
-            );
504
-        }
505
-        return $this->getEntitiesFromRelationUsingModelQueryParams(
506
-            array(
507
-                array(
508
-                    $relation->get_this_model()->primary_key_name() => $id,
509
-                ),
510
-            ),
511
-            $relation,
512
-            $request
513
-        );
514
-    }
515
-
516
-
517
-    /**
518
-     * Sets the headers that are based on the model and query params,
519
-     * like the total records. This should only be called on the original request
520
-     * from the client, not on subsequent internal
521
-     *
522
-     * @param EEM_Base $model
523
-     * @param array    $query_params
524
-     * @return void
525
-     */
526
-    protected function setHeadersFromQueryParams($model, $query_params)
527
-    {
528
-        $this->setDebugInfo('model query params', $query_params);
529
-        $this->setDebugInfo(
530
-            'missing caps',
531
-            Capabilities::getMissingPermissionsString($model, $query_params['caps'])
532
-        );
533
-        // normally the limit to a 2-part array, where the 2nd item is the limit
534
-        if (! isset($query_params['limit'])) {
535
-            $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
536
-        }
537
-        if (is_array($query_params['limit'])) {
538
-            $limit_parts = $query_params['limit'];
539
-        } else {
540
-            $limit_parts = explode(',', $query_params['limit']);
541
-            if (count($limit_parts) == 1) {
542
-                $limit_parts = array(0, $limit_parts[0]);
543
-            }
544
-        }
545
-        // remove the group by and having parts of the query, as those will
546
-        // make the sql query return an array of values, instead of just a single value
547
-        unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
548
-        $count = $model->count($query_params, null, true);
549
-        $pages = $count / $limit_parts[1];
550
-        $this->setResponseHeader('Total', $count, false);
551
-        $this->setResponseHeader('PageSize', $limit_parts[1], false);
552
-        $this->setResponseHeader('TotalPages', ceil($pages), false);
553
-    }
554
-
555
-
556
-    /**
557
-     * Changes database results into REST API entities
558
-     *
559
-     * @param EEM_Base        $model
560
-     * @param array           $db_row     like results from $wpdb->get_results()
561
-     * @param WP_REST_Request $rest_request
562
-     * @param string          $deprecated no longer used
563
-     * @return array ready for being converted into json for sending to client
564
-     */
565
-    public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
566
-    {
567
-        if (! $rest_request instanceof WP_REST_Request) {
568
-            // ok so this was called in the old style, where the 3rd arg was
569
-            // $include, and the 4th arg was $context
570
-            // now setup the request just to avoid fatal errors, although we won't be able
571
-            // to truly make use of it because it's kinda devoid of info
572
-            $rest_request = new WP_REST_Request();
573
-            $rest_request->set_param('include', $rest_request);
574
-            $rest_request->set_param('caps', $deprecated);
575
-        }
576
-        if ($rest_request->get_param('caps') == null) {
577
-            $rest_request->set_param('caps', EEM_Base::caps_read);
578
-        }
579
-        $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row);
580
-        $entity_array = $this->addExtraFields($model, $db_row, $entity_array);
581
-        $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array);
582
-        $entity_array['_calculated_fields'] = $this->getEntityCalculations($model, $db_row, $rest_request);
583
-        $entity_array = apply_filters(
584
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
585
-            $entity_array,
586
-            $model,
587
-            $rest_request->get_param('caps'),
588
-            $rest_request,
589
-            $this
590
-        );
591
-        $entity_array = $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row);
592
-        $entity_array = apply_filters(
593
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
594
-            $entity_array,
595
-            $model,
596
-            $rest_request->get_param('caps'),
597
-            $rest_request,
598
-            $this
599
-        );
600
-        $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
601
-            $entity_array,
602
-            $model,
603
-            $rest_request->get_param('caps'),
604
-            $this->getModelVersionInfo(),
605
-            $model->get_index_primary_key_string(
606
-                $model->deduce_fields_n_values_from_cols_n_values($db_row)
607
-            )
608
-        );
609
-        $this->setDebugInfo(
610
-            'inaccessible fields',
611
-            array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
612
-        );
613
-        return apply_filters(
614
-            'FHEE__Read__create_entity_from_wpdb_results__entity_return',
615
-            $result_without_inaccessible_fields,
616
-            $model,
617
-            $rest_request->get_param('caps')
618
-        );
619
-    }
620
-
621
-
622
-    /**
623
-     * Creates a REST entity array (JSON object we're going to return in the response, but
624
-     * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
625
-     * from $wpdb->get_row( $sql, ARRAY_A)
626
-     *
627
-     * @param EEM_Base $model
628
-     * @param array    $db_row
629
-     * @return array entity mostly ready for converting to JSON and sending in the response
630
-     */
631
-    protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
632
-    {
633
-        $result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
634
-        $result = array_intersect_key(
635
-            $result,
636
-            $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
637
-        );
638
-        // if this is a CPT, we need to set the global $post to it,
639
-        // otherwise shortcodes etc won't work properly while rendering it
640
-        if ($model instanceof \EEM_CPT_Base) {
641
-            $do_chevy_shuffle = true;
642
-        } else {
643
-            $do_chevy_shuffle = false;
644
-        }
645
-        if ($do_chevy_shuffle) {
646
-            global $post;
647
-            $old_post = $post;
648
-            $post = get_post($result[ $model->primary_key_name() ]);
649
-            if (! $post instanceof \WP_Post) {
650
-                // well that's weird, because $result is what we JUST fetched from the database
651
-                throw new RestException(
652
-                    'error_fetching_post_from_database_results',
653
-                    esc_html__(
654
-                        'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
655
-                        'event_espresso'
656
-                    )
657
-                );
658
-            }
659
-            $model_object_classname = 'EE_' . $model->get_this_model_name();
660
-            $post->{$model_object_classname} = \EE_Registry::instance()->load_class(
661
-                $model_object_classname,
662
-                $result,
663
-                false,
664
-                false
665
-            );
666
-        }
667
-        foreach ($result as $field_name => $field_value) {
668
-            $field_obj = $model->field_settings_for($field_name);
669
-            if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
670
-                unset($result[ $field_name ]);
671
-            } elseif ($this->isSubclassOfOne(
672
-                $field_obj,
673
-                $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
674
-            )
675
-            ) {
676
-                $result[ $field_name ] = array(
677
-                    'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
678
-                    'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
679
-                );
680
-            } elseif ($this->isSubclassOfOne(
681
-                $field_obj,
682
-                $this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
683
-            )
684
-            ) {
685
-                $result[ $field_name ] = array(
686
-                    'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
687
-                    'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
688
-                );
689
-            } elseif ($field_obj instanceof \EE_Datetime_Field) {
690
-                $field_value = $field_obj->prepare_for_set_from_db($field_value);
691
-                // if the value is null, but we're not supposed to permit null, then set to the field's default
692
-                if (is_null($field_value)) {
693
-                    $field_value = $field_obj->getDefaultDateTimeObj();
694
-                }
695
-                if (is_null($field_value)) {
696
-                    $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson(
697
-                        $field_obj,
698
-                        $field_value,
699
-                        $this->getModelVersionInfo()->requestedVersion()
700
-                    );
701
-                } else {
702
-                    $timezone = $field_value->getTimezone();
703
-                    EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC'));
704
-                    $gmt_date = ModelDataTranslator::prepareFieldValuesForJson(
705
-                        $field_obj,
706
-                        $field_value,
707
-                        $this->getModelVersionInfo()->requestedVersion()
708
-                    );
709
-                    EEH_DTT_Helper::setTimezone($field_value, $timezone);
710
-                    $local_date = ModelDataTranslator::prepareFieldValuesForJson(
711
-                        $field_obj,
712
-                        $field_value,
713
-                        $this->getModelVersionInfo()->requestedVersion()
714
-                    );
715
-                }
716
-                $result[ $field_name . '_gmt' ] = $gmt_date;
717
-                $result[ $field_name ] = $local_date;
718
-            } else {
719
-                $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
720
-            }
721
-        }
722
-        if ($do_chevy_shuffle) {
723
-            $post = $old_post;
724
-        }
725
-        return $result;
726
-    }
727
-
728
-
729
-    /**
730
-     * Takes a value all the way from the DB representation, to the model object's representation, to the
731
-     * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
732
-     * representation using $field_obj->prepare_for_set_from_db())
733
-     *
734
-     * @param EE_Model_Field_Base $field_obj
735
-     * @param mixed               $value  as it's stored on a model object
736
-     * @param string              $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
737
-     * @return mixed
738
-     * @throws ObjectDetectedException if $value contains a PHP object
739
-     */
740
-    protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
741
-    {
742
-        $value = $field_obj->prepare_for_set_from_db($value);
743
-        switch ($format) {
744
-            case 'pretty':
745
-                $value = $field_obj->prepare_for_pretty_echoing($value);
746
-                break;
747
-            case 'normal':
748
-            default:
749
-                $value = $field_obj->prepare_for_get($value);
750
-                break;
751
-        }
752
-        return ModelDataTranslator::prepareFieldValuesForJson(
753
-            $field_obj,
754
-            $value,
755
-            $this->getModelVersionInfo()->requestedVersion()
756
-        );
757
-    }
758
-
759
-
760
-    /**
761
-     * Adds a few extra fields to the entity response
762
-     *
763
-     * @param EEM_Base $model
764
-     * @param array    $db_row
765
-     * @param array    $entity_array
766
-     * @return array modified entity
767
-     */
768
-    protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
769
-    {
770
-        if ($model instanceof EEM_CPT_Base) {
771
-            $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
772
-        }
773
-        return $entity_array;
774
-    }
775
-
776
-
777
-    /**
778
-     * Gets links we want to add to the response
779
-     *
780
-     * @global \WP_REST_Server $wp_rest_server
781
-     * @param EEM_Base         $model
782
-     * @param array            $db_row
783
-     * @param array            $entity_array
784
-     * @return array the _links item in the entity
785
-     */
786
-    protected function getEntityLinks($model, $db_row, $entity_array)
787
-    {
788
-        // add basic links
789
-        $links = array();
790
-        if ($model->has_primary_key_field()) {
791
-            $links['self'] = array(
792
-                array(
793
-                    'href' => $this->getVersionedLinkTo(
794
-                        EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
795
-                        . '/'
796
-                        . $entity_array[ $model->primary_key_name() ]
797
-                    ),
798
-                ),
799
-            );
800
-        }
801
-        $links['collection'] = array(
802
-            array(
803
-                'href' => $this->getVersionedLinkTo(
804
-                    EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
805
-                ),
806
-            ),
807
-        );
808
-        // add links to related models
809
-        if ($model->has_primary_key_field()) {
810
-            foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
811
-                $related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
812
-                $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = array(
813
-                    array(
814
-                        'href'   => $this->getVersionedLinkTo(
815
-                            EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
816
-                            . '/'
817
-                            . $entity_array[ $model->primary_key_name() ]
818
-                            . '/'
819
-                            . $related_model_part
820
-                        ),
821
-                        'single' => $relation_obj instanceof EE_Belongs_To_Relation ? true : false,
822
-                    ),
823
-                );
824
-            }
825
-        }
826
-        return $links;
827
-    }
828
-
829
-
830
-    /**
831
-     * Adds the included models indicated in the request to the entity provided
832
-     *
833
-     * @param EEM_Base        $model
834
-     * @param WP_REST_Request $rest_request
835
-     * @param array           $entity_array
836
-     * @param array           $db_row
837
-     * @return array the modified entity
838
-     */
839
-    protected function includeRequestedModels(
840
-        EEM_Base $model,
841
-        WP_REST_Request $rest_request,
842
-        $entity_array,
843
-        $db_row = array()
844
-    ) {
845
-        // if $db_row not included, hope the entity array has what we need
846
-        if (! $db_row) {
847
-            $db_row = $entity_array;
848
-        }
849
-        $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
850
-        $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
851
-        // if they passed in * or didn't specify any includes, return everything
852
-        if (! in_array('*', $includes_for_this_model)
853
-            && ! empty($includes_for_this_model)
854
-        ) {
855
-            if ($model->has_primary_key_field()) {
856
-                // always include the primary key. ya just gotta know that at least
857
-                $includes_for_this_model[] = $model->primary_key_name();
858
-            }
859
-            if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
860
-                $includes_for_this_model[] = '_calculated_fields';
861
-            }
862
-            $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
863
-        }
864
-        $relation_settings = $this->getModelVersionInfo()->relationSettings($model);
865
-        foreach ($relation_settings as $relation_name => $relation_obj) {
866
-            $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith(
867
-                $rest_request->get_param('include'),
868
-                $relation_name
869
-            );
870
-            $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
871
-                $rest_request->get_param('calculate'),
872
-                $relation_name
873
-            );
874
-            // did they specify they wanted to include a related model, or
875
-            // specific fields from a related model?
876
-            // or did they specify to calculate a field from a related model?
877
-            if ($related_fields_to_include || $related_fields_to_calculate) {
878
-                // if so, we should include at least some part of the related model
879
-                $pretend_related_request = new WP_REST_Request();
880
-                $pretend_related_request->set_query_params(
881
-                    array(
882
-                        'caps'      => $rest_request->get_param('caps'),
883
-                        'include'   => $related_fields_to_include,
884
-                        'calculate' => $related_fields_to_calculate,
885
-                    )
886
-                );
887
-                $pretend_related_request->add_header('no_rest_headers', true);
888
-                $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
889
-                    $model->get_index_primary_key_string(
890
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
891
-                    )
892
-                );
893
-                $related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
894
-                    $primary_model_query_params,
895
-                    $relation_obj,
896
-                    $pretend_related_request
897
-                );
898
-                $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results
899
-                                                                                             instanceof
900
-                                                                                             WP_Error
901
-                    ? null
902
-                    : $related_results;
903
-            }
904
-        }
905
-        return $entity_array;
906
-    }
907
-
908
-
909
-    /**
910
-     * Returns a new array with all the names of models removed. Eg
911
-     * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
912
-     *
913
-     * @param array $arr
914
-     * @return array
915
-     */
916
-    private function removeModelNamesFromArray($arr)
917
-    {
918
-        return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
919
-    }
920
-
921
-
922
-    /**
923
-     * Gets the calculated fields for the response
924
-     *
925
-     * @param EEM_Base        $model
926
-     * @param array           $wpdb_row
927
-     * @param WP_REST_Request $rest_request
928
-     * @return \stdClass the _calculations item in the entity
929
-     * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
930
-     * did, let's know about it ASAP, so let the exception bubble up)
931
-     */
932
-    protected function getEntityCalculations($model, $wpdb_row, $rest_request)
933
-    {
934
-        $calculated_fields = $this->explodeAndGetItemsPrefixedWith(
935
-            $rest_request->get_param('calculate'),
936
-            ''
937
-        );
938
-        // note: setting calculate=* doesn't do anything
939
-        $calculated_fields_to_return = new \stdClass();
940
-        foreach ($calculated_fields as $field_to_calculate) {
941
-            try {
942
-                $calculated_fields_to_return->$field_to_calculate = ModelDataTranslator::prepareFieldValueForJson(
943
-                    null,
944
-                    $this->fields_calculator->retrieveCalculatedFieldValue(
945
-                        $model,
946
-                        $field_to_calculate,
947
-                        $wpdb_row,
948
-                        $rest_request,
949
-                        $this
950
-                    ),
951
-                    $this->getModelVersionInfo()->requestedVersion()
952
-                );
953
-            } catch (RestException $e) {
954
-                // if we don't have permission to read it, just leave it out. but let devs know about the problem
955
-                $this->setResponseHeader(
956
-                    'Notices-Field-Calculation-Errors['
957
-                    . $e->getStringCode()
958
-                    . ']['
959
-                    . $model->get_this_model_name()
960
-                    . ']['
961
-                    . $field_to_calculate
962
-                    . ']',
963
-                    $e->getMessage(),
964
-                    true
965
-                );
966
-            }
967
-        }
968
-        return $calculated_fields_to_return;
969
-    }
970
-
971
-
972
-    /**
973
-     * Gets the full URL to the resource, taking the requested version into account
974
-     *
975
-     * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
976
-     * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
977
-     */
978
-    public function getVersionedLinkTo($link_part_after_version_and_slash)
979
-    {
980
-        return rest_url(
981
-            EED_Core_Rest_Api::get_versioned_route_to(
982
-                $link_part_after_version_and_slash,
983
-                $this->getModelVersionInfo()->requestedVersion()
984
-            )
985
-        );
986
-    }
987
-
988
-
989
-    /**
990
-     * Gets the correct lowercase name for the relation in the API according
991
-     * to the relation's type
992
-     *
993
-     * @param string                  $relation_name
994
-     * @param \EE_Model_Relation_Base $relation_obj
995
-     * @return string
996
-     */
997
-    public static function getRelatedEntityName($relation_name, $relation_obj)
998
-    {
999
-        if ($relation_obj instanceof EE_Belongs_To_Relation) {
1000
-            return strtolower($relation_name);
1001
-        } else {
1002
-            return EEH_Inflector::pluralize_and_lower($relation_name);
1003
-        }
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * Gets the one model object with the specified id for the specified model
1009
-     *
1010
-     * @param EEM_Base        $model
1011
-     * @param WP_REST_Request $request
1012
-     * @return array|WP_Error
1013
-     */
1014
-    public function getEntityFromModel($model, $request)
1015
-    {
1016
-        $context = $this->validateContext($request->get_param('caps'));
1017
-        return $this->getOneOrReportPermissionError($model, $request, $context);
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * If a context is provided which isn't valid, maybe it was added in a future
1023
-     * version so just treat it as a default read
1024
-     *
1025
-     * @param string $context
1026
-     * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1027
-     */
1028
-    public function validateContext($context)
1029
-    {
1030
-        if (! $context) {
1031
-            $context = EEM_Base::caps_read;
1032
-        }
1033
-        $valid_contexts = EEM_Base::valid_cap_contexts();
1034
-        if (in_array($context, $valid_contexts)) {
1035
-            return $context;
1036
-        } else {
1037
-            return EEM_Base::caps_read;
1038
-        }
1039
-    }
1040
-
1041
-
1042
-    /**
1043
-     * Verifies the passed in value is an allowable default where conditions value.
1044
-     *
1045
-     * @param $default_query_params
1046
-     * @return string
1047
-     */
1048
-    public function validateDefaultQueryParams($default_query_params)
1049
-    {
1050
-        $valid_default_where_conditions_for_api_calls = array(
1051
-            EEM_Base::default_where_conditions_all,
1052
-            EEM_Base::default_where_conditions_minimum_all,
1053
-            EEM_Base::default_where_conditions_minimum_others,
1054
-        );
1055
-        if (! $default_query_params) {
1056
-            $default_query_params = EEM_Base::default_where_conditions_all;
1057
-        }
1058
-        if (in_array(
1059
-            $default_query_params,
1060
-            $valid_default_where_conditions_for_api_calls,
1061
-            true
1062
-        )) {
1063
-            return $default_query_params;
1064
-        } else {
1065
-            return EEM_Base::default_where_conditions_all;
1066
-        }
1067
-    }
1068
-
1069
-
1070
-    /**
1071
-     * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1072
-     * Note: right now the query parameter keys for fields (and related fields)
1073
-     * can be left as-is, but it's quite possible this will change someday.
1074
-     * Also, this method's contents might be candidate for moving to Model_Data_Translator
1075
-     *
1076
-     * @param EEM_Base $model
1077
-     * @param array    $query_parameters  from $_GET parameter @see Read:handle_request_get_all
1078
-     * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1079
-     *                                    that absolutely no results should be returned
1080
-     * @throws EE_Error
1081
-     * @throws RestException
1082
-     */
1083
-    public function createModelQueryParams($model, $query_parameters)
1084
-    {
1085
-        $model_query_params = array();
1086
-        if (isset($query_parameters['where'])) {
1087
-            $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1088
-                $query_parameters['where'],
1089
-                $model,
1090
-                $this->getModelVersionInfo()->requestedVersion()
1091
-            );
1092
-        }
1093
-        if (isset($query_parameters['order_by'])) {
1094
-            $order_by = $query_parameters['order_by'];
1095
-        } elseif (isset($query_parameters['orderby'])) {
1096
-            $order_by = $query_parameters['orderby'];
1097
-        } else {
1098
-            $order_by = null;
1099
-        }
1100
-        if ($order_by !== null) {
1101
-            if (is_array($order_by)) {
1102
-                $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1103
-            } else {
1104
-                // it's a single item
1105
-                $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1106
-            }
1107
-            $model_query_params['order_by'] = $order_by;
1108
-        }
1109
-        if (isset($query_parameters['group_by'])) {
1110
-            $group_by = $query_parameters['group_by'];
1111
-        } elseif (isset($query_parameters['groupby'])) {
1112
-            $group_by = $query_parameters['groupby'];
1113
-        } else {
1114
-            $group_by = array_keys($model->get_combined_primary_key_fields());
1115
-        }
1116
-        // make sure they're all real names
1117
-        if (is_array($group_by)) {
1118
-            $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1119
-        }
1120
-        if ($group_by !== null) {
1121
-            $model_query_params['group_by'] = $group_by;
1122
-        }
1123
-        if (isset($query_parameters['having'])) {
1124
-            $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1125
-                $query_parameters['having'],
1126
-                $model,
1127
-                $this->getModelVersionInfo()->requestedVersion()
1128
-            );
1129
-        }
1130
-        if (isset($query_parameters['order'])) {
1131
-            $model_query_params['order'] = $query_parameters['order'];
1132
-        }
1133
-        if (isset($query_parameters['mine'])) {
1134
-            $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1135
-        }
1136
-        if (isset($query_parameters['limit'])) {
1137
-            // limit should be either a string like '23' or '23,43', or an array with two items in it
1138
-            if (! is_array($query_parameters['limit'])) {
1139
-                $limit_array = explode(',', (string) $query_parameters['limit']);
1140
-            } else {
1141
-                $limit_array = $query_parameters['limit'];
1142
-            }
1143
-            $sanitized_limit = array();
1144
-            foreach ($limit_array as $key => $limit_part) {
1145
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1146
-                    throw new EE_Error(
1147
-                        sprintf(
1148
-                            __(
1149
-                            // @codingStandardsIgnoreStart
1150
-                                'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1151
-                                // @codingStandardsIgnoreEnd
1152
-                                'event_espresso'
1153
-                            ),
1154
-                            wp_json_encode($query_parameters['limit'])
1155
-                        )
1156
-                    );
1157
-                }
1158
-                $sanitized_limit[] = (int) $limit_part;
1159
-            }
1160
-            $model_query_params['limit'] = implode(',', $sanitized_limit);
1161
-        } else {
1162
-            $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1163
-        }
1164
-        if (isset($query_parameters['caps'])) {
1165
-            $model_query_params['caps'] = $this->validateContext($query_parameters['caps']);
1166
-        } else {
1167
-            $model_query_params['caps'] = EEM_Base::caps_read;
1168
-        }
1169
-        if (isset($query_parameters['default_where_conditions'])) {
1170
-            $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1171
-                $query_parameters['default_where_conditions']
1172
-            );
1173
-        }
1174
-        return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Changes the REST-style query params for use in the models
1180
-     *
1181
-     * @deprecated
1182
-     * @param EEM_Base $model
1183
-     * @param array    $query_params sub-array from @see EEM_Base::get_all()
1184
-     * @return array
1185
-     */
1186
-    public function prepareRestQueryParamsKeyForModels($model, $query_params)
1187
-    {
1188
-        $model_ready_query_params = array();
1189
-        foreach ($query_params as $key => $value) {
1190
-            if (is_array($value)) {
1191
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1192
-            } else {
1193
-                $model_ready_query_params[ $key ] = $value;
1194
-            }
1195
-        }
1196
-        return $model_ready_query_params;
1197
-    }
1198
-
1199
-
1200
-    /**
1201
-     * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1202
-     * @param $model
1203
-     * @param $query_params
1204
-     * @return array
1205
-     */
1206
-    public function prepareRestQueryParamsValuesForModels($model, $query_params)
1207
-    {
1208
-        $model_ready_query_params = array();
1209
-        foreach ($query_params as $key => $value) {
1210
-            if (is_array($value)) {
1211
-                $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1212
-            } else {
1213
-                $model_ready_query_params[ $key ] = $value;
1214
-            }
1215
-        }
1216
-        return $model_ready_query_params;
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     * Explodes the string on commas, and only returns items with $prefix followed by a period.
1222
-     * If no prefix is specified, returns items with no period.
1223
-     *
1224
-     * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1225
-     * @param string       $prefix            "Event" or "foobar"
1226
-     * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1227
-     *                                        we only return strings starting with that and a period; if no prefix was
1228
-     *                                        specified we return all items containing NO periods
1229
-     */
1230
-    public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1231
-    {
1232
-        if (is_string($string_to_explode)) {
1233
-            $exploded_contents = explode(',', $string_to_explode);
1234
-        } elseif (is_array($string_to_explode)) {
1235
-            $exploded_contents = $string_to_explode;
1236
-        } else {
1237
-            $exploded_contents = array();
1238
-        }
1239
-        // if the string was empty, we want an empty array
1240
-        $exploded_contents = array_filter($exploded_contents);
1241
-        $contents_with_prefix = array();
1242
-        foreach ($exploded_contents as $item) {
1243
-            $item = trim($item);
1244
-            // if no prefix was provided, so we look for items with no "." in them
1245
-            if (! $prefix) {
1246
-                // does this item have a period?
1247
-                if (strpos($item, '.') === false) {
1248
-                    // if not, then its what we're looking for
1249
-                    $contents_with_prefix[] = $item;
1250
-                }
1251
-            } elseif (strpos($item, $prefix . '.') === 0) {
1252
-                // this item has the prefix and a period, grab it
1253
-                $contents_with_prefix[] = substr(
1254
-                    $item,
1255
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1256
-                );
1257
-            } elseif ($item === $prefix) {
1258
-                // this item is JUST the prefix
1259
-                // so let's grab everything after, which is a blank string
1260
-                $contents_with_prefix[] = '';
1261
-            }
1262
-        }
1263
-        return $contents_with_prefix;
1264
-    }
1265
-
1266
-
1267
-    /**
1268
-     * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1269
-     * Deprecated because its return values were really quite confusing- sometimes it returned
1270
-     * an empty array (when the include string was blank or '*') or sometimes it returned
1271
-     * array('*') (when you provided a model and a model of that kind was found).
1272
-     * Parses the $include_string so we fetch all the field names relating to THIS model
1273
-     * (ie have NO period in them), or for the provided model (ie start with the model
1274
-     * name and then a period).
1275
-     * @param string $include_string @see Read:handle_request_get_all
1276
-     * @param string $model_name
1277
-     * @return array of fields for this model. If $model_name is provided, then
1278
-     *                               the fields for that model, with the model's name removed from each.
1279
-     *                               If $include_string was blank or '*' returns an empty array
1280
-     */
1281
-    public function extractIncludesForThisModel($include_string, $model_name = null)
1282
-    {
1283
-        if (is_array($include_string)) {
1284
-            $include_string = implode(',', $include_string);
1285
-        }
1286
-        if ($include_string === '*' || $include_string === '') {
1287
-            return array();
1288
-        }
1289
-        $includes = explode(',', $include_string);
1290
-        $extracted_fields_to_include = array();
1291
-        if ($model_name) {
1292
-            foreach ($includes as $field_to_include) {
1293
-                $field_to_include = trim($field_to_include);
1294
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1295
-                    // found the model name at the exact start
1296
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1297
-                    $extracted_fields_to_include[] = $field_sans_model_name;
1298
-                } elseif ($field_to_include == $model_name) {
1299
-                    $extracted_fields_to_include[] = '*';
1300
-                }
1301
-            }
1302
-        } else {
1303
-            // look for ones with no period
1304
-            foreach ($includes as $field_to_include) {
1305
-                $field_to_include = trim($field_to_include);
1306
-                if (strpos($field_to_include, '.') === false
1307
-                    && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1308
-                ) {
1309
-                    $extracted_fields_to_include[] = $field_to_include;
1310
-                }
1311
-            }
1312
-        }
1313
-        return $extracted_fields_to_include;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Gets the single item using the model according to the request in the context given, otherwise
1319
-     * returns that it's inaccessible to the current user
1320
-     *
1321
-     * @param EEM_Base        $model
1322
-     * @param WP_REST_Request $request
1323
-     * @param null            $context
1324
-     * @return array|WP_Error
1325
-     */
1326
-    public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1327
-    {
1328
-        $query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
1329
-        if ($model instanceof \EEM_Soft_Delete_Base) {
1330
-            $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1331
-        }
1332
-        $restricted_query_params = $query_params;
1333
-        $restricted_query_params['caps'] = $context;
1334
-        $this->setDebugInfo('model query params', $restricted_query_params);
1335
-        $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1336
-        if (! empty($model_rows)) {
1337
-            return $this->createEntityFromWpdbResult(
1338
-                $model,
1339
-                array_shift($model_rows),
1340
-                $request
1341
-            );
1342
-        } else {
1343
-            // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1344
-            $lowercase_model_name = strtolower($model->get_this_model_name());
1345
-            $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1346
-            if (! empty($model_rows_found_sans_restrictions)) {
1347
-                // you got shafted- it existed but we didn't want to tell you!
1348
-                return new WP_Error(
1349
-                    'rest_user_cannot_' . $context,
1350
-                    sprintf(
1351
-                        __('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1352
-                        $context,
1353
-                        strtolower($model->get_this_model_name()),
1354
-                        Capabilities::getMissingPermissionsString(
1355
-                            $model,
1356
-                            $context
1357
-                        )
1358
-                    ),
1359
-                    array('status' => 403)
1360
-                );
1361
-            } else {
1362
-                // it's not you. It just doesn't exist
1363
-                return new WP_Error(
1364
-                    sprintf('rest_%s_invalid_id', $lowercase_model_name),
1365
-                    sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1366
-                    array('status' => 404)
1367
-                );
1368
-            }
1369
-        }
1370
-    }
38
+	/**
39
+	 * @var CalculatedModelFields
40
+	 */
41
+	protected $fields_calculator;
42
+
43
+
44
+	/**
45
+	 * Read constructor.
46
+	 */
47
+	public function __construct()
48
+	{
49
+		parent::__construct();
50
+		$this->fields_calculator = new CalculatedModelFields();
51
+	}
52
+
53
+
54
+	/**
55
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
56
+	 *
57
+	 * @param WP_REST_Request $request
58
+	 * @param string          $version
59
+	 * @param string          $model_name
60
+	 * @return \WP_REST_Response|WP_Error
61
+	 */
62
+	public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
63
+	{
64
+		$controller = new Read();
65
+		try {
66
+			$controller->setRequestedVersion($version);
67
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
68
+				return $controller->sendResponse(
69
+					new WP_Error(
70
+						'endpoint_parsing_error',
71
+						sprintf(
72
+							__(
73
+								'There is no model for endpoint %s. Please contact event espresso support',
74
+								'event_espresso'
75
+							),
76
+							$model_name
77
+						)
78
+					)
79
+				);
80
+			}
81
+			return $controller->sendResponse(
82
+				$controller->getEntitiesFromModel(
83
+					$controller->getModelVersionInfo()->loadModel($model_name),
84
+					$request
85
+				)
86
+			);
87
+		} catch (Exception $e) {
88
+			return $controller->sendResponse($e);
89
+		}
90
+	}
91
+
92
+
93
+	/**
94
+	 * Prepares and returns schema for any OPTIONS request.
95
+	 *
96
+	 * @param string $version    The API endpoint version being used.
97
+	 * @param string $model_name Something like `Event` or `Registration`
98
+	 * @return array
99
+	 */
100
+	public static function handleSchemaRequest($version, $model_name)
101
+	{
102
+		$controller = new Read();
103
+		try {
104
+			$controller->setRequestedVersion($version);
105
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
106
+				return array();
107
+			}
108
+			// get the model for this version
109
+			$model = $controller->getModelVersionInfo()->loadModel($model_name);
110
+			$model_schema = new JsonModelSchema($model);
111
+			return $model_schema->getModelSchemaForRelations(
112
+				$controller->getModelVersionInfo()->relationSettings($model),
113
+				$controller->customizeSchemaForRestResponse(
114
+					$model,
115
+					$model_schema->getModelSchemaForFields(
116
+						$controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
117
+						$model_schema->getInitialSchemaStructure()
118
+					)
119
+				)
120
+			);
121
+		} catch (Exception $e) {
122
+			return array();
123
+		}
124
+	}
125
+
126
+
127
+	/**
128
+	 * This loops through each field in the given schema for the model and does the following:
129
+	 * - add any extra fields that are REST API specific and related to existing fields.
130
+	 * - transform default values into the correct format for a REST API response.
131
+	 *
132
+	 * @param EEM_Base $model
133
+	 * @param array    $schema
134
+	 * @return array  The final schema.
135
+	 */
136
+	protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
137
+	{
138
+		foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
139
+			$schema = $this->translateDefaultsForRestResponse(
140
+				$field_name,
141
+				$field,
142
+				$this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
143
+			);
144
+		}
145
+		return $schema;
146
+	}
147
+
148
+
149
+	/**
150
+	 * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
151
+	 * response.
152
+	 *
153
+	 * @param                      $field_name
154
+	 * @param EE_Model_Field_Base  $field
155
+	 * @param array                $schema
156
+	 * @return array
157
+	 * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
158
+	 * did, let's know about it ASAP, so let the exception bubble up)
159
+	 */
160
+	protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
161
+	{
162
+		if (isset($schema['properties'][ $field_name ]['default'])) {
163
+			if (is_array($schema['properties'][ $field_name ]['default'])) {
164
+				foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) {
165
+					if ($default_key === 'raw') {
166
+						$schema['properties'][ $field_name ]['default'][ $default_key ] =
167
+							ModelDataTranslator::prepareFieldValueForJson(
168
+								$field,
169
+								$default_value,
170
+								$this->getModelVersionInfo()->requestedVersion()
171
+							);
172
+					}
173
+				}
174
+			} else {
175
+				$schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson(
176
+					$field,
177
+					$schema['properties'][ $field_name ]['default'],
178
+					$this->getModelVersionInfo()->requestedVersion()
179
+				);
180
+			}
181
+		}
182
+		return $schema;
183
+	}
184
+
185
+
186
+	/**
187
+	 * Adds additional fields to the schema
188
+	 * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
189
+	 * needs to be added to the schema.
190
+	 *
191
+	 * @param                      $field_name
192
+	 * @param EE_Model_Field_Base  $field
193
+	 * @param array                $schema
194
+	 * @return array
195
+	 */
196
+	protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
197
+	{
198
+		if ($field instanceof EE_Datetime_Field) {
199
+			$schema['properties'][ $field_name . '_gmt' ] = $field->getSchema();
200
+			// modify the description
201
+			$schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf(
202
+				esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
203
+				wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
204
+			);
205
+		}
206
+		return $schema;
207
+	}
208
+
209
+
210
+	/**
211
+	 * Used to figure out the route from the request when a `WP_REST_Request` object is not available
212
+	 *
213
+	 * @return string
214
+	 */
215
+	protected function getRouteFromRequest()
216
+	{
217
+		if (isset($GLOBALS['wp'])
218
+			&& $GLOBALS['wp'] instanceof \WP
219
+			&& isset($GLOBALS['wp']->query_vars['rest_route'])
220
+		) {
221
+			return $GLOBALS['wp']->query_vars['rest_route'];
222
+		} else {
223
+			return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
224
+		}
225
+	}
226
+
227
+
228
+	/**
229
+	 * Gets a single entity related to the model indicated in the path and its id
230
+	 *
231
+	 * @param WP_REST_Request $request
232
+	 * @param string          $version
233
+	 * @param string          $model_name
234
+	 * @return \WP_REST_Response|WP_Error
235
+	 */
236
+	public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
237
+	{
238
+		$controller = new Read();
239
+		try {
240
+			$controller->setRequestedVersion($version);
241
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
242
+				return $controller->sendResponse(
243
+					new WP_Error(
244
+						'endpoint_parsing_error',
245
+						sprintf(
246
+							__(
247
+								'There is no model for endpoint %s. Please contact event espresso support',
248
+								'event_espresso'
249
+							),
250
+							$model_name
251
+						)
252
+					)
253
+				);
254
+			}
255
+			return $controller->sendResponse(
256
+				$controller->getEntityFromModel(
257
+					$controller->getModelVersionInfo()->loadModel($model_name),
258
+					$request
259
+				)
260
+			);
261
+		} catch (Exception $e) {
262
+			return $controller->sendResponse($e);
263
+		}
264
+	}
265
+
266
+
267
+	/**
268
+	 * Gets all the related entities (or if its a belongs-to relation just the one)
269
+	 * to the item with the given id
270
+	 *
271
+	 * @param WP_REST_Request $request
272
+	 * @param string          $version
273
+	 * @param string          $model_name
274
+	 * @param string          $related_model_name
275
+	 * @return \WP_REST_Response|WP_Error
276
+	 */
277
+	public static function handleRequestGetRelated(
278
+		WP_REST_Request $request,
279
+		$version,
280
+		$model_name,
281
+		$related_model_name
282
+	) {
283
+		$controller = new Read();
284
+		try {
285
+			$controller->setRequestedVersion($version);
286
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
287
+				return $controller->sendResponse(
288
+					new WP_Error(
289
+						'endpoint_parsing_error',
290
+						sprintf(
291
+							__(
292
+								'There is no model for endpoint %s. Please contact event espresso support',
293
+								'event_espresso'
294
+							),
295
+							$model_name
296
+						)
297
+					)
298
+				);
299
+			}
300
+			$main_model = $controller->getModelVersionInfo()->loadModel($model_name);
301
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
302
+				return $controller->sendResponse(
303
+					new WP_Error(
304
+						'endpoint_parsing_error',
305
+						sprintf(
306
+							__(
307
+								'There is no model for endpoint %s. Please contact event espresso support',
308
+								'event_espresso'
309
+							),
310
+							$related_model_name
311
+						)
312
+					)
313
+				);
314
+			}
315
+			return $controller->sendResponse(
316
+				$controller->getEntitiesFromRelation(
317
+					$request->get_param('id'),
318
+					$main_model->related_settings_for($related_model_name),
319
+					$request
320
+				)
321
+			);
322
+		} catch (Exception $e) {
323
+			return $controller->sendResponse($e);
324
+		}
325
+	}
326
+
327
+
328
+	/**
329
+	 * Gets a collection for the given model and filters
330
+	 *
331
+	 * @param EEM_Base        $model
332
+	 * @param WP_REST_Request $request
333
+	 * @return array|WP_Error
334
+	 */
335
+	public function getEntitiesFromModel($model, $request)
336
+	{
337
+		$query_params = $this->createModelQueryParams($model, $request->get_params());
338
+		if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
339
+			$model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
340
+			return new WP_Error(
341
+				sprintf('rest_%s_cannot_list', $model_name_plural),
342
+				sprintf(
343
+					__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
344
+					$model_name_plural,
345
+					Capabilities::getMissingPermissionsString($model, $query_params['caps'])
346
+				),
347
+				array('status' => 403)
348
+			);
349
+		}
350
+		if (! $request->get_header('no_rest_headers')) {
351
+			$this->setHeadersFromQueryParams($model, $query_params);
352
+		}
353
+		/** @type array $results */
354
+		$results = $model->get_all_wpdb_results($query_params);
355
+		$nice_results = array();
356
+		foreach ($results as $result) {
357
+			$nice_results[] = $this->createEntityFromWpdbResult(
358
+				$model,
359
+				$result,
360
+				$request
361
+			);
362
+		}
363
+		return $nice_results;
364
+	}
365
+
366
+
367
+	/**
368
+	 * Gets the collection for given relation object
369
+	 * The same as Read::get_entities_from_model(), except if the relation
370
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
371
+	 * the join-model-object into the results
372
+	 *
373
+	 * @param array                   $primary_model_query_params query params for finding the item from which
374
+	 *                                                            relations will be based
375
+	 * @param \EE_Model_Relation_Base $relation
376
+	 * @param WP_REST_Request         $request
377
+	 * @return WP_Error|array
378
+	 * @throws RestException
379
+	 */
380
+	protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
381
+	{
382
+		$context = $this->validateContext($request->get_param('caps'));
383
+		$model = $relation->get_this_model();
384
+		$related_model = $relation->get_other_model();
385
+		if (! isset($primary_model_query_params[0])) {
386
+			$primary_model_query_params[0] = array();
387
+		}
388
+		// check if they can access the 1st model object
389
+		$primary_model_query_params = array(
390
+			0       => $primary_model_query_params[0],
391
+			'limit' => 1,
392
+		);
393
+		if ($model instanceof \EEM_Soft_Delete_Base) {
394
+			$primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
395
+				$primary_model_query_params
396
+			);
397
+		}
398
+		$restricted_query_params = $primary_model_query_params;
399
+		$restricted_query_params['caps'] = $context;
400
+		$this->setDebugInfo('main model query params', $restricted_query_params);
401
+		$this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
402
+		if (! (
403
+			Capabilities::currentUserHasPartialAccessTo($related_model, $context)
404
+			&& $model->exists($restricted_query_params)
405
+		)
406
+		) {
407
+			if ($relation instanceof EE_Belongs_To_Relation) {
408
+				$related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
409
+			} else {
410
+				$related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
411
+					$related_model->get_this_model_name()
412
+				);
413
+			}
414
+			return new WP_Error(
415
+				sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
416
+				sprintf(
417
+					__(
418
+						'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
419
+						'event_espresso'
420
+					),
421
+					$related_model_name_maybe_plural,
422
+					$relation->get_this_model()->get_this_model_name(),
423
+					implode(
424
+						',',
425
+						array_keys(
426
+							Capabilities::getMissingPermissions($related_model, $context)
427
+						)
428
+					)
429
+				),
430
+				array('status' => 403)
431
+			);
432
+		}
433
+		$query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
434
+		foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
435
+			$query_params[0][ $relation->get_this_model()->get_this_model_name()
436
+							  . '.'
437
+							  . $where_condition_key ] = $where_condition_value;
438
+		}
439
+		$query_params['default_where_conditions'] = 'none';
440
+		$query_params['caps'] = $context;
441
+		if (! $request->get_header('no_rest_headers')) {
442
+			$this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
443
+		}
444
+		/** @type array $results */
445
+		$results = $relation->get_other_model()->get_all_wpdb_results($query_params);
446
+		$nice_results = array();
447
+		foreach ($results as $result) {
448
+			$nice_result = $this->createEntityFromWpdbResult(
449
+				$relation->get_other_model(),
450
+				$result,
451
+				$request
452
+			);
453
+			if ($relation instanceof \EE_HABTM_Relation) {
454
+				// put the unusual stuff (properties from the HABTM relation) first, and make sure
455
+				// if there are conflicts we prefer the properties from the main model
456
+				$join_model_result = $this->createEntityFromWpdbResult(
457
+					$relation->get_join_model(),
458
+					$result,
459
+					$request
460
+				);
461
+				$joined_result = array_merge($nice_result, $join_model_result);
462
+				// but keep the meta stuff from the main model
463
+				if (isset($nice_result['meta'])) {
464
+					$joined_result['meta'] = $nice_result['meta'];
465
+				}
466
+				$nice_result = $joined_result;
467
+			}
468
+			$nice_results[] = $nice_result;
469
+		}
470
+		if ($relation instanceof EE_Belongs_To_Relation) {
471
+			return array_shift($nice_results);
472
+		} else {
473
+			return $nice_results;
474
+		}
475
+	}
476
+
477
+
478
+	/**
479
+	 * Gets the collection for given relation object
480
+	 * The same as Read::get_entities_from_model(), except if the relation
481
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
482
+	 * the join-model-object into the results
483
+	 *
484
+	 * @param string                  $id the ID of the thing we are fetching related stuff from
485
+	 * @param \EE_Model_Relation_Base $relation
486
+	 * @param WP_REST_Request         $request
487
+	 * @return array|WP_Error
488
+	 * @throws EE_Error
489
+	 */
490
+	public function getEntitiesFromRelation($id, $relation, $request)
491
+	{
492
+		if (! $relation->get_this_model()->has_primary_key_field()) {
493
+			throw new EE_Error(
494
+				sprintf(
495
+					__(
496
+					// @codingStandardsIgnoreStart
497
+						'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
498
+						// @codingStandardsIgnoreEnd
499
+						'event_espresso'
500
+					),
501
+					$relation->get_this_model()->get_this_model_name()
502
+				)
503
+			);
504
+		}
505
+		return $this->getEntitiesFromRelationUsingModelQueryParams(
506
+			array(
507
+				array(
508
+					$relation->get_this_model()->primary_key_name() => $id,
509
+				),
510
+			),
511
+			$relation,
512
+			$request
513
+		);
514
+	}
515
+
516
+
517
+	/**
518
+	 * Sets the headers that are based on the model and query params,
519
+	 * like the total records. This should only be called on the original request
520
+	 * from the client, not on subsequent internal
521
+	 *
522
+	 * @param EEM_Base $model
523
+	 * @param array    $query_params
524
+	 * @return void
525
+	 */
526
+	protected function setHeadersFromQueryParams($model, $query_params)
527
+	{
528
+		$this->setDebugInfo('model query params', $query_params);
529
+		$this->setDebugInfo(
530
+			'missing caps',
531
+			Capabilities::getMissingPermissionsString($model, $query_params['caps'])
532
+		);
533
+		// normally the limit to a 2-part array, where the 2nd item is the limit
534
+		if (! isset($query_params['limit'])) {
535
+			$query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
536
+		}
537
+		if (is_array($query_params['limit'])) {
538
+			$limit_parts = $query_params['limit'];
539
+		} else {
540
+			$limit_parts = explode(',', $query_params['limit']);
541
+			if (count($limit_parts) == 1) {
542
+				$limit_parts = array(0, $limit_parts[0]);
543
+			}
544
+		}
545
+		// remove the group by and having parts of the query, as those will
546
+		// make the sql query return an array of values, instead of just a single value
547
+		unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
548
+		$count = $model->count($query_params, null, true);
549
+		$pages = $count / $limit_parts[1];
550
+		$this->setResponseHeader('Total', $count, false);
551
+		$this->setResponseHeader('PageSize', $limit_parts[1], false);
552
+		$this->setResponseHeader('TotalPages', ceil($pages), false);
553
+	}
554
+
555
+
556
+	/**
557
+	 * Changes database results into REST API entities
558
+	 *
559
+	 * @param EEM_Base        $model
560
+	 * @param array           $db_row     like results from $wpdb->get_results()
561
+	 * @param WP_REST_Request $rest_request
562
+	 * @param string          $deprecated no longer used
563
+	 * @return array ready for being converted into json for sending to client
564
+	 */
565
+	public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
566
+	{
567
+		if (! $rest_request instanceof WP_REST_Request) {
568
+			// ok so this was called in the old style, where the 3rd arg was
569
+			// $include, and the 4th arg was $context
570
+			// now setup the request just to avoid fatal errors, although we won't be able
571
+			// to truly make use of it because it's kinda devoid of info
572
+			$rest_request = new WP_REST_Request();
573
+			$rest_request->set_param('include', $rest_request);
574
+			$rest_request->set_param('caps', $deprecated);
575
+		}
576
+		if ($rest_request->get_param('caps') == null) {
577
+			$rest_request->set_param('caps', EEM_Base::caps_read);
578
+		}
579
+		$entity_array = $this->createBareEntityFromWpdbResults($model, $db_row);
580
+		$entity_array = $this->addExtraFields($model, $db_row, $entity_array);
581
+		$entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array);
582
+		$entity_array['_calculated_fields'] = $this->getEntityCalculations($model, $db_row, $rest_request);
583
+		$entity_array = apply_filters(
584
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
585
+			$entity_array,
586
+			$model,
587
+			$rest_request->get_param('caps'),
588
+			$rest_request,
589
+			$this
590
+		);
591
+		$entity_array = $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row);
592
+		$entity_array = apply_filters(
593
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
594
+			$entity_array,
595
+			$model,
596
+			$rest_request->get_param('caps'),
597
+			$rest_request,
598
+			$this
599
+		);
600
+		$result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
601
+			$entity_array,
602
+			$model,
603
+			$rest_request->get_param('caps'),
604
+			$this->getModelVersionInfo(),
605
+			$model->get_index_primary_key_string(
606
+				$model->deduce_fields_n_values_from_cols_n_values($db_row)
607
+			)
608
+		);
609
+		$this->setDebugInfo(
610
+			'inaccessible fields',
611
+			array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
612
+		);
613
+		return apply_filters(
614
+			'FHEE__Read__create_entity_from_wpdb_results__entity_return',
615
+			$result_without_inaccessible_fields,
616
+			$model,
617
+			$rest_request->get_param('caps')
618
+		);
619
+	}
620
+
621
+
622
+	/**
623
+	 * Creates a REST entity array (JSON object we're going to return in the response, but
624
+	 * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
625
+	 * from $wpdb->get_row( $sql, ARRAY_A)
626
+	 *
627
+	 * @param EEM_Base $model
628
+	 * @param array    $db_row
629
+	 * @return array entity mostly ready for converting to JSON and sending in the response
630
+	 */
631
+	protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
632
+	{
633
+		$result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
634
+		$result = array_intersect_key(
635
+			$result,
636
+			$this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
637
+		);
638
+		// if this is a CPT, we need to set the global $post to it,
639
+		// otherwise shortcodes etc won't work properly while rendering it
640
+		if ($model instanceof \EEM_CPT_Base) {
641
+			$do_chevy_shuffle = true;
642
+		} else {
643
+			$do_chevy_shuffle = false;
644
+		}
645
+		if ($do_chevy_shuffle) {
646
+			global $post;
647
+			$old_post = $post;
648
+			$post = get_post($result[ $model->primary_key_name() ]);
649
+			if (! $post instanceof \WP_Post) {
650
+				// well that's weird, because $result is what we JUST fetched from the database
651
+				throw new RestException(
652
+					'error_fetching_post_from_database_results',
653
+					esc_html__(
654
+						'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
655
+						'event_espresso'
656
+					)
657
+				);
658
+			}
659
+			$model_object_classname = 'EE_' . $model->get_this_model_name();
660
+			$post->{$model_object_classname} = \EE_Registry::instance()->load_class(
661
+				$model_object_classname,
662
+				$result,
663
+				false,
664
+				false
665
+			);
666
+		}
667
+		foreach ($result as $field_name => $field_value) {
668
+			$field_obj = $model->field_settings_for($field_name);
669
+			if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
670
+				unset($result[ $field_name ]);
671
+			} elseif ($this->isSubclassOfOne(
672
+				$field_obj,
673
+				$this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
674
+			)
675
+			) {
676
+				$result[ $field_name ] = array(
677
+					'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
678
+					'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
679
+				);
680
+			} elseif ($this->isSubclassOfOne(
681
+				$field_obj,
682
+				$this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
683
+			)
684
+			) {
685
+				$result[ $field_name ] = array(
686
+					'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
687
+					'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
688
+				);
689
+			} elseif ($field_obj instanceof \EE_Datetime_Field) {
690
+				$field_value = $field_obj->prepare_for_set_from_db($field_value);
691
+				// if the value is null, but we're not supposed to permit null, then set to the field's default
692
+				if (is_null($field_value)) {
693
+					$field_value = $field_obj->getDefaultDateTimeObj();
694
+				}
695
+				if (is_null($field_value)) {
696
+					$gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson(
697
+						$field_obj,
698
+						$field_value,
699
+						$this->getModelVersionInfo()->requestedVersion()
700
+					);
701
+				} else {
702
+					$timezone = $field_value->getTimezone();
703
+					EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC'));
704
+					$gmt_date = ModelDataTranslator::prepareFieldValuesForJson(
705
+						$field_obj,
706
+						$field_value,
707
+						$this->getModelVersionInfo()->requestedVersion()
708
+					);
709
+					EEH_DTT_Helper::setTimezone($field_value, $timezone);
710
+					$local_date = ModelDataTranslator::prepareFieldValuesForJson(
711
+						$field_obj,
712
+						$field_value,
713
+						$this->getModelVersionInfo()->requestedVersion()
714
+					);
715
+				}
716
+				$result[ $field_name . '_gmt' ] = $gmt_date;
717
+				$result[ $field_name ] = $local_date;
718
+			} else {
719
+				$result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
720
+			}
721
+		}
722
+		if ($do_chevy_shuffle) {
723
+			$post = $old_post;
724
+		}
725
+		return $result;
726
+	}
727
+
728
+
729
+	/**
730
+	 * Takes a value all the way from the DB representation, to the model object's representation, to the
731
+	 * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
732
+	 * representation using $field_obj->prepare_for_set_from_db())
733
+	 *
734
+	 * @param EE_Model_Field_Base $field_obj
735
+	 * @param mixed               $value  as it's stored on a model object
736
+	 * @param string              $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
737
+	 * @return mixed
738
+	 * @throws ObjectDetectedException if $value contains a PHP object
739
+	 */
740
+	protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
741
+	{
742
+		$value = $field_obj->prepare_for_set_from_db($value);
743
+		switch ($format) {
744
+			case 'pretty':
745
+				$value = $field_obj->prepare_for_pretty_echoing($value);
746
+				break;
747
+			case 'normal':
748
+			default:
749
+				$value = $field_obj->prepare_for_get($value);
750
+				break;
751
+		}
752
+		return ModelDataTranslator::prepareFieldValuesForJson(
753
+			$field_obj,
754
+			$value,
755
+			$this->getModelVersionInfo()->requestedVersion()
756
+		);
757
+	}
758
+
759
+
760
+	/**
761
+	 * Adds a few extra fields to the entity response
762
+	 *
763
+	 * @param EEM_Base $model
764
+	 * @param array    $db_row
765
+	 * @param array    $entity_array
766
+	 * @return array modified entity
767
+	 */
768
+	protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
769
+	{
770
+		if ($model instanceof EEM_CPT_Base) {
771
+			$entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]);
772
+		}
773
+		return $entity_array;
774
+	}
775
+
776
+
777
+	/**
778
+	 * Gets links we want to add to the response
779
+	 *
780
+	 * @global \WP_REST_Server $wp_rest_server
781
+	 * @param EEM_Base         $model
782
+	 * @param array            $db_row
783
+	 * @param array            $entity_array
784
+	 * @return array the _links item in the entity
785
+	 */
786
+	protected function getEntityLinks($model, $db_row, $entity_array)
787
+	{
788
+		// add basic links
789
+		$links = array();
790
+		if ($model->has_primary_key_field()) {
791
+			$links['self'] = array(
792
+				array(
793
+					'href' => $this->getVersionedLinkTo(
794
+						EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
795
+						. '/'
796
+						. $entity_array[ $model->primary_key_name() ]
797
+					),
798
+				),
799
+			);
800
+		}
801
+		$links['collection'] = array(
802
+			array(
803
+				'href' => $this->getVersionedLinkTo(
804
+					EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
805
+				),
806
+			),
807
+		);
808
+		// add links to related models
809
+		if ($model->has_primary_key_field()) {
810
+			foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
811
+				$related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
812
+				$links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = array(
813
+					array(
814
+						'href'   => $this->getVersionedLinkTo(
815
+							EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
816
+							. '/'
817
+							. $entity_array[ $model->primary_key_name() ]
818
+							. '/'
819
+							. $related_model_part
820
+						),
821
+						'single' => $relation_obj instanceof EE_Belongs_To_Relation ? true : false,
822
+					),
823
+				);
824
+			}
825
+		}
826
+		return $links;
827
+	}
828
+
829
+
830
+	/**
831
+	 * Adds the included models indicated in the request to the entity provided
832
+	 *
833
+	 * @param EEM_Base        $model
834
+	 * @param WP_REST_Request $rest_request
835
+	 * @param array           $entity_array
836
+	 * @param array           $db_row
837
+	 * @return array the modified entity
838
+	 */
839
+	protected function includeRequestedModels(
840
+		EEM_Base $model,
841
+		WP_REST_Request $rest_request,
842
+		$entity_array,
843
+		$db_row = array()
844
+	) {
845
+		// if $db_row not included, hope the entity array has what we need
846
+		if (! $db_row) {
847
+			$db_row = $entity_array;
848
+		}
849
+		$includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
850
+		$includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
851
+		// if they passed in * or didn't specify any includes, return everything
852
+		if (! in_array('*', $includes_for_this_model)
853
+			&& ! empty($includes_for_this_model)
854
+		) {
855
+			if ($model->has_primary_key_field()) {
856
+				// always include the primary key. ya just gotta know that at least
857
+				$includes_for_this_model[] = $model->primary_key_name();
858
+			}
859
+			if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
860
+				$includes_for_this_model[] = '_calculated_fields';
861
+			}
862
+			$entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
863
+		}
864
+		$relation_settings = $this->getModelVersionInfo()->relationSettings($model);
865
+		foreach ($relation_settings as $relation_name => $relation_obj) {
866
+			$related_fields_to_include = $this->explodeAndGetItemsPrefixedWith(
867
+				$rest_request->get_param('include'),
868
+				$relation_name
869
+			);
870
+			$related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
871
+				$rest_request->get_param('calculate'),
872
+				$relation_name
873
+			);
874
+			// did they specify they wanted to include a related model, or
875
+			// specific fields from a related model?
876
+			// or did they specify to calculate a field from a related model?
877
+			if ($related_fields_to_include || $related_fields_to_calculate) {
878
+				// if so, we should include at least some part of the related model
879
+				$pretend_related_request = new WP_REST_Request();
880
+				$pretend_related_request->set_query_params(
881
+					array(
882
+						'caps'      => $rest_request->get_param('caps'),
883
+						'include'   => $related_fields_to_include,
884
+						'calculate' => $related_fields_to_calculate,
885
+					)
886
+				);
887
+				$pretend_related_request->add_header('no_rest_headers', true);
888
+				$primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
889
+					$model->get_index_primary_key_string(
890
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
891
+					)
892
+				);
893
+				$related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
894
+					$primary_model_query_params,
895
+					$relation_obj,
896
+					$pretend_related_request
897
+				);
898
+				$entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results
899
+																							 instanceof
900
+																							 WP_Error
901
+					? null
902
+					: $related_results;
903
+			}
904
+		}
905
+		return $entity_array;
906
+	}
907
+
908
+
909
+	/**
910
+	 * Returns a new array with all the names of models removed. Eg
911
+	 * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
912
+	 *
913
+	 * @param array $arr
914
+	 * @return array
915
+	 */
916
+	private function removeModelNamesFromArray($arr)
917
+	{
918
+		return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
919
+	}
920
+
921
+
922
+	/**
923
+	 * Gets the calculated fields for the response
924
+	 *
925
+	 * @param EEM_Base        $model
926
+	 * @param array           $wpdb_row
927
+	 * @param WP_REST_Request $rest_request
928
+	 * @return \stdClass the _calculations item in the entity
929
+	 * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
930
+	 * did, let's know about it ASAP, so let the exception bubble up)
931
+	 */
932
+	protected function getEntityCalculations($model, $wpdb_row, $rest_request)
933
+	{
934
+		$calculated_fields = $this->explodeAndGetItemsPrefixedWith(
935
+			$rest_request->get_param('calculate'),
936
+			''
937
+		);
938
+		// note: setting calculate=* doesn't do anything
939
+		$calculated_fields_to_return = new \stdClass();
940
+		foreach ($calculated_fields as $field_to_calculate) {
941
+			try {
942
+				$calculated_fields_to_return->$field_to_calculate = ModelDataTranslator::prepareFieldValueForJson(
943
+					null,
944
+					$this->fields_calculator->retrieveCalculatedFieldValue(
945
+						$model,
946
+						$field_to_calculate,
947
+						$wpdb_row,
948
+						$rest_request,
949
+						$this
950
+					),
951
+					$this->getModelVersionInfo()->requestedVersion()
952
+				);
953
+			} catch (RestException $e) {
954
+				// if we don't have permission to read it, just leave it out. but let devs know about the problem
955
+				$this->setResponseHeader(
956
+					'Notices-Field-Calculation-Errors['
957
+					. $e->getStringCode()
958
+					. ']['
959
+					. $model->get_this_model_name()
960
+					. ']['
961
+					. $field_to_calculate
962
+					. ']',
963
+					$e->getMessage(),
964
+					true
965
+				);
966
+			}
967
+		}
968
+		return $calculated_fields_to_return;
969
+	}
970
+
971
+
972
+	/**
973
+	 * Gets the full URL to the resource, taking the requested version into account
974
+	 *
975
+	 * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
976
+	 * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
977
+	 */
978
+	public function getVersionedLinkTo($link_part_after_version_and_slash)
979
+	{
980
+		return rest_url(
981
+			EED_Core_Rest_Api::get_versioned_route_to(
982
+				$link_part_after_version_and_slash,
983
+				$this->getModelVersionInfo()->requestedVersion()
984
+			)
985
+		);
986
+	}
987
+
988
+
989
+	/**
990
+	 * Gets the correct lowercase name for the relation in the API according
991
+	 * to the relation's type
992
+	 *
993
+	 * @param string                  $relation_name
994
+	 * @param \EE_Model_Relation_Base $relation_obj
995
+	 * @return string
996
+	 */
997
+	public static function getRelatedEntityName($relation_name, $relation_obj)
998
+	{
999
+		if ($relation_obj instanceof EE_Belongs_To_Relation) {
1000
+			return strtolower($relation_name);
1001
+		} else {
1002
+			return EEH_Inflector::pluralize_and_lower($relation_name);
1003
+		}
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * Gets the one model object with the specified id for the specified model
1009
+	 *
1010
+	 * @param EEM_Base        $model
1011
+	 * @param WP_REST_Request $request
1012
+	 * @return array|WP_Error
1013
+	 */
1014
+	public function getEntityFromModel($model, $request)
1015
+	{
1016
+		$context = $this->validateContext($request->get_param('caps'));
1017
+		return $this->getOneOrReportPermissionError($model, $request, $context);
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * If a context is provided which isn't valid, maybe it was added in a future
1023
+	 * version so just treat it as a default read
1024
+	 *
1025
+	 * @param string $context
1026
+	 * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1027
+	 */
1028
+	public function validateContext($context)
1029
+	{
1030
+		if (! $context) {
1031
+			$context = EEM_Base::caps_read;
1032
+		}
1033
+		$valid_contexts = EEM_Base::valid_cap_contexts();
1034
+		if (in_array($context, $valid_contexts)) {
1035
+			return $context;
1036
+		} else {
1037
+			return EEM_Base::caps_read;
1038
+		}
1039
+	}
1040
+
1041
+
1042
+	/**
1043
+	 * Verifies the passed in value is an allowable default where conditions value.
1044
+	 *
1045
+	 * @param $default_query_params
1046
+	 * @return string
1047
+	 */
1048
+	public function validateDefaultQueryParams($default_query_params)
1049
+	{
1050
+		$valid_default_where_conditions_for_api_calls = array(
1051
+			EEM_Base::default_where_conditions_all,
1052
+			EEM_Base::default_where_conditions_minimum_all,
1053
+			EEM_Base::default_where_conditions_minimum_others,
1054
+		);
1055
+		if (! $default_query_params) {
1056
+			$default_query_params = EEM_Base::default_where_conditions_all;
1057
+		}
1058
+		if (in_array(
1059
+			$default_query_params,
1060
+			$valid_default_where_conditions_for_api_calls,
1061
+			true
1062
+		)) {
1063
+			return $default_query_params;
1064
+		} else {
1065
+			return EEM_Base::default_where_conditions_all;
1066
+		}
1067
+	}
1068
+
1069
+
1070
+	/**
1071
+	 * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1072
+	 * Note: right now the query parameter keys for fields (and related fields)
1073
+	 * can be left as-is, but it's quite possible this will change someday.
1074
+	 * Also, this method's contents might be candidate for moving to Model_Data_Translator
1075
+	 *
1076
+	 * @param EEM_Base $model
1077
+	 * @param array    $query_parameters  from $_GET parameter @see Read:handle_request_get_all
1078
+	 * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1079
+	 *                                    that absolutely no results should be returned
1080
+	 * @throws EE_Error
1081
+	 * @throws RestException
1082
+	 */
1083
+	public function createModelQueryParams($model, $query_parameters)
1084
+	{
1085
+		$model_query_params = array();
1086
+		if (isset($query_parameters['where'])) {
1087
+			$model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1088
+				$query_parameters['where'],
1089
+				$model,
1090
+				$this->getModelVersionInfo()->requestedVersion()
1091
+			);
1092
+		}
1093
+		if (isset($query_parameters['order_by'])) {
1094
+			$order_by = $query_parameters['order_by'];
1095
+		} elseif (isset($query_parameters['orderby'])) {
1096
+			$order_by = $query_parameters['orderby'];
1097
+		} else {
1098
+			$order_by = null;
1099
+		}
1100
+		if ($order_by !== null) {
1101
+			if (is_array($order_by)) {
1102
+				$order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1103
+			} else {
1104
+				// it's a single item
1105
+				$order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1106
+			}
1107
+			$model_query_params['order_by'] = $order_by;
1108
+		}
1109
+		if (isset($query_parameters['group_by'])) {
1110
+			$group_by = $query_parameters['group_by'];
1111
+		} elseif (isset($query_parameters['groupby'])) {
1112
+			$group_by = $query_parameters['groupby'];
1113
+		} else {
1114
+			$group_by = array_keys($model->get_combined_primary_key_fields());
1115
+		}
1116
+		// make sure they're all real names
1117
+		if (is_array($group_by)) {
1118
+			$group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1119
+		}
1120
+		if ($group_by !== null) {
1121
+			$model_query_params['group_by'] = $group_by;
1122
+		}
1123
+		if (isset($query_parameters['having'])) {
1124
+			$model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1125
+				$query_parameters['having'],
1126
+				$model,
1127
+				$this->getModelVersionInfo()->requestedVersion()
1128
+			);
1129
+		}
1130
+		if (isset($query_parameters['order'])) {
1131
+			$model_query_params['order'] = $query_parameters['order'];
1132
+		}
1133
+		if (isset($query_parameters['mine'])) {
1134
+			$model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1135
+		}
1136
+		if (isset($query_parameters['limit'])) {
1137
+			// limit should be either a string like '23' or '23,43', or an array with two items in it
1138
+			if (! is_array($query_parameters['limit'])) {
1139
+				$limit_array = explode(',', (string) $query_parameters['limit']);
1140
+			} else {
1141
+				$limit_array = $query_parameters['limit'];
1142
+			}
1143
+			$sanitized_limit = array();
1144
+			foreach ($limit_array as $key => $limit_part) {
1145
+				if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1146
+					throw new EE_Error(
1147
+						sprintf(
1148
+							__(
1149
+							// @codingStandardsIgnoreStart
1150
+								'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1151
+								// @codingStandardsIgnoreEnd
1152
+								'event_espresso'
1153
+							),
1154
+							wp_json_encode($query_parameters['limit'])
1155
+						)
1156
+					);
1157
+				}
1158
+				$sanitized_limit[] = (int) $limit_part;
1159
+			}
1160
+			$model_query_params['limit'] = implode(',', $sanitized_limit);
1161
+		} else {
1162
+			$model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1163
+		}
1164
+		if (isset($query_parameters['caps'])) {
1165
+			$model_query_params['caps'] = $this->validateContext($query_parameters['caps']);
1166
+		} else {
1167
+			$model_query_params['caps'] = EEM_Base::caps_read;
1168
+		}
1169
+		if (isset($query_parameters['default_where_conditions'])) {
1170
+			$model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1171
+				$query_parameters['default_where_conditions']
1172
+			);
1173
+		}
1174
+		return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Changes the REST-style query params for use in the models
1180
+	 *
1181
+	 * @deprecated
1182
+	 * @param EEM_Base $model
1183
+	 * @param array    $query_params sub-array from @see EEM_Base::get_all()
1184
+	 * @return array
1185
+	 */
1186
+	public function prepareRestQueryParamsKeyForModels($model, $query_params)
1187
+	{
1188
+		$model_ready_query_params = array();
1189
+		foreach ($query_params as $key => $value) {
1190
+			if (is_array($value)) {
1191
+				$model_ready_query_params[ $key ] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1192
+			} else {
1193
+				$model_ready_query_params[ $key ] = $value;
1194
+			}
1195
+		}
1196
+		return $model_ready_query_params;
1197
+	}
1198
+
1199
+
1200
+	/**
1201
+	 * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1202
+	 * @param $model
1203
+	 * @param $query_params
1204
+	 * @return array
1205
+	 */
1206
+	public function prepareRestQueryParamsValuesForModels($model, $query_params)
1207
+	{
1208
+		$model_ready_query_params = array();
1209
+		foreach ($query_params as $key => $value) {
1210
+			if (is_array($value)) {
1211
+				$model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1212
+			} else {
1213
+				$model_ready_query_params[ $key ] = $value;
1214
+			}
1215
+		}
1216
+		return $model_ready_query_params;
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 * Explodes the string on commas, and only returns items with $prefix followed by a period.
1222
+	 * If no prefix is specified, returns items with no period.
1223
+	 *
1224
+	 * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1225
+	 * @param string       $prefix            "Event" or "foobar"
1226
+	 * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1227
+	 *                                        we only return strings starting with that and a period; if no prefix was
1228
+	 *                                        specified we return all items containing NO periods
1229
+	 */
1230
+	public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1231
+	{
1232
+		if (is_string($string_to_explode)) {
1233
+			$exploded_contents = explode(',', $string_to_explode);
1234
+		} elseif (is_array($string_to_explode)) {
1235
+			$exploded_contents = $string_to_explode;
1236
+		} else {
1237
+			$exploded_contents = array();
1238
+		}
1239
+		// if the string was empty, we want an empty array
1240
+		$exploded_contents = array_filter($exploded_contents);
1241
+		$contents_with_prefix = array();
1242
+		foreach ($exploded_contents as $item) {
1243
+			$item = trim($item);
1244
+			// if no prefix was provided, so we look for items with no "." in them
1245
+			if (! $prefix) {
1246
+				// does this item have a period?
1247
+				if (strpos($item, '.') === false) {
1248
+					// if not, then its what we're looking for
1249
+					$contents_with_prefix[] = $item;
1250
+				}
1251
+			} elseif (strpos($item, $prefix . '.') === 0) {
1252
+				// this item has the prefix and a period, grab it
1253
+				$contents_with_prefix[] = substr(
1254
+					$item,
1255
+					strpos($item, $prefix . '.') + strlen($prefix . '.')
1256
+				);
1257
+			} elseif ($item === $prefix) {
1258
+				// this item is JUST the prefix
1259
+				// so let's grab everything after, which is a blank string
1260
+				$contents_with_prefix[] = '';
1261
+			}
1262
+		}
1263
+		return $contents_with_prefix;
1264
+	}
1265
+
1266
+
1267
+	/**
1268
+	 * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1269
+	 * Deprecated because its return values were really quite confusing- sometimes it returned
1270
+	 * an empty array (when the include string was blank or '*') or sometimes it returned
1271
+	 * array('*') (when you provided a model and a model of that kind was found).
1272
+	 * Parses the $include_string so we fetch all the field names relating to THIS model
1273
+	 * (ie have NO period in them), or for the provided model (ie start with the model
1274
+	 * name and then a period).
1275
+	 * @param string $include_string @see Read:handle_request_get_all
1276
+	 * @param string $model_name
1277
+	 * @return array of fields for this model. If $model_name is provided, then
1278
+	 *                               the fields for that model, with the model's name removed from each.
1279
+	 *                               If $include_string was blank or '*' returns an empty array
1280
+	 */
1281
+	public function extractIncludesForThisModel($include_string, $model_name = null)
1282
+	{
1283
+		if (is_array($include_string)) {
1284
+			$include_string = implode(',', $include_string);
1285
+		}
1286
+		if ($include_string === '*' || $include_string === '') {
1287
+			return array();
1288
+		}
1289
+		$includes = explode(',', $include_string);
1290
+		$extracted_fields_to_include = array();
1291
+		if ($model_name) {
1292
+			foreach ($includes as $field_to_include) {
1293
+				$field_to_include = trim($field_to_include);
1294
+				if (strpos($field_to_include, $model_name . '.') === 0) {
1295
+					// found the model name at the exact start
1296
+					$field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1297
+					$extracted_fields_to_include[] = $field_sans_model_name;
1298
+				} elseif ($field_to_include == $model_name) {
1299
+					$extracted_fields_to_include[] = '*';
1300
+				}
1301
+			}
1302
+		} else {
1303
+			// look for ones with no period
1304
+			foreach ($includes as $field_to_include) {
1305
+				$field_to_include = trim($field_to_include);
1306
+				if (strpos($field_to_include, '.') === false
1307
+					&& ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1308
+				) {
1309
+					$extracted_fields_to_include[] = $field_to_include;
1310
+				}
1311
+			}
1312
+		}
1313
+		return $extracted_fields_to_include;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Gets the single item using the model according to the request in the context given, otherwise
1319
+	 * returns that it's inaccessible to the current user
1320
+	 *
1321
+	 * @param EEM_Base        $model
1322
+	 * @param WP_REST_Request $request
1323
+	 * @param null            $context
1324
+	 * @return array|WP_Error
1325
+	 */
1326
+	public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1327
+	{
1328
+		$query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
1329
+		if ($model instanceof \EEM_Soft_Delete_Base) {
1330
+			$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1331
+		}
1332
+		$restricted_query_params = $query_params;
1333
+		$restricted_query_params['caps'] = $context;
1334
+		$this->setDebugInfo('model query params', $restricted_query_params);
1335
+		$model_rows = $model->get_all_wpdb_results($restricted_query_params);
1336
+		if (! empty($model_rows)) {
1337
+			return $this->createEntityFromWpdbResult(
1338
+				$model,
1339
+				array_shift($model_rows),
1340
+				$request
1341
+			);
1342
+		} else {
1343
+			// ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1344
+			$lowercase_model_name = strtolower($model->get_this_model_name());
1345
+			$model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1346
+			if (! empty($model_rows_found_sans_restrictions)) {
1347
+				// you got shafted- it existed but we didn't want to tell you!
1348
+				return new WP_Error(
1349
+					'rest_user_cannot_' . $context,
1350
+					sprintf(
1351
+						__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1352
+						$context,
1353
+						strtolower($model->get_this_model_name()),
1354
+						Capabilities::getMissingPermissionsString(
1355
+							$model,
1356
+							$context
1357
+						)
1358
+					),
1359
+					array('status' => 403)
1360
+				);
1361
+			} else {
1362
+				// it's not you. It just doesn't exist
1363
+				return new WP_Error(
1364
+					sprintf('rest_%s_invalid_id', $lowercase_model_name),
1365
+					sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1366
+					array('status' => 404)
1367
+				);
1368
+			}
1369
+		}
1370
+	}
1371 1371
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelDataTranslator.php 1 patch
Indentation   +832 added lines, -832 removed lines patch added patch discarded remove patch
@@ -32,836 +32,836 @@
 block discarded – undo
32 32
 class ModelDataTranslator
33 33
 {
34 34
 
35
-    /**
36
-     * We used to use -1 for infinity in the rest api, but that's ambiguous for
37
-     * fields that COULD contain -1; so we use null
38
-     */
39
-    const EE_INF_IN_REST = null;
40
-
41
-
42
-    /**
43
-     * Prepares a possible array of input values from JSON for use by the models
44
-     *
45
-     * @param EE_Model_Field_Base $field_obj
46
-     * @param mixed               $original_value_maybe_array
47
-     * @param string              $requested_version
48
-     * @param string              $timezone_string treat values as being in this timezone
49
-     * @return mixed
50
-     * @throws RestException
51
-     */
52
-    public static function prepareFieldValuesFromJson(
53
-        $field_obj,
54
-        $original_value_maybe_array,
55
-        $requested_version,
56
-        $timezone_string = 'UTC'
57
-    ) {
58
-        if (is_array($original_value_maybe_array)
59
-            && ! $field_obj instanceof EE_Serialized_Text_Field
60
-        ) {
61
-            $new_value_maybe_array = array();
62
-            foreach ($original_value_maybe_array as $array_key => $array_item) {
63
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
64
-                    $field_obj,
65
-                    $array_item,
66
-                    $requested_version,
67
-                    $timezone_string
68
-                );
69
-            }
70
-        } else {
71
-            $new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
72
-                $field_obj,
73
-                $original_value_maybe_array,
74
-                $requested_version,
75
-                $timezone_string
76
-            );
77
-        }
78
-        return $new_value_maybe_array;
79
-    }
80
-
81
-
82
-    /**
83
-     * Prepares an array of field values FOR use in JSON/REST API
84
-     *
85
-     * @param EE_Model_Field_Base $field_obj
86
-     * @param mixed               $original_value_maybe_array
87
-     * @param string              $request_version (eg 4.8.36)
88
-     * @return array
89
-     */
90
-    public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
91
-    {
92
-        if (is_array($original_value_maybe_array)) {
93
-            $new_value = array();
94
-            foreach ($original_value_maybe_array as $key => $value) {
95
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
96
-                    $field_obj,
97
-                    $value,
98
-                    $request_version
99
-                );
100
-            }
101
-        } else {
102
-            $new_value = ModelDataTranslator::prepareFieldValueForJson(
103
-                $field_obj,
104
-                $original_value_maybe_array,
105
-                $request_version
106
-            );
107
-        }
108
-        return $new_value;
109
-    }
110
-
111
-
112
-    /**
113
-     * Prepares incoming data from the json or $_REQUEST parameters for the models'
114
-     * "$query_params".
115
-     *
116
-     * @param EE_Model_Field_Base $field_obj
117
-     * @param mixed               $original_value
118
-     * @param string              $requested_version
119
-     * @param string              $timezone_string treat values as being in this timezone
120
-     * @return mixed
121
-     * @throws RestException
122
-     * @throws DomainException
123
-     * @throws EE_Error
124
-     */
125
-    public static function prepareFieldValueFromJson(
126
-        $field_obj,
127
-        $original_value,
128
-        $requested_version,
129
-        $timezone_string = 'UTC' // UTC
130
-    ) {
131
-        // check if they accidentally submitted an error value. If so throw an exception
132
-        if (is_array($original_value)
133
-            && isset($original_value['error_code'], $original_value['error_message'])) {
134
-            throw new RestException(
135
-                'rest_submitted_error_value',
136
-                sprintf(
137
-                    esc_html__(
138
-                        'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
139
-                        'event_espresso'
140
-                    ),
141
-                    $field_obj->get_name()
142
-                ),
143
-                array(
144
-                    'status' => 400,
145
-                )
146
-            );
147
-        }
148
-        // double-check for serialized PHP. We never accept serialized PHP. No way Jose.
149
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
150
-        $timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
151
-        $new_value = null;
152
-        // walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
153
-        // way Jose.
154
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
155
-        if ($field_obj instanceof EE_Infinite_Integer_Field
156
-            && in_array($original_value, array(null, ''), true)
157
-        ) {
158
-            $new_value = EE_INF;
159
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
160
-            $new_value = rest_parse_date(
161
-                self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
162
-            );
163
-            if ($new_value === false) {
164
-                throw new RestException(
165
-                    'invalid_format_for_timestamp',
166
-                    sprintf(
167
-                        esc_html__(
168
-                            'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
169
-                            'event_espresso'
170
-                        ),
171
-                        'RFC3339',
172
-                        'ISO8601',
173
-                        $original_value
174
-                    ),
175
-                    array(
176
-                        'status' => 400,
177
-                    )
178
-                );
179
-            }
180
-        } else {
181
-            $new_value = $original_value;
182
-        }
183
-        return $new_value;
184
-    }
185
-
186
-
187
-    /**
188
-     * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
189
-     * information via details obtained from the host site.
190
-     *
191
-     * @param string            $original_timestamp
192
-     * @param EE_Datetime_Field $datetime_field
193
-     * @param                   $timezone_string
194
-     * @return string
195
-     * @throws DomainException
196
-     */
197
-    private static function getTimestampWithTimezoneOffset(
198
-        $original_timestamp,
199
-        EE_Datetime_Field $datetime_field,
200
-        $timezone_string
201
-    ) {
202
-        // already have timezone information?
203
-        if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
204
-            // yes, we're ignoring the timezone.
205
-            return $original_timestamp;
206
-        }
207
-        // need to append timezone
208
-        list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
209
-            $datetime_field->get_timezone_offset(
210
-                new \DateTimeZone($timezone_string),
211
-                $original_timestamp
212
-            )
213
-        );
214
-        $offset_string =
215
-            str_pad(
216
-                floor($offset_secs / HOUR_IN_SECONDS),
217
-                2,
218
-                '0',
219
-                STR_PAD_LEFT
220
-            )
221
-            . ':'
222
-            . str_pad(
223
-                ($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
224
-                2,
225
-                '0',
226
-                STR_PAD_LEFT
227
-            );
228
-        return $original_timestamp . $offset_sign . $offset_string;
229
-    }
230
-
231
-
232
-    /**
233
-     * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
234
-     * think that can happen). If $data is an array, recurses into its keys and values
235
-     *
236
-     * @param mixed $data
237
-     * @throws RestException
238
-     * @return void
239
-     */
240
-    public static function throwExceptionIfContainsSerializedData($data)
241
-    {
242
-        if (is_array($data)) {
243
-            foreach ($data as $key => $value) {
244
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
245
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
246
-            }
247
-        } else {
248
-            if (is_serialized($data) || is_object($data)) {
249
-                throw new RestException(
250
-                    'serialized_data_submission_prohibited',
251
-                    esc_html__(
252
-                    // @codingStandardsIgnoreStart
253
-                        'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
254
-                        // @codingStandardsIgnoreEnd
255
-                        'event_espresso'
256
-                    )
257
-                );
258
-            }
259
-        }
260
-    }
261
-
262
-
263
-    /**
264
-     * determines what's going on with them timezone strings
265
-     *
266
-     * @param int $timezone_offset
267
-     * @return array
268
-     */
269
-    private static function parseTimezoneOffset($timezone_offset)
270
-    {
271
-        $first_char = substr((string) $timezone_offset, 0, 1);
272
-        if ($first_char === '+' || $first_char === '-') {
273
-            $offset_sign = $first_char;
274
-            $offset_secs = substr((string) $timezone_offset, 1);
275
-        } else {
276
-            $offset_sign = '+';
277
-            $offset_secs = $timezone_offset;
278
-        }
279
-        return array($offset_sign, $offset_secs);
280
-    }
281
-
282
-
283
-    /**
284
-     * Prepares a field's value for display in the API
285
-     *
286
-     * @param EE_Model_Field_Base $field_obj
287
-     * @param mixed               $original_value
288
-     * @param string              $requested_version
289
-     * @return mixed
290
-     */
291
-    public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
292
-    {
293
-        if ($original_value === EE_INF) {
294
-            $new_value = ModelDataTranslator::EE_INF_IN_REST;
295
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
296
-            if (is_string($original_value)) {
297
-                // did they submit a string of a unix timestamp?
298
-                if (is_numeric($original_value)) {
299
-                    $datetime_obj = new \DateTime();
300
-                    $datetime_obj->setTimestamp((int) $original_value);
301
-                } else {
302
-                    // first, check if its a MySQL timestamp in GMT
303
-                    $datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
304
-                }
305
-                if (! $datetime_obj instanceof \DateTime) {
306
-                    // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
307
-                    $datetime_obj = $field_obj->prepare_for_set($original_value);
308
-                }
309
-                $original_value = $datetime_obj;
310
-            }
311
-            if ($original_value instanceof \DateTime) {
312
-                $new_value = $original_value->format('Y-m-d H:i:s');
313
-            } elseif (is_int($original_value) || is_float($original_value)) {
314
-                $new_value = date('Y-m-d H:i:s', $original_value);
315
-            } elseif ($original_value === null || $original_value === '') {
316
-                $new_value = null;
317
-            } else {
318
-                // so it's not a datetime object, unix timestamp (as string or int),
319
-                // MySQL timestamp, or even a string in the field object's format. So no idea what it is
320
-                throw new \EE_Error(
321
-                    sprintf(
322
-                        esc_html__(
323
-                        // @codingStandardsIgnoreStart
324
-                            'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
325
-                            // @codingStandardsIgnoreEnd
326
-                            'event_espresso'
327
-                        ),
328
-                        $original_value,
329
-                        $field_obj->get_name(),
330
-                        $field_obj->get_model_name(),
331
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
332
-                    )
333
-                );
334
-            }
335
-            if ($new_value !== null) {
336
-                $new_value = mysql_to_rfc3339($new_value);
337
-            }
338
-        } else {
339
-            $new_value = $original_value;
340
-        }
341
-        // are we about to send an object? just don't. We have no good way to represent it in JSON.
342
-        // can't just check using is_object() because that missed PHP incomplete objects
343
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
344
-            $new_value = array(
345
-                'error_code'    => 'php_object_not_return',
346
-                'error_message' => esc_html__(
347
-                    'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
348
-                    'event_espresso'
349
-                ),
350
-            );
351
-        }
352
-        return apply_filters(
353
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
354
-            $new_value,
355
-            $field_obj,
356
-            $original_value,
357
-            $requested_version
358
-        );
359
-    }
360
-
361
-
362
-    /**
363
-     * Prepares condition-query-parameters (like what's in where and having) from
364
-     * the format expected in the API to use in the models
365
-     *
366
-     * @param array    $inputted_query_params_of_this_type
367
-     * @param EEM_Base $model
368
-     * @param string   $requested_version
369
-     * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
370
-     *                          If we're writing to the DB, we don't expect any operators, or any logic query
371
-     *                          parameters, and we also won't accept serialized data unless the current user has
372
-     *                          unfiltered_html.
373
-     * @return array
374
-     * @throws DomainException
375
-     * @throws RestException
376
-     * @throws EE_Error
377
-     */
378
-    public static function prepareConditionsQueryParamsForModels(
379
-        $inputted_query_params_of_this_type,
380
-        EEM_Base $model,
381
-        $requested_version,
382
-        $writing = false
383
-    ) {
384
-        $query_param_for_models = array();
385
-        $valid_operators = $model->valid_operators();
386
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
387
-            $is_gmt_datetime_field = false;
388
-            $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
389
-                $query_param_key
390
-            );
391
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
392
-                $query_param_sans_stars,
393
-                $model
394
-            );
395
-            // double-check is it a *_gmt field?
396
-            if (! $field instanceof EE_Model_Field_Base
397
-                && ModelDataTranslator::isGmtDateFieldName($query_param_sans_stars)
398
-            ) {
399
-                // yep, take off '_gmt', and find the field
400
-                $query_param_key = ModelDataTranslator::removeGmtFromFieldName($query_param_sans_stars);
401
-                $field = ModelDataTranslator::deduceFieldFromQueryParam(
402
-                    $query_param_key,
403
-                    $model
404
-                );
405
-                $timezone = 'UTC';
406
-                $is_gmt_datetime_field = true;
407
-            } elseif ($field instanceof EE_Datetime_Field) {
408
-                // so it's not a GMT field. Set the timezone on the model to the default
409
-                $timezone = \EEH_DTT_Helper::get_valid_timezone_string();
410
-            } else {
411
-                // just keep using what's already set for the timezone
412
-                $timezone = $model->get_timezone();
413
-            }
414
-            if ($field instanceof EE_Model_Field_Base) {
415
-                if (! $writing && is_array($query_param_value)) {
416
-                    if (! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
417
-                        if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
418
-                            throw new RestException(
419
-                                'numerically_indexed_array_of_values_only',
420
-                                sprintf(
421
-                                    esc_html__(
422
-                                        'The array provided for the parameter "%1$s" should be numerically indexed.',
423
-                                        'event_espresso'
424
-                                    ),
425
-                                    $query_param_key
426
-                                ),
427
-                                array(
428
-                                    'status' => 400,
429
-                                )
430
-                            );
431
-                        }
432
-                    }
433
-                    // did they specify an operator?
434
-                    if (isset($query_param_value[0])
435
-                        && isset($valid_operators[ $query_param_value[0] ])
436
-                    ) {
437
-                        $op = $query_param_value[0];
438
-                        $translated_value = array($op);
439
-                        if (array_key_exists($op, $model->valid_in_style_operators())
440
-                            && isset($query_param_value[1])
441
-                            && ! isset($query_param_value[2])
442
-                        ) {
443
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
444
-                                $field,
445
-                                $query_param_value[1],
446
-                                $requested_version,
447
-                                $timezone
448
-                            );
449
-                        } elseif (array_key_exists($op, $model->valid_between_style_operators())
450
-                                  && isset($query_param_value[1])
451
-                                  && is_array($query_param_value[1])
452
-                                  && isset($query_param_key[1][0], $query_param_value[1][1])
453
-                                  && ! isset($query_param_value[1][2])
454
-                                  && ! isset($query_param_value[2])
455
-                        ) {
456
-                            $translated_value[] = array(
457
-                                ModelDataTranslator::prepareFieldValuesFromJson(
458
-                                    $field,
459
-                                    $query_param_value[1][0],
460
-                                    $requested_version,
461
-                                    $timezone
462
-                                ),
463
-                                ModelDataTranslator::prepareFieldValuesFromJson(
464
-                                    $field,
465
-                                    $query_param_value[1][1],
466
-                                    $requested_version,
467
-                                    $timezone
468
-                                )
469
-                            );
470
-                        } elseif (array_key_exists($op, $model->valid_like_style_operators())
471
-                                  && isset($query_param_value[1])
472
-                                  && ! isset($query_param_value[2])
473
-                        ) {
474
-                            // we want to leave this value mostly-as-is (eg don't force it to be a float
475
-                            // or a boolean or an enum value. Leave it as-is with wildcards etc)
476
-                            // but do verify it at least doesn't have any serialized data
477
-                            ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
478
-                            $translated_value[] = $query_param_value[1];
479
-                        } elseif (array_key_exists($op, $model->valid_null_style_operators())
480
-                                  && ! isset($query_param_value[1])) {
481
-                            // no arguments should have been provided, so don't look for any
482
-                        } elseif (isset($query_param_value[1])
483
-                                  && ! isset($query_param_value[2])
484
-                                  && ! array_key_exists(
485
-                                      $op,
486
-                                      array_merge(
487
-                                          $model->valid_in_style_operators(),
488
-                                          $model->valid_null_style_operators(),
489
-                                          $model->valid_like_style_operators(),
490
-                                          $model->valid_between_style_operators()
491
-                                      )
492
-                                  )
493
-                        ) {
494
-                            // it's a valid operator, but none of the exceptions. Treat it normally.
495
-                            $translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
496
-                                $field,
497
-                                $query_param_value[1],
498
-                                $requested_version,
499
-                                $timezone
500
-                            );
501
-                        } else {
502
-                            // so they provided a valid operator, but wrong number of arguments
503
-                            if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
504
-                                throw new RestException(
505
-                                    'wrong_number_of_arguments',
506
-                                    sprintf(
507
-                                        esc_html__(
508
-                                            'The operator you provided, "%1$s" had the wrong number of arguments',
509
-                                            'event_espresso'
510
-                                        ),
511
-                                        $op
512
-                                    ),
513
-                                    array(
514
-                                        'status' => 400,
515
-                                    )
516
-                                );
517
-                            }
518
-                            $translated_value = null;
519
-                        }
520
-                    } else {
521
-                        // so they didn't provide a valid operator
522
-                        if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
523
-                            throw new RestException(
524
-                                'invalid_operator',
525
-                                sprintf(
526
-                                    esc_html__(
527
-                                        'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
528
-                                        'event_espresso'
529
-                                    ),
530
-                                    $query_param_key,
531
-                                    $query_param_value
532
-                                ),
533
-                                array(
534
-                                    'status' => 400,
535
-                                )
536
-                            );
537
-                        }
538
-                        // if we aren't in debug mode, then just try our best to fulfill the user's request
539
-                        $translated_value = null;
540
-                    }
541
-                } else {
542
-                    $translated_value = ModelDataTranslator::prepareFieldValueFromJson(
543
-                        $field,
544
-                        $query_param_value,
545
-                        $requested_version,
546
-                        $timezone
547
-                    );
548
-                }
549
-                if ((isset($query_param_for_models[ $query_param_key ]) && $is_gmt_datetime_field)
550
-                    || $translated_value === null
551
-                ) {
552
-                    // they have already provided a non-gmt field, ignore the gmt one. That's what WP core
553
-                    // currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
554
-                    // OR we couldn't create a translated value from their input
555
-                    continue;
556
-                }
557
-                $query_param_for_models[ $query_param_key ] = $translated_value;
558
-            } else {
559
-                // so this param doesn't correspond to a field eh?
560
-                if ($writing) {
561
-                    // always tell API clients about invalid parameters when they're creating data. Otherwise,
562
-                    // they are probably going to create invalid data
563
-                    throw new RestException(
564
-                        'invalid_field',
565
-                        sprintf(
566
-                            esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
567
-                            $query_param_key
568
-                        )
569
-                    );
570
-                } else {
571
-                    // so it's not for a field, is it a logic query param key?
572
-                    if (in_array(
573
-                        $query_param_sans_stars,
574
-                        $model->logic_query_param_keys()
575
-                    )) {
576
-                        $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
577
-                            $query_param_value,
578
-                            $model,
579
-                            $requested_version
580
-                        );
581
-                    } elseif (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
582
-                        // only tell API clients they got it wrong if we're in debug mode
583
-                        // otherwise try our best ot fulfill their request by ignoring this invalid data
584
-                        throw new RestException(
585
-                            'invalid_parameter',
586
-                            sprintf(
587
-                                esc_html__(
588
-                                    'You provided an invalid parameter, with key "%1$s"',
589
-                                    'event_espresso'
590
-                                ),
591
-                                $query_param_sans_stars
592
-                            ),
593
-                            array(
594
-                                'status' => 400,
595
-                            )
596
-                        );
597
-                    }
598
-                }
599
-            }
600
-        }
601
-        return $query_param_for_models;
602
-    }
603
-
604
-
605
-    /**
606
-     * Mostly checks if the last 4 characters are "_gmt", indicating its a
607
-     * gmt date field name
608
-     *
609
-     * @param string $field_name
610
-     * @return boolean
611
-     */
612
-    public static function isGmtDateFieldName($field_name)
613
-    {
614
-        return substr(
615
-            ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
616
-            -4,
617
-            4
618
-        ) === '_gmt';
619
-    }
620
-
621
-
622
-    /**
623
-     * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
624
-     *
625
-     * @param string $field_name
626
-     * @return string
627
-     */
628
-    public static function removeGmtFromFieldName($field_name)
629
-    {
630
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
631
-            return $field_name;
632
-        }
633
-        $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
634
-            $field_name
635
-        );
636
-        $query_param_sans_gmt_and_sans_stars = substr(
637
-            $query_param_sans_stars,
638
-            0,
639
-            strrpos(
640
-                $field_name,
641
-                '_gmt'
642
-            )
643
-        );
644
-        return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
645
-    }
646
-
647
-
648
-    /**
649
-     * Takes a field name from the REST API and prepares it for the model querying
650
-     *
651
-     * @param string $field_name
652
-     * @return string
653
-     */
654
-    public static function prepareFieldNameFromJson($field_name)
655
-    {
656
-        if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
657
-            return ModelDataTranslator::removeGmtFromFieldName($field_name);
658
-        }
659
-        return $field_name;
660
-    }
661
-
662
-
663
-    /**
664
-     * Takes array of field names from REST API and prepares for models
665
-     *
666
-     * @param array $field_names
667
-     * @return array of field names (possibly include model prefixes)
668
-     */
669
-    public static function prepareFieldNamesFromJson(array $field_names)
670
-    {
671
-        $new_array = array();
672
-        foreach ($field_names as $key => $field_name) {
673
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
674
-        }
675
-        return $new_array;
676
-    }
677
-
678
-
679
-    /**
680
-     * Takes array where array keys are field names (possibly with model path prefixes)
681
-     * from the REST API and prepares them for model querying
682
-     *
683
-     * @param array $field_names_as_keys
684
-     * @return array
685
-     */
686
-    public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
687
-    {
688
-        $new_array = array();
689
-        foreach ($field_names_as_keys as $field_name => $value) {
690
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
691
-        }
692
-        return $new_array;
693
-    }
694
-
695
-
696
-    /**
697
-     * Prepares an array of model query params for use in the REST API
698
-     *
699
-     * @param array    $model_query_params
700
-     * @param EEM_Base $model
701
-     * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
702
-     *                                     REST API
703
-     * @return array which can be passed into the EE4 REST API when querying a model resource
704
-     * @throws EE_Error
705
-     */
706
-    public static function prepareQueryParamsForRestApi(
707
-        array $model_query_params,
708
-        EEM_Base $model,
709
-        $requested_version = null
710
-    ) {
711
-        if ($requested_version === null) {
712
-            $requested_version = \EED_Core_Rest_Api::latest_rest_api_version();
713
-        }
714
-        $rest_query_params = $model_query_params;
715
-        if (isset($model_query_params[0])) {
716
-            $rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
717
-                $model_query_params[0],
718
-                $model,
719
-                $requested_version
720
-            );
721
-            unset($rest_query_params[0]);
722
-        }
723
-        if (isset($model_query_params['having'])) {
724
-            $rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
725
-                $model_query_params['having'],
726
-                $model,
727
-                $requested_version
728
-            );
729
-        }
730
-        return apply_filters(
731
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
732
-            $rest_query_params,
733
-            $model_query_params,
734
-            $model,
735
-            $requested_version
736
-        );
737
-    }
738
-
739
-
740
-    /**
741
-     * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
742
-     *
743
-     * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
744
-     *                                                      passed into EEM_Base::get_all()
745
-     * @param EEM_Base $model
746
-     * @param string   $requested_version                   eg "4.8.36"
747
-     * @return array ready for use in the rest api query params
748
-     * @throws EE_Error
749
-     * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
750
-     *                                                      (which would be really unusual)
751
-     */
752
-    public static function prepareConditionsQueryParamsForRestApi(
753
-        $inputted_query_params_of_this_type,
754
-        EEM_Base $model,
755
-        $requested_version
756
-    ) {
757
-        $query_param_for_models = array();
758
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
759
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
760
-                ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
761
-                $model
762
-            );
763
-            if ($field instanceof EE_Model_Field_Base) {
764
-                // did they specify an operator?
765
-                if (is_array($query_param_value)) {
766
-                    $op = $query_param_value[0];
767
-                    $translated_value = array($op);
768
-                    if (isset($query_param_value[1])) {
769
-                        $value = $query_param_value[1];
770
-                        $translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
771
-                            $field,
772
-                            $value,
773
-                            $requested_version
774
-                        );
775
-                    }
776
-                } else {
777
-                    $translated_value = ModelDataTranslator::prepareFieldValueForJson(
778
-                        $field,
779
-                        $query_param_value,
780
-                        $requested_version
781
-                    );
782
-                }
783
-                $query_param_for_models[ $query_param_key ] = $translated_value;
784
-            } else {
785
-                // so it's not for a field, assume it's a logic query param key
786
-                $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
787
-                    $query_param_value,
788
-                    $model,
789
-                    $requested_version
790
-                );
791
-            }
792
-        }
793
-        return $query_param_for_models;
794
-    }
795
-
796
-
797
-    /**
798
-     * @param $condition_query_param_key
799
-     * @return string
800
-     */
801
-    public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
802
-    {
803
-        $pos_of_star = strpos($condition_query_param_key, '*');
804
-        if ($pos_of_star === false) {
805
-            return $condition_query_param_key;
806
-        } else {
807
-            $condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
808
-            return $condition_query_param_sans_star;
809
-        }
810
-    }
811
-
812
-
813
-    /**
814
-     * Takes the input parameter and finds the model field that it indicates.
815
-     *
816
-     * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
817
-     * @param EEM_Base $model
818
-     * @return EE_Model_Field_Base
819
-     * @throws EE_Error
820
-     */
821
-    public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
822
-    {
823
-        // ok, now proceed with deducing which part is the model's name, and which is the field's name
824
-        // which will help us find the database table and column
825
-        $query_param_parts = explode('.', $query_param_name);
826
-        if (empty($query_param_parts)) {
827
-            throw new EE_Error(
828
-                sprintf(
829
-                    __(
830
-                        '_extract_column_name is empty when trying to extract column and table name from %s',
831
-                        'event_espresso'
832
-                    ),
833
-                    $query_param_name
834
-                )
835
-            );
836
-        }
837
-        $number_of_parts = count($query_param_parts);
838
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
839
-        if ($number_of_parts === 1) {
840
-            $field_name = $last_query_param_part;
841
-        } else {// $number_of_parts >= 2
842
-            // the last part is the column name, and there are only 2parts. therefore...
843
-            $field_name = $last_query_param_part;
844
-            $model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
845
-        }
846
-        try {
847
-            return $model->field_settings_for($field_name, false);
848
-        } catch (EE_Error $e) {
849
-            return null;
850
-        }
851
-    }
852
-
853
-
854
-    /**
855
-     * Returns true if $data can be easily represented in JSON.
856
-     * Basically, objects and resources can't be represented in JSON easily.
857
-     *
858
-     * @param mixed $data
859
-     * @return bool
860
-     */
861
-    protected static function isRepresentableInJson($data)
862
-    {
863
-        return is_scalar($data)
864
-               || is_array($data)
865
-               || is_null($data);
866
-    }
35
+	/**
36
+	 * We used to use -1 for infinity in the rest api, but that's ambiguous for
37
+	 * fields that COULD contain -1; so we use null
38
+	 */
39
+	const EE_INF_IN_REST = null;
40
+
41
+
42
+	/**
43
+	 * Prepares a possible array of input values from JSON for use by the models
44
+	 *
45
+	 * @param EE_Model_Field_Base $field_obj
46
+	 * @param mixed               $original_value_maybe_array
47
+	 * @param string              $requested_version
48
+	 * @param string              $timezone_string treat values as being in this timezone
49
+	 * @return mixed
50
+	 * @throws RestException
51
+	 */
52
+	public static function prepareFieldValuesFromJson(
53
+		$field_obj,
54
+		$original_value_maybe_array,
55
+		$requested_version,
56
+		$timezone_string = 'UTC'
57
+	) {
58
+		if (is_array($original_value_maybe_array)
59
+			&& ! $field_obj instanceof EE_Serialized_Text_Field
60
+		) {
61
+			$new_value_maybe_array = array();
62
+			foreach ($original_value_maybe_array as $array_key => $array_item) {
63
+				$new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
64
+					$field_obj,
65
+					$array_item,
66
+					$requested_version,
67
+					$timezone_string
68
+				);
69
+			}
70
+		} else {
71
+			$new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
72
+				$field_obj,
73
+				$original_value_maybe_array,
74
+				$requested_version,
75
+				$timezone_string
76
+			);
77
+		}
78
+		return $new_value_maybe_array;
79
+	}
80
+
81
+
82
+	/**
83
+	 * Prepares an array of field values FOR use in JSON/REST API
84
+	 *
85
+	 * @param EE_Model_Field_Base $field_obj
86
+	 * @param mixed               $original_value_maybe_array
87
+	 * @param string              $request_version (eg 4.8.36)
88
+	 * @return array
89
+	 */
90
+	public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
91
+	{
92
+		if (is_array($original_value_maybe_array)) {
93
+			$new_value = array();
94
+			foreach ($original_value_maybe_array as $key => $value) {
95
+				$new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
96
+					$field_obj,
97
+					$value,
98
+					$request_version
99
+				);
100
+			}
101
+		} else {
102
+			$new_value = ModelDataTranslator::prepareFieldValueForJson(
103
+				$field_obj,
104
+				$original_value_maybe_array,
105
+				$request_version
106
+			);
107
+		}
108
+		return $new_value;
109
+	}
110
+
111
+
112
+	/**
113
+	 * Prepares incoming data from the json or $_REQUEST parameters for the models'
114
+	 * "$query_params".
115
+	 *
116
+	 * @param EE_Model_Field_Base $field_obj
117
+	 * @param mixed               $original_value
118
+	 * @param string              $requested_version
119
+	 * @param string              $timezone_string treat values as being in this timezone
120
+	 * @return mixed
121
+	 * @throws RestException
122
+	 * @throws DomainException
123
+	 * @throws EE_Error
124
+	 */
125
+	public static function prepareFieldValueFromJson(
126
+		$field_obj,
127
+		$original_value,
128
+		$requested_version,
129
+		$timezone_string = 'UTC' // UTC
130
+	) {
131
+		// check if they accidentally submitted an error value. If so throw an exception
132
+		if (is_array($original_value)
133
+			&& isset($original_value['error_code'], $original_value['error_message'])) {
134
+			throw new RestException(
135
+				'rest_submitted_error_value',
136
+				sprintf(
137
+					esc_html__(
138
+						'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
139
+						'event_espresso'
140
+					),
141
+					$field_obj->get_name()
142
+				),
143
+				array(
144
+					'status' => 400,
145
+				)
146
+			);
147
+		}
148
+		// double-check for serialized PHP. We never accept serialized PHP. No way Jose.
149
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
150
+		$timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
151
+		$new_value = null;
152
+		// walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
153
+		// way Jose.
154
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
155
+		if ($field_obj instanceof EE_Infinite_Integer_Field
156
+			&& in_array($original_value, array(null, ''), true)
157
+		) {
158
+			$new_value = EE_INF;
159
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
160
+			$new_value = rest_parse_date(
161
+				self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
162
+			);
163
+			if ($new_value === false) {
164
+				throw new RestException(
165
+					'invalid_format_for_timestamp',
166
+					sprintf(
167
+						esc_html__(
168
+							'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
169
+							'event_espresso'
170
+						),
171
+						'RFC3339',
172
+						'ISO8601',
173
+						$original_value
174
+					),
175
+					array(
176
+						'status' => 400,
177
+					)
178
+				);
179
+			}
180
+		} else {
181
+			$new_value = $original_value;
182
+		}
183
+		return $new_value;
184
+	}
185
+
186
+
187
+	/**
188
+	 * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
189
+	 * information via details obtained from the host site.
190
+	 *
191
+	 * @param string            $original_timestamp
192
+	 * @param EE_Datetime_Field $datetime_field
193
+	 * @param                   $timezone_string
194
+	 * @return string
195
+	 * @throws DomainException
196
+	 */
197
+	private static function getTimestampWithTimezoneOffset(
198
+		$original_timestamp,
199
+		EE_Datetime_Field $datetime_field,
200
+		$timezone_string
201
+	) {
202
+		// already have timezone information?
203
+		if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
204
+			// yes, we're ignoring the timezone.
205
+			return $original_timestamp;
206
+		}
207
+		// need to append timezone
208
+		list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
209
+			$datetime_field->get_timezone_offset(
210
+				new \DateTimeZone($timezone_string),
211
+				$original_timestamp
212
+			)
213
+		);
214
+		$offset_string =
215
+			str_pad(
216
+				floor($offset_secs / HOUR_IN_SECONDS),
217
+				2,
218
+				'0',
219
+				STR_PAD_LEFT
220
+			)
221
+			. ':'
222
+			. str_pad(
223
+				($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
224
+				2,
225
+				'0',
226
+				STR_PAD_LEFT
227
+			);
228
+		return $original_timestamp . $offset_sign . $offset_string;
229
+	}
230
+
231
+
232
+	/**
233
+	 * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
234
+	 * think that can happen). If $data is an array, recurses into its keys and values
235
+	 *
236
+	 * @param mixed $data
237
+	 * @throws RestException
238
+	 * @return void
239
+	 */
240
+	public static function throwExceptionIfContainsSerializedData($data)
241
+	{
242
+		if (is_array($data)) {
243
+			foreach ($data as $key => $value) {
244
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
245
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
246
+			}
247
+		} else {
248
+			if (is_serialized($data) || is_object($data)) {
249
+				throw new RestException(
250
+					'serialized_data_submission_prohibited',
251
+					esc_html__(
252
+					// @codingStandardsIgnoreStart
253
+						'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
254
+						// @codingStandardsIgnoreEnd
255
+						'event_espresso'
256
+					)
257
+				);
258
+			}
259
+		}
260
+	}
261
+
262
+
263
+	/**
264
+	 * determines what's going on with them timezone strings
265
+	 *
266
+	 * @param int $timezone_offset
267
+	 * @return array
268
+	 */
269
+	private static function parseTimezoneOffset($timezone_offset)
270
+	{
271
+		$first_char = substr((string) $timezone_offset, 0, 1);
272
+		if ($first_char === '+' || $first_char === '-') {
273
+			$offset_sign = $first_char;
274
+			$offset_secs = substr((string) $timezone_offset, 1);
275
+		} else {
276
+			$offset_sign = '+';
277
+			$offset_secs = $timezone_offset;
278
+		}
279
+		return array($offset_sign, $offset_secs);
280
+	}
281
+
282
+
283
+	/**
284
+	 * Prepares a field's value for display in the API
285
+	 *
286
+	 * @param EE_Model_Field_Base $field_obj
287
+	 * @param mixed               $original_value
288
+	 * @param string              $requested_version
289
+	 * @return mixed
290
+	 */
291
+	public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
292
+	{
293
+		if ($original_value === EE_INF) {
294
+			$new_value = ModelDataTranslator::EE_INF_IN_REST;
295
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
296
+			if (is_string($original_value)) {
297
+				// did they submit a string of a unix timestamp?
298
+				if (is_numeric($original_value)) {
299
+					$datetime_obj = new \DateTime();
300
+					$datetime_obj->setTimestamp((int) $original_value);
301
+				} else {
302
+					// first, check if its a MySQL timestamp in GMT
303
+					$datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
304
+				}
305
+				if (! $datetime_obj instanceof \DateTime) {
306
+					// so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
307
+					$datetime_obj = $field_obj->prepare_for_set($original_value);
308
+				}
309
+				$original_value = $datetime_obj;
310
+			}
311
+			if ($original_value instanceof \DateTime) {
312
+				$new_value = $original_value->format('Y-m-d H:i:s');
313
+			} elseif (is_int($original_value) || is_float($original_value)) {
314
+				$new_value = date('Y-m-d H:i:s', $original_value);
315
+			} elseif ($original_value === null || $original_value === '') {
316
+				$new_value = null;
317
+			} else {
318
+				// so it's not a datetime object, unix timestamp (as string or int),
319
+				// MySQL timestamp, or even a string in the field object's format. So no idea what it is
320
+				throw new \EE_Error(
321
+					sprintf(
322
+						esc_html__(
323
+						// @codingStandardsIgnoreStart
324
+							'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
325
+							// @codingStandardsIgnoreEnd
326
+							'event_espresso'
327
+						),
328
+						$original_value,
329
+						$field_obj->get_name(),
330
+						$field_obj->get_model_name(),
331
+						$field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
332
+					)
333
+				);
334
+			}
335
+			if ($new_value !== null) {
336
+				$new_value = mysql_to_rfc3339($new_value);
337
+			}
338
+		} else {
339
+			$new_value = $original_value;
340
+		}
341
+		// are we about to send an object? just don't. We have no good way to represent it in JSON.
342
+		// can't just check using is_object() because that missed PHP incomplete objects
343
+		if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
344
+			$new_value = array(
345
+				'error_code'    => 'php_object_not_return',
346
+				'error_message' => esc_html__(
347
+					'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
348
+					'event_espresso'
349
+				),
350
+			);
351
+		}
352
+		return apply_filters(
353
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
354
+			$new_value,
355
+			$field_obj,
356
+			$original_value,
357
+			$requested_version
358
+		);
359
+	}
360
+
361
+
362
+	/**
363
+	 * Prepares condition-query-parameters (like what's in where and having) from
364
+	 * the format expected in the API to use in the models
365
+	 *
366
+	 * @param array    $inputted_query_params_of_this_type
367
+	 * @param EEM_Base $model
368
+	 * @param string   $requested_version
369
+	 * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
370
+	 *                          If we're writing to the DB, we don't expect any operators, or any logic query
371
+	 *                          parameters, and we also won't accept serialized data unless the current user has
372
+	 *                          unfiltered_html.
373
+	 * @return array
374
+	 * @throws DomainException
375
+	 * @throws RestException
376
+	 * @throws EE_Error
377
+	 */
378
+	public static function prepareConditionsQueryParamsForModels(
379
+		$inputted_query_params_of_this_type,
380
+		EEM_Base $model,
381
+		$requested_version,
382
+		$writing = false
383
+	) {
384
+		$query_param_for_models = array();
385
+		$valid_operators = $model->valid_operators();
386
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
387
+			$is_gmt_datetime_field = false;
388
+			$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
389
+				$query_param_key
390
+			);
391
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
392
+				$query_param_sans_stars,
393
+				$model
394
+			);
395
+			// double-check is it a *_gmt field?
396
+			if (! $field instanceof EE_Model_Field_Base
397
+				&& ModelDataTranslator::isGmtDateFieldName($query_param_sans_stars)
398
+			) {
399
+				// yep, take off '_gmt', and find the field
400
+				$query_param_key = ModelDataTranslator::removeGmtFromFieldName($query_param_sans_stars);
401
+				$field = ModelDataTranslator::deduceFieldFromQueryParam(
402
+					$query_param_key,
403
+					$model
404
+				);
405
+				$timezone = 'UTC';
406
+				$is_gmt_datetime_field = true;
407
+			} elseif ($field instanceof EE_Datetime_Field) {
408
+				// so it's not a GMT field. Set the timezone on the model to the default
409
+				$timezone = \EEH_DTT_Helper::get_valid_timezone_string();
410
+			} else {
411
+				// just keep using what's already set for the timezone
412
+				$timezone = $model->get_timezone();
413
+			}
414
+			if ($field instanceof EE_Model_Field_Base) {
415
+				if (! $writing && is_array($query_param_value)) {
416
+					if (! \EEH_Array::is_array_numerically_and_sequentially_indexed($query_param_value)) {
417
+						if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
418
+							throw new RestException(
419
+								'numerically_indexed_array_of_values_only',
420
+								sprintf(
421
+									esc_html__(
422
+										'The array provided for the parameter "%1$s" should be numerically indexed.',
423
+										'event_espresso'
424
+									),
425
+									$query_param_key
426
+								),
427
+								array(
428
+									'status' => 400,
429
+								)
430
+							);
431
+						}
432
+					}
433
+					// did they specify an operator?
434
+					if (isset($query_param_value[0])
435
+						&& isset($valid_operators[ $query_param_value[0] ])
436
+					) {
437
+						$op = $query_param_value[0];
438
+						$translated_value = array($op);
439
+						if (array_key_exists($op, $model->valid_in_style_operators())
440
+							&& isset($query_param_value[1])
441
+							&& ! isset($query_param_value[2])
442
+						) {
443
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
444
+								$field,
445
+								$query_param_value[1],
446
+								$requested_version,
447
+								$timezone
448
+							);
449
+						} elseif (array_key_exists($op, $model->valid_between_style_operators())
450
+								  && isset($query_param_value[1])
451
+								  && is_array($query_param_value[1])
452
+								  && isset($query_param_key[1][0], $query_param_value[1][1])
453
+								  && ! isset($query_param_value[1][2])
454
+								  && ! isset($query_param_value[2])
455
+						) {
456
+							$translated_value[] = array(
457
+								ModelDataTranslator::prepareFieldValuesFromJson(
458
+									$field,
459
+									$query_param_value[1][0],
460
+									$requested_version,
461
+									$timezone
462
+								),
463
+								ModelDataTranslator::prepareFieldValuesFromJson(
464
+									$field,
465
+									$query_param_value[1][1],
466
+									$requested_version,
467
+									$timezone
468
+								)
469
+							);
470
+						} elseif (array_key_exists($op, $model->valid_like_style_operators())
471
+								  && isset($query_param_value[1])
472
+								  && ! isset($query_param_value[2])
473
+						) {
474
+							// we want to leave this value mostly-as-is (eg don't force it to be a float
475
+							// or a boolean or an enum value. Leave it as-is with wildcards etc)
476
+							// but do verify it at least doesn't have any serialized data
477
+							ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
478
+							$translated_value[] = $query_param_value[1];
479
+						} elseif (array_key_exists($op, $model->valid_null_style_operators())
480
+								  && ! isset($query_param_value[1])) {
481
+							// no arguments should have been provided, so don't look for any
482
+						} elseif (isset($query_param_value[1])
483
+								  && ! isset($query_param_value[2])
484
+								  && ! array_key_exists(
485
+									  $op,
486
+									  array_merge(
487
+										  $model->valid_in_style_operators(),
488
+										  $model->valid_null_style_operators(),
489
+										  $model->valid_like_style_operators(),
490
+										  $model->valid_between_style_operators()
491
+									  )
492
+								  )
493
+						) {
494
+							// it's a valid operator, but none of the exceptions. Treat it normally.
495
+							$translated_value[] = ModelDataTranslator::prepareFieldValuesFromJson(
496
+								$field,
497
+								$query_param_value[1],
498
+								$requested_version,
499
+								$timezone
500
+							);
501
+						} else {
502
+							// so they provided a valid operator, but wrong number of arguments
503
+							if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
504
+								throw new RestException(
505
+									'wrong_number_of_arguments',
506
+									sprintf(
507
+										esc_html__(
508
+											'The operator you provided, "%1$s" had the wrong number of arguments',
509
+											'event_espresso'
510
+										),
511
+										$op
512
+									),
513
+									array(
514
+										'status' => 400,
515
+									)
516
+								);
517
+							}
518
+							$translated_value = null;
519
+						}
520
+					} else {
521
+						// so they didn't provide a valid operator
522
+						if (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
523
+							throw new RestException(
524
+								'invalid_operator',
525
+								sprintf(
526
+									esc_html__(
527
+										'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
528
+										'event_espresso'
529
+									),
530
+									$query_param_key,
531
+									$query_param_value
532
+								),
533
+								array(
534
+									'status' => 400,
535
+								)
536
+							);
537
+						}
538
+						// if we aren't in debug mode, then just try our best to fulfill the user's request
539
+						$translated_value = null;
540
+					}
541
+				} else {
542
+					$translated_value = ModelDataTranslator::prepareFieldValueFromJson(
543
+						$field,
544
+						$query_param_value,
545
+						$requested_version,
546
+						$timezone
547
+					);
548
+				}
549
+				if ((isset($query_param_for_models[ $query_param_key ]) && $is_gmt_datetime_field)
550
+					|| $translated_value === null
551
+				) {
552
+					// they have already provided a non-gmt field, ignore the gmt one. That's what WP core
553
+					// currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
554
+					// OR we couldn't create a translated value from their input
555
+					continue;
556
+				}
557
+				$query_param_for_models[ $query_param_key ] = $translated_value;
558
+			} else {
559
+				// so this param doesn't correspond to a field eh?
560
+				if ($writing) {
561
+					// always tell API clients about invalid parameters when they're creating data. Otherwise,
562
+					// they are probably going to create invalid data
563
+					throw new RestException(
564
+						'invalid_field',
565
+						sprintf(
566
+							esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
567
+							$query_param_key
568
+						)
569
+					);
570
+				} else {
571
+					// so it's not for a field, is it a logic query param key?
572
+					if (in_array(
573
+						$query_param_sans_stars,
574
+						$model->logic_query_param_keys()
575
+					)) {
576
+						$query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
577
+							$query_param_value,
578
+							$model,
579
+							$requested_version
580
+						);
581
+					} elseif (defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE) {
582
+						// only tell API clients they got it wrong if we're in debug mode
583
+						// otherwise try our best ot fulfill their request by ignoring this invalid data
584
+						throw new RestException(
585
+							'invalid_parameter',
586
+							sprintf(
587
+								esc_html__(
588
+									'You provided an invalid parameter, with key "%1$s"',
589
+									'event_espresso'
590
+								),
591
+								$query_param_sans_stars
592
+							),
593
+							array(
594
+								'status' => 400,
595
+							)
596
+						);
597
+					}
598
+				}
599
+			}
600
+		}
601
+		return $query_param_for_models;
602
+	}
603
+
604
+
605
+	/**
606
+	 * Mostly checks if the last 4 characters are "_gmt", indicating its a
607
+	 * gmt date field name
608
+	 *
609
+	 * @param string $field_name
610
+	 * @return boolean
611
+	 */
612
+	public static function isGmtDateFieldName($field_name)
613
+	{
614
+		return substr(
615
+			ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
616
+			-4,
617
+			4
618
+		) === '_gmt';
619
+	}
620
+
621
+
622
+	/**
623
+	 * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
624
+	 *
625
+	 * @param string $field_name
626
+	 * @return string
627
+	 */
628
+	public static function removeGmtFromFieldName($field_name)
629
+	{
630
+		if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
631
+			return $field_name;
632
+		}
633
+		$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
634
+			$field_name
635
+		);
636
+		$query_param_sans_gmt_and_sans_stars = substr(
637
+			$query_param_sans_stars,
638
+			0,
639
+			strrpos(
640
+				$field_name,
641
+				'_gmt'
642
+			)
643
+		);
644
+		return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
645
+	}
646
+
647
+
648
+	/**
649
+	 * Takes a field name from the REST API and prepares it for the model querying
650
+	 *
651
+	 * @param string $field_name
652
+	 * @return string
653
+	 */
654
+	public static function prepareFieldNameFromJson($field_name)
655
+	{
656
+		if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
657
+			return ModelDataTranslator::removeGmtFromFieldName($field_name);
658
+		}
659
+		return $field_name;
660
+	}
661
+
662
+
663
+	/**
664
+	 * Takes array of field names from REST API and prepares for models
665
+	 *
666
+	 * @param array $field_names
667
+	 * @return array of field names (possibly include model prefixes)
668
+	 */
669
+	public static function prepareFieldNamesFromJson(array $field_names)
670
+	{
671
+		$new_array = array();
672
+		foreach ($field_names as $key => $field_name) {
673
+			$new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
674
+		}
675
+		return $new_array;
676
+	}
677
+
678
+
679
+	/**
680
+	 * Takes array where array keys are field names (possibly with model path prefixes)
681
+	 * from the REST API and prepares them for model querying
682
+	 *
683
+	 * @param array $field_names_as_keys
684
+	 * @return array
685
+	 */
686
+	public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
687
+	{
688
+		$new_array = array();
689
+		foreach ($field_names_as_keys as $field_name => $value) {
690
+			$new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
691
+		}
692
+		return $new_array;
693
+	}
694
+
695
+
696
+	/**
697
+	 * Prepares an array of model query params for use in the REST API
698
+	 *
699
+	 * @param array    $model_query_params
700
+	 * @param EEM_Base $model
701
+	 * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
702
+	 *                                     REST API
703
+	 * @return array which can be passed into the EE4 REST API when querying a model resource
704
+	 * @throws EE_Error
705
+	 */
706
+	public static function prepareQueryParamsForRestApi(
707
+		array $model_query_params,
708
+		EEM_Base $model,
709
+		$requested_version = null
710
+	) {
711
+		if ($requested_version === null) {
712
+			$requested_version = \EED_Core_Rest_Api::latest_rest_api_version();
713
+		}
714
+		$rest_query_params = $model_query_params;
715
+		if (isset($model_query_params[0])) {
716
+			$rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
717
+				$model_query_params[0],
718
+				$model,
719
+				$requested_version
720
+			);
721
+			unset($rest_query_params[0]);
722
+		}
723
+		if (isset($model_query_params['having'])) {
724
+			$rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
725
+				$model_query_params['having'],
726
+				$model,
727
+				$requested_version
728
+			);
729
+		}
730
+		return apply_filters(
731
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
732
+			$rest_query_params,
733
+			$model_query_params,
734
+			$model,
735
+			$requested_version
736
+		);
737
+	}
738
+
739
+
740
+	/**
741
+	 * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
742
+	 *
743
+	 * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
744
+	 *                                                      passed into EEM_Base::get_all()
745
+	 * @param EEM_Base $model
746
+	 * @param string   $requested_version                   eg "4.8.36"
747
+	 * @return array ready for use in the rest api query params
748
+	 * @throws EE_Error
749
+	 * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
750
+	 *                                                      (which would be really unusual)
751
+	 */
752
+	public static function prepareConditionsQueryParamsForRestApi(
753
+		$inputted_query_params_of_this_type,
754
+		EEM_Base $model,
755
+		$requested_version
756
+	) {
757
+		$query_param_for_models = array();
758
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
759
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
760
+				ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
761
+				$model
762
+			);
763
+			if ($field instanceof EE_Model_Field_Base) {
764
+				// did they specify an operator?
765
+				if (is_array($query_param_value)) {
766
+					$op = $query_param_value[0];
767
+					$translated_value = array($op);
768
+					if (isset($query_param_value[1])) {
769
+						$value = $query_param_value[1];
770
+						$translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
771
+							$field,
772
+							$value,
773
+							$requested_version
774
+						);
775
+					}
776
+				} else {
777
+					$translated_value = ModelDataTranslator::prepareFieldValueForJson(
778
+						$field,
779
+						$query_param_value,
780
+						$requested_version
781
+					);
782
+				}
783
+				$query_param_for_models[ $query_param_key ] = $translated_value;
784
+			} else {
785
+				// so it's not for a field, assume it's a logic query param key
786
+				$query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
787
+					$query_param_value,
788
+					$model,
789
+					$requested_version
790
+				);
791
+			}
792
+		}
793
+		return $query_param_for_models;
794
+	}
795
+
796
+
797
+	/**
798
+	 * @param $condition_query_param_key
799
+	 * @return string
800
+	 */
801
+	public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
802
+	{
803
+		$pos_of_star = strpos($condition_query_param_key, '*');
804
+		if ($pos_of_star === false) {
805
+			return $condition_query_param_key;
806
+		} else {
807
+			$condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
808
+			return $condition_query_param_sans_star;
809
+		}
810
+	}
811
+
812
+
813
+	/**
814
+	 * Takes the input parameter and finds the model field that it indicates.
815
+	 *
816
+	 * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
817
+	 * @param EEM_Base $model
818
+	 * @return EE_Model_Field_Base
819
+	 * @throws EE_Error
820
+	 */
821
+	public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
822
+	{
823
+		// ok, now proceed with deducing which part is the model's name, and which is the field's name
824
+		// which will help us find the database table and column
825
+		$query_param_parts = explode('.', $query_param_name);
826
+		if (empty($query_param_parts)) {
827
+			throw new EE_Error(
828
+				sprintf(
829
+					__(
830
+						'_extract_column_name is empty when trying to extract column and table name from %s',
831
+						'event_espresso'
832
+					),
833
+					$query_param_name
834
+				)
835
+			);
836
+		}
837
+		$number_of_parts = count($query_param_parts);
838
+		$last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
839
+		if ($number_of_parts === 1) {
840
+			$field_name = $last_query_param_part;
841
+		} else {// $number_of_parts >= 2
842
+			// the last part is the column name, and there are only 2parts. therefore...
843
+			$field_name = $last_query_param_part;
844
+			$model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
845
+		}
846
+		try {
847
+			return $model->field_settings_for($field_name, false);
848
+		} catch (EE_Error $e) {
849
+			return null;
850
+		}
851
+	}
852
+
853
+
854
+	/**
855
+	 * Returns true if $data can be easily represented in JSON.
856
+	 * Basically, objects and resources can't be represented in JSON easily.
857
+	 *
858
+	 * @param mixed $data
859
+	 * @return bool
860
+	 */
861
+	protected static function isRepresentableInJson($data)
862
+	{
863
+		return is_scalar($data)
864
+			   || is_array($data)
865
+			   || is_null($data);
866
+	}
867 867
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelVersionInfo.php 1 patch
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -21,440 +21,440 @@
 block discarded – undo
21 21
 class ModelVersionInfo
22 22
 {
23 23
 
24
-    /**
25
-     * Constant used in the $_model_changes array to indicate that a model
26
-     * was completely new in this version
27
-     */
28
-    const MODEL_ADDED = 'model_added_in_this_version';
29
-
30
-    /**
31
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
32
-     * next-level keys are model names (eg "Event") that underwent some change in that version
33
-     * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
34
-     * or it's an array where the values are model field names,
35
-     * or API resource properties (ie, non-model fields that appear in REST API results)
36
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
37
-     *
38
-     * @var array
39
-     */
40
-    protected $model_changes = array();
41
-
42
-    /**
43
-     * top-level keys are version numbers,
44
-     * next-level keys are model CLASSNAMES (even parent classnames),
45
-     * and next-level keys are extra resource properties to attach to those models' resources,
46
-     * and next-level key-value pairs, where the keys are:
47
-     * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
48
-     *
49
-     * @var array
50
-     */
51
-    protected $resource_changes = array();
52
-
53
-    /**
54
-     * @var string indicating what version of the API was requested
55
-     * (eg although core might be at version 4.8.11, they may have sent a request
56
-     * for 4.6)
57
-     */
58
-    protected $requested_version = null;
59
-
60
-    /**
61
-     * Keys are model names, values are their classnames.
62
-     * We cache this so we only need to calculate this once per request
63
-     *
64
-     * @var array
65
-     */
66
-    protected $cached_models_for_requested_version = null;
67
-
68
-    /**
69
-     * @var array
70
-     */
71
-    protected $cached_model_changes_between_requested_version_and_current = null;
72
-
73
-    /**
74
-     * @var array
75
-     */
76
-    protected $cached_resource_changes_between_requested_version_and_current = null;
77
-
78
-    /**
79
-     * 2d array where top-level keys are model names, 2nd-level keys are field names
80
-     * and values are the actual field objects
81
-     *
82
-     * @var array
83
-     */
84
-    protected $cached_fields_on_models = array();
85
-
86
-
87
-    /**
88
-     * Model_Version_Info constructor.
89
-     *
90
-     * @param string $requested_version
91
-     */
92
-    public function __construct($requested_version)
93
-    {
94
-        $this->requested_version = (string) $requested_version;
95
-        $this->model_changes = array(
96
-            '4.8.29' => array(
97
-                // first version where the REST API is in EE core, so no need
98
-                // to specify how its different from the previous
99
-            ),
100
-        );
101
-        // setup data for "extra" fields added onto resources which don't actually exist on models
102
-        $this->resource_changes = apply_filters(
103
-            'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
104
-            array()
105
-        );
106
-        $defaults = array(
107
-            'raw'              => false,
108
-            'type'             => 'N/A',
109
-            'nullable'         => true,
110
-            'table_alias'      => 'N/A',
111
-            'table_column'     => 'N/A',
112
-            'always_available' => true,
113
-        );
114
-        foreach ($this->resource_changes as $version => $model_classnames) {
115
-            foreach ($model_classnames as $model_classname => $extra_fields) {
116
-                foreach ($extra_fields as $fieldname => $field_data) {
117
-                    $this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
118
-                    foreach ($defaults as $attribute => $default_value) {
119
-                        if (! isset($this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ])) {
120
-                            $this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ] = $default_value;
121
-                        }
122
-                    }
123
-                }
124
-            }
125
-        }
126
-    }
127
-
128
-
129
-    /**
130
-     * Returns a slice of Model_Version_Info::model_changes()'s array
131
-     * indicating exactly what changes happened between the current core version,
132
-     * and the version requested
133
-     *
134
-     * @return array
135
-     */
136
-    public function modelChangesBetweenRequestedVersionAndCurrent()
137
-    {
138
-        if ($this->cached_model_changes_between_requested_version_and_current === null) {
139
-            $model_changes = array();
140
-            foreach ($this->modelChanges() as $version => $models_changed_in_version) {
141
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
142
-                    $model_changes[ $version ] = $models_changed_in_version;
143
-                }
144
-            }
145
-            $this->cached_model_changes_between_requested_version_and_current = $model_changes;
146
-        }
147
-        return $this->cached_model_changes_between_requested_version_and_current;
148
-    }
149
-
150
-
151
-    /**
152
-     * Returns a slice of Model_Version_Info::model_changes()'s array
153
-     * indicating exactly what changes happened between the current core version,
154
-     * and the version requested
155
-     *
156
-     * @return array
157
-     */
158
-    public function resourceChangesBetweenRequestedVersionAndCurrent()
159
-    {
160
-        if ($this->cached_resource_changes_between_requested_version_and_current === null) {
161
-            $resource_changes = array();
162
-            foreach ($this->resourceChanges() as $version => $model_classnames) {
163
-                if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
164
-                    $resource_changes[ $version ] = $model_classnames;
165
-                }
166
-            }
167
-            $this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
168
-        }
169
-        return $this->cached_resource_changes_between_requested_version_and_current;
170
-    }
171
-
172
-
173
-    /**
174
-     * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
175
-     *
176
-     * @return string like '4.6'
177
-     */
178
-    public function requestedVersion()
179
-    {
180
-        return $this->requested_version;
181
-    }
182
-
183
-
184
-    /**
185
-     * Returns an array describing how the models have changed in each version of core
186
-     * that supports the API (starting at 4.6)
187
-     * Top-level keys are versions (major and minor version numbers, eg "4.6")
188
-     * next-level keys are model names (eg "Event") that underwent some change in that version
189
-     * and the value is either NULL (indicating the model is completely NEW in this version),
190
-     * or it's an array where fields are value names.
191
-     * If a version is missing then we don't know anything about what changes it introduced from the previous version
192
-     *
193
-     * @return array
194
-     */
195
-    public function modelChanges()
196
-    {
197
-        return $this->model_changes;
198
-    }
199
-
200
-
201
-    /**
202
-     * Takes into account the requested version, and the current version, and
203
-     * what changed between the two, and tries to return.
204
-     * Analogous to EE_Registry::instance()->non_abstract_db_models
205
-     *
206
-     * @return array keys are model names, values are their classname
207
-     */
208
-    public function modelsForRequestedVersion()
209
-    {
210
-        if ($this->cached_models_for_requested_version === null) {
211
-            $all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
212
-            foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
213
-                foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
214
-                    if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
215
-                        unset($all_models_in_current_version[ $model_name ]);
216
-                    }
217
-                }
218
-            }
219
-            $this->cached_models_for_requested_version = apply_filters(
220
-                'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
221
-                $all_models_in_current_version,
222
-                $this
223
-            );
224
-        }
225
-        return $this->cached_models_for_requested_version;
226
-    }
227
-
228
-
229
-    /**
230
-     * Determines if this is a valid model name in the requested version.
231
-     * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
232
-     * version's models into account
233
-     *
234
-     * @param string $model_name eg 'Event'
235
-     * @return boolean
236
-     */
237
-    public function isModelNameInThisVersion($model_name)
238
-    {
239
-        $model_names = $this->modelsForRequestedVersion();
240
-        if (isset($model_names[ $model_name ])) {
241
-            return true;
242
-        } else {
243
-            return false;
244
-        }
245
-    }
246
-
247
-
248
-    /**
249
-     * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
250
-     * version's models into account
251
-     *
252
-     * @param string $model_name
253
-     * @return \EEM_Base
254
-     * @throws \EE_Error
255
-     */
256
-    public function loadModel($model_name)
257
-    {
258
-        if ($this->isModelNameInThisVersion($model_name)) {
259
-            return EE_Registry::instance()->load_model($model_name);
260
-        } else {
261
-            throw new \EE_Error(
262
-                sprintf(
263
-                    __(
264
-                        'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
265
-                        'event_espresso'
266
-                    ),
267
-                    $model_name,
268
-                    $this->requestedVersion()
269
-                )
270
-            );
271
-        }
272
-    }
273
-
274
-
275
-    /**
276
-     * Gets all the fields that should exist on this model right now
277
-     *
278
-     * @param \EEM_Base $model
279
-     * @return array|\EE_Model_Field_Base[]
280
-     */
281
-    public function fieldsOnModelInThisVersion($model)
282
-    {
283
-        if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
284
-            // get all model changes between the requested version and current core version
285
-            $changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
286
-            // fetch all fields currently on this model
287
-            $current_fields = $model->field_settings();
288
-            // remove all fields that have been added since
289
-            foreach ($changes as $version => $changes_in_version) {
290
-                if (isset($changes_in_version[ $model->get_this_model_name() ])
291
-                    && $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
292
-                ) {
293
-                    $current_fields = array_diff_key(
294
-                        $current_fields,
295
-                        array_flip($changes_in_version[ $model->get_this_model_name() ])
296
-                    );
297
-                }
298
-            }
299
-            $this->cached_fields_on_models = $current_fields;
300
-        }
301
-        return $this->cached_fields_on_models;
302
-    }
303
-
304
-
305
-    /**
306
-     * Determines if $object is of one of the classes of $classes. Similar to
307
-     * in_array(), except this checks if $object is a subclass of the classnames provided
308
-     * in $classnames
309
-     *
310
-     * @param object $object
311
-     * @param array  $classnames
312
-     * @return boolean
313
-     */
314
-    public function isSubclassOfOne($object, $classnames)
315
-    {
316
-        foreach ($classnames as $classname) {
317
-            if (is_a($object, $classname)) {
318
-                return true;
319
-            }
320
-        }
321
-        return false;
322
-    }
323
-
324
-
325
-    /**
326
-     * Returns the list of model field classes that that the API basically ignores
327
-     *
328
-     * @return array
329
-     */
330
-    public function fieldsIgnored()
331
-    {
332
-        return apply_filters(
333
-            'FHEE__Controller_Model_Read_fields_ignored',
334
-            array()
335
-        );
336
-    }
337
-
338
-
339
-    /**
340
-     * If this field one that should be ignored by the API?
341
-     *
342
-     * @param EE_Model_Field_Base
343
-     * @return boolean
344
-     */
345
-    public function fieldIsIgnored($field_obj)
346
-    {
347
-        return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
348
-    }
349
-
350
-
351
-    /**
352
-     * Returns the list of model field classes that have a "raw" and non-raw formats.
353
-     * Normally the "raw" versions are only accessible to those who can edit them.
354
-     *
355
-     * @return array an array of EE_Model_Field_Base child classnames
356
-     */
357
-    public function fieldsThatHaveRenderedFormat()
358
-    {
359
-        return apply_filters(
360
-            'FHEE__Controller_Model_Read__fields_raw',
361
-            array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
362
-        );
363
-    }
364
-
365
-
366
-    /**
367
-     * If this field one that has a raw format
368
-     *
369
-     * @param EE_Model_Field_Base
370
-     * @return boolean
371
-     */
372
-    public function fieldHasRenderedFormat($field_obj)
373
-    {
374
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
375
-    }
376
-
377
-
378
-    /**
379
-     * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
380
-     * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
381
-     * to view
382
-     *
383
-     * @return array an array of EE_Model_Field_Base child classnames
384
-     */
385
-    public function fieldsThatHavePrettyFormat()
386
-    {
387
-        return apply_filters(
388
-            'FHEE__Controller_Model_Read__fields_pretty',
389
-            array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * If this field one that has a pretty equivalent
396
-     *
397
-     * @param EE_Model_Field_Base
398
-     * @return boolean
399
-     */
400
-    public function fieldHasPrettyFormat($field_obj)
401
-    {
402
-        return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
403
-    }
404
-
405
-
406
-    /**
407
-     * Returns an array describing what extra API resource properties have been added through the versions
408
-     *
409
-     * @return array @see $this->_extra_resource_properties_for_models
410
-     */
411
-    public function resourceChanges()
412
-    {
413
-        return $this->resource_changes;
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns an array where keys are extra resource properties in this version of the API,
419
-     * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
420
-     *
421
-     * @param \EEM_Base $model
422
-     * @return array
423
-     */
424
-    public function extraResourcePropertiesForModel($model)
425
-    {
426
-        $extra_properties = array();
427
-        foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
428
-            foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
429
-                if (is_subclass_of($model, $model_classname)) {
430
-                    $extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
431
-                }
432
-            }
433
-        }
434
-        return $extra_properties;
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets all the related models for the specified model. It's good to use this
440
-     * in case this model didn't exist for this version or something
441
-     *
442
-     * @param \EEM_Base $model
443
-     * @return \EE_Model_Relation_Base[]
444
-     */
445
-    public function relationSettings(\EEM_Base $model)
446
-    {
447
-        $relations = array();
448
-        foreach ($model->relation_settings() as $relation_name => $relation_obj) {
449
-            if ($this->isModelNameInThisVersion($relation_name)) {
450
-                $relations[ $relation_name ] = $relation_obj;
451
-            }
452
-        }
453
-        // filter the results, but use the old filter name
454
-        return apply_filters(
455
-            'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
456
-            $relations,
457
-            $model
458
-        );
459
-    }
24
+	/**
25
+	 * Constant used in the $_model_changes array to indicate that a model
26
+	 * was completely new in this version
27
+	 */
28
+	const MODEL_ADDED = 'model_added_in_this_version';
29
+
30
+	/**
31
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
32
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
33
+	 * and the value is either Model_Version_Info::model_added (indicating the model is completely NEW in this version),
34
+	 * or it's an array where the values are model field names,
35
+	 * or API resource properties (ie, non-model fields that appear in REST API results)
36
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
37
+	 *
38
+	 * @var array
39
+	 */
40
+	protected $model_changes = array();
41
+
42
+	/**
43
+	 * top-level keys are version numbers,
44
+	 * next-level keys are model CLASSNAMES (even parent classnames),
45
+	 * and next-level keys are extra resource properties to attach to those models' resources,
46
+	 * and next-level key-value pairs, where the keys are:
47
+	 * 'raw', 'type', 'nullable', 'table_alias', 'table_column',  'always_available'
48
+	 *
49
+	 * @var array
50
+	 */
51
+	protected $resource_changes = array();
52
+
53
+	/**
54
+	 * @var string indicating what version of the API was requested
55
+	 * (eg although core might be at version 4.8.11, they may have sent a request
56
+	 * for 4.6)
57
+	 */
58
+	protected $requested_version = null;
59
+
60
+	/**
61
+	 * Keys are model names, values are their classnames.
62
+	 * We cache this so we only need to calculate this once per request
63
+	 *
64
+	 * @var array
65
+	 */
66
+	protected $cached_models_for_requested_version = null;
67
+
68
+	/**
69
+	 * @var array
70
+	 */
71
+	protected $cached_model_changes_between_requested_version_and_current = null;
72
+
73
+	/**
74
+	 * @var array
75
+	 */
76
+	protected $cached_resource_changes_between_requested_version_and_current = null;
77
+
78
+	/**
79
+	 * 2d array where top-level keys are model names, 2nd-level keys are field names
80
+	 * and values are the actual field objects
81
+	 *
82
+	 * @var array
83
+	 */
84
+	protected $cached_fields_on_models = array();
85
+
86
+
87
+	/**
88
+	 * Model_Version_Info constructor.
89
+	 *
90
+	 * @param string $requested_version
91
+	 */
92
+	public function __construct($requested_version)
93
+	{
94
+		$this->requested_version = (string) $requested_version;
95
+		$this->model_changes = array(
96
+			'4.8.29' => array(
97
+				// first version where the REST API is in EE core, so no need
98
+				// to specify how its different from the previous
99
+			),
100
+		);
101
+		// setup data for "extra" fields added onto resources which don't actually exist on models
102
+		$this->resource_changes = apply_filters(
103
+			'FHEE__Model_Version_Info___construct__extra_resource_properties_for_models',
104
+			array()
105
+		);
106
+		$defaults = array(
107
+			'raw'              => false,
108
+			'type'             => 'N/A',
109
+			'nullable'         => true,
110
+			'table_alias'      => 'N/A',
111
+			'table_column'     => 'N/A',
112
+			'always_available' => true,
113
+		);
114
+		foreach ($this->resource_changes as $version => $model_classnames) {
115
+			foreach ($model_classnames as $model_classname => $extra_fields) {
116
+				foreach ($extra_fields as $fieldname => $field_data) {
117
+					$this->resource_changes[ $model_classname ][ $fieldname ]['name'] = $fieldname;
118
+					foreach ($defaults as $attribute => $default_value) {
119
+						if (! isset($this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ])) {
120
+							$this->resource_changes[ $model_classname ][ $fieldname ][ $attribute ] = $default_value;
121
+						}
122
+					}
123
+				}
124
+			}
125
+		}
126
+	}
127
+
128
+
129
+	/**
130
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
131
+	 * indicating exactly what changes happened between the current core version,
132
+	 * and the version requested
133
+	 *
134
+	 * @return array
135
+	 */
136
+	public function modelChangesBetweenRequestedVersionAndCurrent()
137
+	{
138
+		if ($this->cached_model_changes_between_requested_version_and_current === null) {
139
+			$model_changes = array();
140
+			foreach ($this->modelChanges() as $version => $models_changed_in_version) {
141
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
142
+					$model_changes[ $version ] = $models_changed_in_version;
143
+				}
144
+			}
145
+			$this->cached_model_changes_between_requested_version_and_current = $model_changes;
146
+		}
147
+		return $this->cached_model_changes_between_requested_version_and_current;
148
+	}
149
+
150
+
151
+	/**
152
+	 * Returns a slice of Model_Version_Info::model_changes()'s array
153
+	 * indicating exactly what changes happened between the current core version,
154
+	 * and the version requested
155
+	 *
156
+	 * @return array
157
+	 */
158
+	public function resourceChangesBetweenRequestedVersionAndCurrent()
159
+	{
160
+		if ($this->cached_resource_changes_between_requested_version_and_current === null) {
161
+			$resource_changes = array();
162
+			foreach ($this->resourceChanges() as $version => $model_classnames) {
163
+				if ($version <= EED_Core_Rest_Api::core_version() && $version > $this->requestedVersion()) {
164
+					$resource_changes[ $version ] = $model_classnames;
165
+				}
166
+			}
167
+			$this->cached_resource_changes_between_requested_version_and_current = $resource_changes;
168
+		}
169
+		return $this->cached_resource_changes_between_requested_version_and_current;
170
+	}
171
+
172
+
173
+	/**
174
+	 * If a request was sent to 'wp-json/ee/v4.7/events' this would be '4.7'
175
+	 *
176
+	 * @return string like '4.6'
177
+	 */
178
+	public function requestedVersion()
179
+	{
180
+		return $this->requested_version;
181
+	}
182
+
183
+
184
+	/**
185
+	 * Returns an array describing how the models have changed in each version of core
186
+	 * that supports the API (starting at 4.6)
187
+	 * Top-level keys are versions (major and minor version numbers, eg "4.6")
188
+	 * next-level keys are model names (eg "Event") that underwent some change in that version
189
+	 * and the value is either NULL (indicating the model is completely NEW in this version),
190
+	 * or it's an array where fields are value names.
191
+	 * If a version is missing then we don't know anything about what changes it introduced from the previous version
192
+	 *
193
+	 * @return array
194
+	 */
195
+	public function modelChanges()
196
+	{
197
+		return $this->model_changes;
198
+	}
199
+
200
+
201
+	/**
202
+	 * Takes into account the requested version, and the current version, and
203
+	 * what changed between the two, and tries to return.
204
+	 * Analogous to EE_Registry::instance()->non_abstract_db_models
205
+	 *
206
+	 * @return array keys are model names, values are their classname
207
+	 */
208
+	public function modelsForRequestedVersion()
209
+	{
210
+		if ($this->cached_models_for_requested_version === null) {
211
+			$all_models_in_current_version = EE_Registry::instance()->non_abstract_db_models;
212
+			foreach ($this->modelChangesBetweenRequestedVersionAndCurrent() as $version => $models_changed) {
213
+				foreach ($models_changed as $model_name => $new_indicator_or_fields_added) {
214
+					if ($new_indicator_or_fields_added === ModelVersionInfo::MODEL_ADDED) {
215
+						unset($all_models_in_current_version[ $model_name ]);
216
+					}
217
+				}
218
+			}
219
+			$this->cached_models_for_requested_version = apply_filters(
220
+				'FHEE__EventEspresso_core_libraries_rest_api__models_for_requested_version',
221
+				$all_models_in_current_version,
222
+				$this
223
+			);
224
+		}
225
+		return $this->cached_models_for_requested_version;
226
+	}
227
+
228
+
229
+	/**
230
+	 * Determines if this is a valid model name in the requested version.
231
+	 * Similar to EE_Registry::instance()->is_model_name(), but takes the requested
232
+	 * version's models into account
233
+	 *
234
+	 * @param string $model_name eg 'Event'
235
+	 * @return boolean
236
+	 */
237
+	public function isModelNameInThisVersion($model_name)
238
+	{
239
+		$model_names = $this->modelsForRequestedVersion();
240
+		if (isset($model_names[ $model_name ])) {
241
+			return true;
242
+		} else {
243
+			return false;
244
+		}
245
+	}
246
+
247
+
248
+	/**
249
+	 * Wrapper for EE_Registry::instance()->load_model(), but takes the requested
250
+	 * version's models into account
251
+	 *
252
+	 * @param string $model_name
253
+	 * @return \EEM_Base
254
+	 * @throws \EE_Error
255
+	 */
256
+	public function loadModel($model_name)
257
+	{
258
+		if ($this->isModelNameInThisVersion($model_name)) {
259
+			return EE_Registry::instance()->load_model($model_name);
260
+		} else {
261
+			throw new \EE_Error(
262
+				sprintf(
263
+					__(
264
+						'Cannot load model "%1$s" because it does not exist in version %2$s of Event Espresso',
265
+						'event_espresso'
266
+					),
267
+					$model_name,
268
+					$this->requestedVersion()
269
+				)
270
+			);
271
+		}
272
+	}
273
+
274
+
275
+	/**
276
+	 * Gets all the fields that should exist on this model right now
277
+	 *
278
+	 * @param \EEM_Base $model
279
+	 * @return array|\EE_Model_Field_Base[]
280
+	 */
281
+	public function fieldsOnModelInThisVersion($model)
282
+	{
283
+		if (! isset($this->cached_fields_on_models[ $model->get_this_model_name() ])) {
284
+			// get all model changes between the requested version and current core version
285
+			$changes = $this->modelChangesBetweenRequestedVersionAndCurrent();
286
+			// fetch all fields currently on this model
287
+			$current_fields = $model->field_settings();
288
+			// remove all fields that have been added since
289
+			foreach ($changes as $version => $changes_in_version) {
290
+				if (isset($changes_in_version[ $model->get_this_model_name() ])
291
+					&& $changes_in_version[ $model->get_this_model_name() ] !== ModelVersionInfo::MODEL_ADDED
292
+				) {
293
+					$current_fields = array_diff_key(
294
+						$current_fields,
295
+						array_flip($changes_in_version[ $model->get_this_model_name() ])
296
+					);
297
+				}
298
+			}
299
+			$this->cached_fields_on_models = $current_fields;
300
+		}
301
+		return $this->cached_fields_on_models;
302
+	}
303
+
304
+
305
+	/**
306
+	 * Determines if $object is of one of the classes of $classes. Similar to
307
+	 * in_array(), except this checks if $object is a subclass of the classnames provided
308
+	 * in $classnames
309
+	 *
310
+	 * @param object $object
311
+	 * @param array  $classnames
312
+	 * @return boolean
313
+	 */
314
+	public function isSubclassOfOne($object, $classnames)
315
+	{
316
+		foreach ($classnames as $classname) {
317
+			if (is_a($object, $classname)) {
318
+				return true;
319
+			}
320
+		}
321
+		return false;
322
+	}
323
+
324
+
325
+	/**
326
+	 * Returns the list of model field classes that that the API basically ignores
327
+	 *
328
+	 * @return array
329
+	 */
330
+	public function fieldsIgnored()
331
+	{
332
+		return apply_filters(
333
+			'FHEE__Controller_Model_Read_fields_ignored',
334
+			array()
335
+		);
336
+	}
337
+
338
+
339
+	/**
340
+	 * If this field one that should be ignored by the API?
341
+	 *
342
+	 * @param EE_Model_Field_Base
343
+	 * @return boolean
344
+	 */
345
+	public function fieldIsIgnored($field_obj)
346
+	{
347
+		return $this->isSubclassOfOne($field_obj, $this->fieldsIgnored());
348
+	}
349
+
350
+
351
+	/**
352
+	 * Returns the list of model field classes that have a "raw" and non-raw formats.
353
+	 * Normally the "raw" versions are only accessible to those who can edit them.
354
+	 *
355
+	 * @return array an array of EE_Model_Field_Base child classnames
356
+	 */
357
+	public function fieldsThatHaveRenderedFormat()
358
+	{
359
+		return apply_filters(
360
+			'FHEE__Controller_Model_Read__fields_raw',
361
+			array('EE_Post_Content_Field', 'EE_Full_HTML_Field')
362
+		);
363
+	}
364
+
365
+
366
+	/**
367
+	 * If this field one that has a raw format
368
+	 *
369
+	 * @param EE_Model_Field_Base
370
+	 * @return boolean
371
+	 */
372
+	public function fieldHasRenderedFormat($field_obj)
373
+	{
374
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHaveRenderedFormat());
375
+	}
376
+
377
+
378
+	/**
379
+	 * Returns the list of model field classes that have a "_pretty" and non-pretty versions.
380
+	 * The pretty version of the field is NOT query-able or editable, but requires no extra permissions
381
+	 * to view
382
+	 *
383
+	 * @return array an array of EE_Model_Field_Base child classnames
384
+	 */
385
+	public function fieldsThatHavePrettyFormat()
386
+	{
387
+		return apply_filters(
388
+			'FHEE__Controller_Model_Read__fields_pretty',
389
+			array('EE_Enum_Integer_Field', 'EE_Enum_Text_Field', 'EE_Money_Field')
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * If this field one that has a pretty equivalent
396
+	 *
397
+	 * @param EE_Model_Field_Base
398
+	 * @return boolean
399
+	 */
400
+	public function fieldHasPrettyFormat($field_obj)
401
+	{
402
+		return $this->isSubclassOfOne($field_obj, $this->fieldsThatHavePrettyFormat());
403
+	}
404
+
405
+
406
+	/**
407
+	 * Returns an array describing what extra API resource properties have been added through the versions
408
+	 *
409
+	 * @return array @see $this->_extra_resource_properties_for_models
410
+	 */
411
+	public function resourceChanges()
412
+	{
413
+		return $this->resource_changes;
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns an array where keys are extra resource properties in this version of the API,
419
+	 * and values are key-value pairs describing the new properties. @see Model_Version::_resource_changes
420
+	 *
421
+	 * @param \EEM_Base $model
422
+	 * @return array
423
+	 */
424
+	public function extraResourcePropertiesForModel($model)
425
+	{
426
+		$extra_properties = array();
427
+		foreach ($this->resourceChangesBetweenRequestedVersionAndCurrent() as $version => $model_classnames) {
428
+			foreach ($model_classnames as $model_classname => $properties_added_in_this_version) {
429
+				if (is_subclass_of($model, $model_classname)) {
430
+					$extra_properties = array_merge($extra_properties, $properties_added_in_this_version);
431
+				}
432
+			}
433
+		}
434
+		return $extra_properties;
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets all the related models for the specified model. It's good to use this
440
+	 * in case this model didn't exist for this version or something
441
+	 *
442
+	 * @param \EEM_Base $model
443
+	 * @return \EE_Model_Relation_Base[]
444
+	 */
445
+	public function relationSettings(\EEM_Base $model)
446
+	{
447
+		$relations = array();
448
+		foreach ($model->relation_settings() as $relation_name => $relation_obj) {
449
+			if ($this->isModelNameInThisVersion($relation_name)) {
450
+				$relations[ $relation_name ] = $relation_obj;
451
+			}
452
+		}
453
+		// filter the results, but use the old filter name
454
+		return apply_filters(
455
+			'FHEE__Read__create_entity_from_wpdb_result__related_models_to_include',
456
+			$relations,
457
+			$model
458
+		);
459
+	}
460 460
 }
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 1 patch
Indentation   +1278 added lines, -1278 removed lines patch added patch discarded remove patch
@@ -16,1282 +16,1282 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Extend_Events_Admin_Page constructor.
21
-     *
22
-     * @param bool $routing
23
-     */
24
-    public function __construct($routing = true)
25
-    {
26
-        parent::__construct($routing);
27
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
-        }
32
-    }
33
-
34
-
35
-    /**
36
-     * Sets routes.
37
-     */
38
-    protected function _extend_page_config()
39
-    {
40
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
-        // is there a evt_id in the request?
42
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
43
-            ? $this->_req_data['EVT_ID']
44
-            : 0;
45
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
46
-        // tkt_id?
47
-        $tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
48
-            ? $this->_req_data['TKT_ID']
49
-            : 0;
50
-        $new_page_routes = array(
51
-            'duplicate_event'          => array(
52
-                'func'       => '_duplicate_event',
53
-                'capability' => 'ee_edit_event',
54
-                'obj_id'     => $evt_id,
55
-                'noheader'   => true,
56
-            ),
57
-            'ticket_list_table'        => array(
58
-                'func'       => '_tickets_overview_list_table',
59
-                'capability' => 'ee_read_default_tickets',
60
-            ),
61
-            'trash_ticket'             => array(
62
-                'func'       => '_trash_or_restore_ticket',
63
-                'capability' => 'ee_delete_default_ticket',
64
-                'obj_id'     => $tkt_id,
65
-                'noheader'   => true,
66
-                'args'       => array('trash' => true),
67
-            ),
68
-            'trash_tickets'            => array(
69
-                'func'       => '_trash_or_restore_ticket',
70
-                'capability' => 'ee_delete_default_tickets',
71
-                'noheader'   => true,
72
-                'args'       => array('trash' => true),
73
-            ),
74
-            'restore_ticket'           => array(
75
-                'func'       => '_trash_or_restore_ticket',
76
-                'capability' => 'ee_delete_default_ticket',
77
-                'obj_id'     => $tkt_id,
78
-                'noheader'   => true,
79
-            ),
80
-            'restore_tickets'          => array(
81
-                'func'       => '_trash_or_restore_ticket',
82
-                'capability' => 'ee_delete_default_tickets',
83
-                'noheader'   => true,
84
-            ),
85
-            'delete_ticket'            => array(
86
-                'func'       => '_delete_ticket',
87
-                'capability' => 'ee_delete_default_ticket',
88
-                'obj_id'     => $tkt_id,
89
-                'noheader'   => true,
90
-            ),
91
-            'delete_tickets'           => array(
92
-                'func'       => '_delete_ticket',
93
-                'capability' => 'ee_delete_default_tickets',
94
-                'noheader'   => true,
95
-            ),
96
-            'import_page'              => array(
97
-                'func'       => '_import_page',
98
-                'capability' => 'import',
99
-            ),
100
-            'import'                   => array(
101
-                'func'       => '_import_events',
102
-                'capability' => 'import',
103
-                'noheader'   => true,
104
-            ),
105
-            'import_events'            => array(
106
-                'func'       => '_import_events',
107
-                'capability' => 'import',
108
-                'noheader'   => true,
109
-            ),
110
-            'export_events'            => array(
111
-                'func'       => '_events_export',
112
-                'capability' => 'export',
113
-                'noheader'   => true,
114
-            ),
115
-            'export_categories'        => array(
116
-                'func'       => '_categories_export',
117
-                'capability' => 'export',
118
-                'noheader'   => true,
119
-            ),
120
-            'sample_export_file'       => array(
121
-                'func'       => '_sample_export_file',
122
-                'capability' => 'export',
123
-                'noheader'   => true,
124
-            ),
125
-            'update_template_settings' => array(
126
-                'func'       => '_update_template_settings',
127
-                'capability' => 'manage_options',
128
-                'noheader'   => true,
129
-            ),
130
-        );
131
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
132
-        // partial route/config override
133
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
134
-        $this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
135
-        $this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
136
-        $this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
137
-        $this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
138
-        $this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
139
-        // add tickets tab but only if there are more than one default ticket!
140
-        $tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
141
-            array(array('TKT_is_default' => 1)),
142
-            'TKT_ID',
143
-            true
144
-        );
145
-        if ($tkt_count > 1) {
146
-            $new_page_config = array(
147
-                'ticket_list_table' => array(
148
-                    'nav'           => array(
149
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
150
-                        'order' => 60,
151
-                    ),
152
-                    'list_table'    => 'Tickets_List_Table',
153
-                    'require_nonce' => false,
154
-                ),
155
-            );
156
-        }
157
-        // template settings
158
-        $new_page_config['template_settings'] = array(
159
-            'nav'           => array(
160
-                'label' => esc_html__('Templates', 'event_espresso'),
161
-                'order' => 30,
162
-            ),
163
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
164
-            'help_tabs'     => array(
165
-                'general_settings_templates_help_tab' => array(
166
-                    'title'    => esc_html__('Templates', 'event_espresso'),
167
-                    'filename' => 'general_settings_templates',
168
-                ),
169
-            ),
170
-            'help_tour'     => array('Templates_Help_Tour'),
171
-            'require_nonce' => false,
172
-        );
173
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
174
-        // add filters and actions
175
-        // modifying _views
176
-        add_filter(
177
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
178
-            array($this, 'add_additional_datetime_button'),
179
-            10,
180
-            2
181
-        );
182
-        add_filter(
183
-            'FHEE_event_datetime_metabox_clone_button_template',
184
-            array($this, 'add_datetime_clone_button'),
185
-            10,
186
-            2
187
-        );
188
-        add_filter(
189
-            'FHEE_event_datetime_metabox_timezones_template',
190
-            array($this, 'datetime_timezones_template'),
191
-            10,
192
-            2
193
-        );
194
-        // filters for event list table
195
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
196
-        add_filter(
197
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
198
-            array($this, 'extra_list_table_actions'),
199
-            10,
200
-            2
201
-        );
202
-        // legend item
203
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
204
-        add_action('admin_init', array($this, 'admin_init'));
205
-        // heartbeat stuff
206
-        add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
207
-    }
208
-
209
-
210
-    /**
211
-     * admin_init
212
-     */
213
-    public function admin_init()
214
-    {
215
-        EE_Registry::$i18n_js_strings = array_merge(
216
-            EE_Registry::$i18n_js_strings,
217
-            array(
218
-                'image_confirm'          => esc_html__(
219
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
220
-                    'event_espresso'
221
-                ),
222
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
223
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
224
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
225
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
226
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
227
-            )
228
-        );
229
-    }
230
-
231
-
232
-    /**
233
-     * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
234
-     * accordingly.
235
-     *
236
-     * @param array $response The existing heartbeat response array.
237
-     * @param array $data     The incoming data package.
238
-     * @return array  possibly appended response.
239
-     */
240
-    public function heartbeat_response($response, $data)
241
-    {
242
-        /**
243
-         * check whether count of tickets is approaching the potential
244
-         * limits for the server.
245
-         */
246
-        if (! empty($data['input_count'])) {
247
-            $response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
248
-                $data['input_count']
249
-            );
250
-        }
251
-        return $response;
252
-    }
253
-
254
-
255
-    /**
256
-     * Add per page screen options to the default ticket list table view.
257
-     */
258
-    protected function _add_screen_options_ticket_list_table()
259
-    {
260
-        $this->_per_page_screen_option();
261
-    }
262
-
263
-
264
-    /**
265
-     * @param string $return
266
-     * @param int    $id
267
-     * @param string $new_title
268
-     * @param string $new_slug
269
-     * @return string
270
-     */
271
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
272
-    {
273
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
274
-        // make sure this is only when editing
275
-        if (! empty($id)) {
276
-            $href = EE_Admin_Page::add_query_args_and_nonce(
277
-                array('action' => 'duplicate_event', 'EVT_ID' => $id),
278
-                $this->_admin_base_url
279
-            );
280
-            $title = esc_attr__('Duplicate Event', 'event_espresso');
281
-            $return .= '<a href="'
282
-                       . $href
283
-                       . '" title="'
284
-                       . $title
285
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
286
-                       . $title
287
-                       . '</a>';
288
-        }
289
-        return $return;
290
-    }
291
-
292
-
293
-    /**
294
-     * Set the list table views for the default ticket list table view.
295
-     */
296
-    public function _set_list_table_views_ticket_list_table()
297
-    {
298
-        $this->_views = array(
299
-            'all'     => array(
300
-                'slug'        => 'all',
301
-                'label'       => esc_html__('All', 'event_espresso'),
302
-                'count'       => 0,
303
-                'bulk_action' => array(
304
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
305
-                ),
306
-            ),
307
-            'trashed' => array(
308
-                'slug'        => 'trashed',
309
-                'label'       => esc_html__('Trash', 'event_espresso'),
310
-                'count'       => 0,
311
-                'bulk_action' => array(
312
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
313
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
314
-                ),
315
-            ),
316
-        );
317
-    }
318
-
319
-
320
-    /**
321
-     * Enqueue scripts and styles for the event editor.
322
-     */
323
-    public function load_scripts_styles_edit()
324
-    {
325
-        wp_register_script(
326
-            'ee-event-editor-heartbeat',
327
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
328
-            array('ee_admin_js', 'heartbeat'),
329
-            EVENT_ESPRESSO_VERSION,
330
-            true
331
-        );
332
-        wp_enqueue_script('ee-accounting');
333
-        // styles
334
-        wp_enqueue_style('espresso-ui-theme');
335
-        wp_enqueue_script('event_editor_js');
336
-        wp_enqueue_script('ee-event-editor-heartbeat');
337
-    }
338
-
339
-
340
-    /**
341
-     * Returns template for the additional datetime.
342
-     *
343
-     * @param $template
344
-     * @param $template_args
345
-     * @return mixed
346
-     * @throws DomainException
347
-     */
348
-    public function add_additional_datetime_button($template, $template_args)
349
-    {
350
-        return EEH_Template::display_template(
351
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
352
-            $template_args,
353
-            true
354
-        );
355
-    }
356
-
357
-
358
-    /**
359
-     * Returns the template for cloning a datetime.
360
-     *
361
-     * @param $template
362
-     * @param $template_args
363
-     * @return mixed
364
-     * @throws DomainException
365
-     */
366
-    public function add_datetime_clone_button($template, $template_args)
367
-    {
368
-        return EEH_Template::display_template(
369
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
370
-            $template_args,
371
-            true
372
-        );
373
-    }
374
-
375
-
376
-    /**
377
-     * Returns the template for datetime timezones.
378
-     *
379
-     * @param $template
380
-     * @param $template_args
381
-     * @return mixed
382
-     * @throws DomainException
383
-     */
384
-    public function datetime_timezones_template($template, $template_args)
385
-    {
386
-        return EEH_Template::display_template(
387
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
388
-            $template_args,
389
-            true
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * Sets the views for the default list table view.
396
-     */
397
-    protected function _set_list_table_views_default()
398
-    {
399
-        parent::_set_list_table_views_default();
400
-        $new_views = array(
401
-            'today' => array(
402
-                'slug'        => 'today',
403
-                'label'       => esc_html__('Today', 'event_espresso'),
404
-                'count'       => $this->total_events_today(),
405
-                'bulk_action' => array(
406
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
407
-                ),
408
-            ),
409
-            'month' => array(
410
-                'slug'        => 'month',
411
-                'label'       => esc_html__('This Month', 'event_espresso'),
412
-                'count'       => $this->total_events_this_month(),
413
-                'bulk_action' => array(
414
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
415
-                ),
416
-            ),
417
-        );
418
-        $this->_views = array_merge($this->_views, $new_views);
419
-    }
420
-
421
-
422
-    /**
423
-     * Returns the extra action links for the default list table view.
424
-     *
425
-     * @param array     $action_links
426
-     * @param \EE_Event $event
427
-     * @return array
428
-     * @throws EE_Error
429
-     */
430
-    public function extra_list_table_actions(array $action_links, \EE_Event $event)
431
-    {
432
-        if (EE_Registry::instance()->CAP->current_user_can(
433
-            'ee_read_registrations',
434
-            'espresso_registrations_reports',
435
-            $event->ID()
436
-        )
437
-        ) {
438
-            $reports_query_args = array(
439
-                'action' => 'reports',
440
-                'EVT_ID' => $event->ID(),
441
-            );
442
-            $reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
443
-            $action_links[] = '<a href="'
444
-                              . $reports_link
445
-                              . '" title="'
446
-                              . esc_attr__('View Report', 'event_espresso')
447
-                              . '"><div class="dashicons dashicons-chart-bar"></div></a>'
448
-                              . "\n\t";
449
-        }
450
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
451
-            EE_Registry::instance()->load_helper('MSG_Template');
452
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
453
-                'see_notifications_for',
454
-                null,
455
-                array('EVT_ID' => $event->ID())
456
-            );
457
-        }
458
-        return $action_links;
459
-    }
460
-
461
-
462
-    /**
463
-     * @param $items
464
-     * @return mixed
465
-     */
466
-    public function additional_legend_items($items)
467
-    {
468
-        if (EE_Registry::instance()->CAP->current_user_can(
469
-            'ee_read_registrations',
470
-            'espresso_registrations_reports'
471
-        )
472
-        ) {
473
-            $items['reports'] = array(
474
-                'class' => 'dashicons dashicons-chart-bar',
475
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
476
-            );
477
-        }
478
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
479
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
480
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
481
-                $items['view_related_messages'] = array(
482
-                    'class' => $related_for_icon['css_class'],
483
-                    'desc'  => $related_for_icon['label'],
484
-                );
485
-            }
486
-        }
487
-        return $items;
488
-    }
489
-
490
-
491
-    /**
492
-     * This is the callback method for the duplicate event route
493
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
494
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
495
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
496
-     * After duplication the redirect is to the new event edit page.
497
-     *
498
-     * @return void
499
-     * @access protected
500
-     * @throws EE_Error If EE_Event is not available with given ID
501
-     */
502
-    protected function _duplicate_event()
503
-    {
504
-        // first make sure the ID for the event is in the request.
505
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
506
-        if (! isset($this->_req_data['EVT_ID'])) {
507
-            EE_Error::add_error(
508
-                esc_html__(
509
-                    'In order to duplicate an event an Event ID is required.  None was given.',
510
-                    'event_espresso'
511
-                ),
512
-                __FILE__,
513
-                __FUNCTION__,
514
-                __LINE__
515
-            );
516
-            $this->_redirect_after_action(false, '', '', array(), true);
517
-            return;
518
-        }
519
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
520
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
521
-        if (! $orig_event instanceof EE_Event) {
522
-            throw new EE_Error(
523
-                sprintf(
524
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
525
-                    $this->_req_data['EVT_ID']
526
-                )
527
-            );
528
-        }
529
-        // k now let's clone the $orig_event before getting relations
530
-        $new_event = clone $orig_event;
531
-        // original datetimes
532
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
533
-        // other original relations
534
-        $orig_ven = $orig_event->get_many_related('Venue');
535
-        // reset the ID and modify other details to make it clear this is a dupe
536
-        $new_event->set('EVT_ID', 0);
537
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
538
-        $new_event->set('EVT_name', $new_name);
539
-        $new_event->set(
540
-            'EVT_slug',
541
-            wp_unique_post_slug(
542
-                sanitize_title($orig_event->name()),
543
-                0,
544
-                'publish',
545
-                'espresso_events',
546
-                0
547
-            )
548
-        );
549
-        $new_event->set('status', 'draft');
550
-        // duplicate discussion settings
551
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
552
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
553
-        // save the new event
554
-        $new_event->save();
555
-        // venues
556
-        foreach ($orig_ven as $ven) {
557
-            $new_event->_add_relation_to($ven, 'Venue');
558
-        }
559
-        $new_event->save();
560
-        // now we need to get the question group relations and handle that
561
-        // first primary question groups
562
-        $orig_primary_qgs = $orig_event->get_many_related(
563
-            'Question_Group',
564
-            array(array('Event_Question_Group.EQG_primary' => 1))
565
-        );
566
-        if (! empty($orig_primary_qgs)) {
567
-            foreach ($orig_primary_qgs as $id => $obj) {
568
-                if ($obj instanceof EE_Question_Group) {
569
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
570
-                }
571
-            }
572
-        }
573
-        // next additional attendee question groups
574
-        $orig_additional_qgs = $orig_event->get_many_related(
575
-            'Question_Group',
576
-            array(array('Event_Question_Group.EQG_primary' => 0))
577
-        );
578
-        if (! empty($orig_additional_qgs)) {
579
-            foreach ($orig_additional_qgs as $id => $obj) {
580
-                if ($obj instanceof EE_Question_Group) {
581
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
582
-                }
583
-            }
584
-        }
585
-
586
-        $new_event->save();
587
-
588
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
589
-        $cloned_tickets = array();
590
-        foreach ($orig_datetimes as $orig_dtt) {
591
-            if (! $orig_dtt instanceof EE_Datetime) {
592
-                continue;
593
-            }
594
-            $new_dtt = clone $orig_dtt;
595
-            $orig_tkts = $orig_dtt->tickets();
596
-            // save new dtt then add to event
597
-            $new_dtt->set('DTT_ID', 0);
598
-            $new_dtt->set('DTT_sold', 0);
599
-            $new_dtt->set_reserved(0);
600
-            $new_dtt->save();
601
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
602
-            $new_event->save();
603
-            // now let's get the ticket relations setup.
604
-            foreach ((array) $orig_tkts as $orig_tkt) {
605
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
606
-                if (! $orig_tkt instanceof EE_Ticket) {
607
-                    continue;
608
-                }
609
-                // is this ticket archived?  If it is then let's skip
610
-                if ($orig_tkt->get('TKT_deleted')) {
611
-                    continue;
612
-                }
613
-                // does this original ticket already exist in the clone_tickets cache?
614
-                //  If so we'll just use the new ticket from it.
615
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
616
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
617
-                } else {
618
-                    $new_tkt = clone $orig_tkt;
619
-                    // get relations on the $orig_tkt that we need to setup.
620
-                    $orig_prices = $orig_tkt->prices();
621
-                    $new_tkt->set('TKT_ID', 0);
622
-                    $new_tkt->set('TKT_sold', 0);
623
-                    $new_tkt->set('TKT_reserved', 0);
624
-                    $new_tkt->save(); // make sure new ticket has ID.
625
-                    // price relations on new ticket need to be setup.
626
-                    foreach ($orig_prices as $orig_price) {
627
-                        $new_price = clone $orig_price;
628
-                        $new_price->set('PRC_ID', 0);
629
-                        $new_price->save();
630
-                        $new_tkt->_add_relation_to($new_price, 'Price');
631
-                        $new_tkt->save();
632
-                    }
633
-
634
-                    do_action(
635
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
636
-                        $orig_tkt,
637
-                        $new_tkt,
638
-                        $orig_prices,
639
-                        $orig_event,
640
-                        $orig_dtt,
641
-                        $new_dtt
642
-                    );
643
-                }
644
-                // k now we can add the new ticket as a relation to the new datetime
645
-                // and make sure its added to our cached $cloned_tickets array
646
-                // for use with later datetimes that have the same ticket.
647
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
648
-                $new_dtt->save();
649
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
650
-            }
651
-        }
652
-        // clone taxonomy information
653
-        $taxonomies_to_clone_with = apply_filters(
654
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
655
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
656
-        );
657
-        // get terms for original event (notice)
658
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
659
-        // loop through terms and add them to new event.
660
-        foreach ($orig_terms as $term) {
661
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
662
-        }
663
-
664
-        // duplicate other core WP_Post items for this event.
665
-        // post thumbnail (feature image).
666
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
667
-        if ($feature_image_id) {
668
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
669
-        }
670
-
671
-        // duplicate page_template setting
672
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
673
-        if ($page_template) {
674
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
675
-        }
676
-
677
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
678
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
679
-        if ($new_event->ID()) {
680
-            $redirect_args = array(
681
-                'post'   => $new_event->ID(),
682
-                'action' => 'edit',
683
-            );
684
-            EE_Error::add_success(
685
-                esc_html__(
686
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
687
-                    'event_espresso'
688
-                )
689
-            );
690
-        } else {
691
-            $redirect_args = array(
692
-                'action' => 'default',
693
-            );
694
-            EE_Error::add_error(
695
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
696
-                __FILE__,
697
-                __FUNCTION__,
698
-                __LINE__
699
-            );
700
-        }
701
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
702
-    }
703
-
704
-
705
-    /**
706
-     * Generates output for the import page.
707
-     *
708
-     * @throws DomainException
709
-     */
710
-    protected function _import_page()
711
-    {
712
-        $title = esc_html__('Import', 'event_espresso');
713
-        $intro = esc_html__(
714
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
715
-            'event_espresso'
716
-        );
717
-        $form_url = EVENTS_ADMIN_URL;
718
-        $action = 'import_events';
719
-        $type = 'csv';
720
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
721
-            $title,
722
-            $intro,
723
-            $form_url,
724
-            $action,
725
-            $type
726
-        );
727
-        $this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
728
-            array('action' => 'sample_export_file'),
729
-            $this->_admin_base_url
730
-        );
731
-        $content = EEH_Template::display_template(
732
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
733
-            $this->_template_args,
734
-            true
735
-        );
736
-        $this->_template_args['admin_page_content'] = $content;
737
-        $this->display_admin_page_with_sidebar();
738
-    }
739
-
740
-
741
-    /**
742
-     * _import_events
743
-     * This handles displaying the screen and running imports for importing events.
744
-     *
745
-     * @return void
746
-     */
747
-    protected function _import_events()
748
-    {
749
-        require_once(EE_CLASSES . 'EE_Import.class.php');
750
-        $success = EE_Import::instance()->import();
751
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
752
-    }
753
-
754
-
755
-    /**
756
-     * _events_export
757
-     * Will export all (or just the given event) to a Excel compatible file.
758
-     *
759
-     * @access protected
760
-     * @return void
761
-     */
762
-    protected function _events_export()
763
-    {
764
-        if (isset($this->_req_data['EVT_ID'])) {
765
-            $event_ids = $this->_req_data['EVT_ID'];
766
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
767
-            $event_ids = $this->_req_data['EVT_IDs'];
768
-        } else {
769
-            $event_ids = null;
770
-        }
771
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
772
-        $new_request_args = array(
773
-            'export' => 'report',
774
-            'action' => 'all_event_data',
775
-            'EVT_ID' => $event_ids,
776
-        );
777
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
778
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
779
-            require_once(EE_CLASSES . 'EE_Export.class.php');
780
-            $EE_Export = EE_Export::instance($this->_req_data);
781
-            $EE_Export->export();
782
-        }
783
-    }
784
-
785
-
786
-    /**
787
-     * handle category exports()
788
-     *
789
-     * @return void
790
-     */
791
-    protected function _categories_export()
792
-    {
793
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
794
-        $new_request_args = array(
795
-            'export'       => 'report',
796
-            'action'       => 'categories',
797
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
798
-        );
799
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
800
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
801
-            require_once(EE_CLASSES . 'EE_Export.class.php');
802
-            $EE_Export = EE_Export::instance($this->_req_data);
803
-            $EE_Export->export();
804
-        }
805
-    }
806
-
807
-
808
-    /**
809
-     * Creates a sample CSV file for importing
810
-     */
811
-    protected function _sample_export_file()
812
-    {
813
-        // require_once(EE_CLASSES . 'EE_Export.class.php');
814
-        EE_Export::instance()->export_sample();
815
-    }
816
-
817
-
818
-    /*************        Template Settings        *************/
819
-    /**
820
-     * Generates template settings page output
821
-     *
822
-     * @throws DomainException
823
-     * @throws EE_Error
824
-     */
825
-    protected function _template_settings()
826
-    {
827
-        $this->_template_args['values'] = $this->_yes_no_values;
828
-        /**
829
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
830
-         * from General_Settings_Admin_Page to here.
831
-         */
832
-        $this->_template_args = apply_filters(
833
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
834
-            $this->_template_args
835
-        );
836
-        $this->_set_add_edit_form_tags('update_template_settings');
837
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
838
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
839
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
840
-            $this->_template_args,
841
-            true
842
-        );
843
-        $this->display_admin_page_with_sidebar();
844
-    }
845
-
846
-
847
-    /**
848
-     * Handler for updating template settings.
849
-     *
850
-     * @throws InvalidInterfaceException
851
-     * @throws InvalidDataTypeException
852
-     * @throws InvalidArgumentException
853
-     */
854
-    protected function _update_template_settings()
855
-    {
856
-        /**
857
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
858
-         * from General_Settings_Admin_Page to here.
859
-         */
860
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
861
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
862
-            EE_Registry::instance()->CFG->template_settings,
863
-            $this->_req_data
864
-        );
865
-        // update custom post type slugs and detect if we need to flush rewrite rules
866
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
867
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
868
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
869
-            : EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
870
-        $what = 'Template Settings';
871
-        $success = $this->_update_espresso_configuration(
872
-            $what,
873
-            EE_Registry::instance()->CFG->template_settings,
874
-            __FILE__,
875
-            __FUNCTION__,
876
-            __LINE__
877
-        );
878
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
879
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
880
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
881
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
882
-            );
883
-            $rewrite_rules->flush();
884
-        }
885
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
886
-    }
887
-
888
-
889
-    /**
890
-     * _premium_event_editor_meta_boxes
891
-     * add all metaboxes related to the event_editor
892
-     *
893
-     * @access protected
894
-     * @return void
895
-     * @throws EE_Error
896
-     */
897
-    protected function _premium_event_editor_meta_boxes()
898
-    {
899
-        $this->verify_cpt_object();
900
-        add_meta_box(
901
-            'espresso_event_editor_event_options',
902
-            esc_html__('Event Registration Options', 'event_espresso'),
903
-            array($this, 'registration_options_meta_box'),
904
-            $this->page_slug,
905
-            'side',
906
-            'core'
907
-        );
908
-    }
909
-
910
-
911
-    /**
912
-     * override caf metabox
913
-     *
914
-     * @return void
915
-     * @throws DomainException
916
-     */
917
-    public function registration_options_meta_box()
918
-    {
919
-        $yes_no_values = array(
920
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
921
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
922
-        );
923
-        $default_reg_status_values = EEM_Registration::reg_status_array(
924
-            array(
925
-                EEM_Registration::status_id_cancelled,
926
-                EEM_Registration::status_id_declined,
927
-                EEM_Registration::status_id_incomplete,
928
-                EEM_Registration::status_id_wait_list,
929
-            ),
930
-            true
931
-        );
932
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
933
-        $template_args['_event'] = $this->_cpt_model_obj;
934
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
935
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
936
-            'default_reg_status',
937
-            $default_reg_status_values,
938
-            $this->_cpt_model_obj->default_registration_status()
939
-        );
940
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
941
-            'display_desc',
942
-            $yes_no_values,
943
-            $this->_cpt_model_obj->display_description()
944
-        );
945
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
946
-            'display_ticket_selector',
947
-            $yes_no_values,
948
-            $this->_cpt_model_obj->display_ticket_selector(),
949
-            '',
950
-            '',
951
-            false
952
-        );
953
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
954
-            'EVT_default_registration_status',
955
-            $default_reg_status_values,
956
-            $this->_cpt_model_obj->default_registration_status()
957
-        );
958
-        $template_args['additional_registration_options'] = apply_filters(
959
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
960
-            '',
961
-            $template_args,
962
-            $yes_no_values,
963
-            $default_reg_status_values
964
-        );
965
-        EEH_Template::display_template(
966
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
967
-            $template_args
968
-        );
969
-    }
970
-
971
-
972
-
973
-    /**
974
-     * wp_list_table_mods for caf
975
-     * ============================
976
-     */
977
-    /**
978
-     * hook into list table filters and provide filters for caffeinated list table
979
-     *
980
-     * @param  array $old_filters    any existing filters present
981
-     * @param  array $list_table_obj the list table object
982
-     * @return array                  new filters
983
-     */
984
-    public function list_table_filters($old_filters, $list_table_obj)
985
-    {
986
-        $filters = array();
987
-        // first month/year filters
988
-        $filters[] = $this->espresso_event_months_dropdown();
989
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
990
-        // active status dropdown
991
-        if ($status !== 'draft') {
992
-            $filters[] = $this->active_status_dropdown(
993
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
994
-            );
995
-        }
996
-        // category filter
997
-        $filters[] = $this->category_dropdown();
998
-        return array_merge($old_filters, $filters);
999
-    }
1000
-
1001
-
1002
-    /**
1003
-     * espresso_event_months_dropdown
1004
-     *
1005
-     * @access public
1006
-     * @return string                dropdown listing month/year selections for events.
1007
-     */
1008
-    public function espresso_event_months_dropdown()
1009
-    {
1010
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
1011
-        // Note we need to include any other filters that are set!
1012
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1013
-        // categories?
1014
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1015
-            ? $this->_req_data['EVT_CAT']
1016
-            : null;
1017
-        // active status?
1018
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1019
-        $cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1020
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * returns a list of "active" statuses on the event
1026
-     *
1027
-     * @param  string $current_value whatever the current active status is
1028
-     * @return string
1029
-     */
1030
-    public function active_status_dropdown($current_value = '')
1031
-    {
1032
-        $select_name = 'active_status';
1033
-        $values = array(
1034
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1035
-            'active'   => esc_html__('Active', 'event_espresso'),
1036
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1037
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1038
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1039
-        );
1040
-        $id = 'id="espresso-active-status-dropdown-filter"';
1041
-        $class = 'wide';
1042
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     * output a dropdown of the categories for the category filter on the event admin list table
1048
-     *
1049
-     * @access  public
1050
-     * @return string html
1051
-     */
1052
-    public function category_dropdown()
1053
-    {
1054
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1055
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1056
-    }
1057
-
1058
-
1059
-    /**
1060
-     * get total number of events today
1061
-     *
1062
-     * @access public
1063
-     * @return int
1064
-     * @throws EE_Error
1065
-     */
1066
-    public function total_events_today()
1067
-    {
1068
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1069
-            'DTT_EVT_start',
1070
-            date('Y-m-d') . ' 00:00:00',
1071
-            'Y-m-d H:i:s',
1072
-            'UTC'
1073
-        );
1074
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1075
-            'DTT_EVT_start',
1076
-            date('Y-m-d') . ' 23:59:59',
1077
-            'Y-m-d H:i:s',
1078
-            'UTC'
1079
-        );
1080
-        $where = array(
1081
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1082
-        );
1083
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1084
-        return $count;
1085
-    }
1086
-
1087
-
1088
-    /**
1089
-     * get total number of events this month
1090
-     *
1091
-     * @access public
1092
-     * @return int
1093
-     * @throws EE_Error
1094
-     */
1095
-    public function total_events_this_month()
1096
-    {
1097
-        // Dates
1098
-        $this_year_r = date('Y');
1099
-        $this_month_r = date('m');
1100
-        $days_this_month = date('t');
1101
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1102
-            'DTT_EVT_start',
1103
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1104
-            'Y-m-d H:i:s',
1105
-            'UTC'
1106
-        );
1107
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1108
-            'DTT_EVT_start',
1109
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1110
-            'Y-m-d H:i:s',
1111
-            'UTC'
1112
-        );
1113
-        $where = array(
1114
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1115
-        );
1116
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1117
-        return $count;
1118
-    }
1119
-
1120
-
1121
-    /** DEFAULT TICKETS STUFF **/
1122
-
1123
-    /**
1124
-     * Output default tickets list table view.
1125
-     */
1126
-    public function _tickets_overview_list_table()
1127
-    {
1128
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1129
-        $this->display_admin_list_table_page_with_no_sidebar();
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     * @param int  $per_page
1135
-     * @param bool $count
1136
-     * @param bool $trashed
1137
-     * @return \EE_Soft_Delete_Base_Class[]|int
1138
-     */
1139
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1140
-    {
1141
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1142
-        $order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1143
-        switch ($orderby) {
1144
-            case 'TKT_name':
1145
-                $orderby = array('TKT_name' => $order);
1146
-                break;
1147
-            case 'TKT_price':
1148
-                $orderby = array('TKT_price' => $order);
1149
-                break;
1150
-            case 'TKT_uses':
1151
-                $orderby = array('TKT_uses' => $order);
1152
-                break;
1153
-            case 'TKT_min':
1154
-                $orderby = array('TKT_min' => $order);
1155
-                break;
1156
-            case 'TKT_max':
1157
-                $orderby = array('TKT_max' => $order);
1158
-                break;
1159
-            case 'TKT_qty':
1160
-                $orderby = array('TKT_qty' => $order);
1161
-                break;
1162
-        }
1163
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1164
-            ? $this->_req_data['paged']
1165
-            : 1;
1166
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1167
-            ? $this->_req_data['perpage']
1168
-            : $per_page;
1169
-        $_where = array(
1170
-            'TKT_is_default' => 1,
1171
-            'TKT_deleted'    => $trashed,
1172
-        );
1173
-        $offset = ($current_page - 1) * $per_page;
1174
-        $limit = array($offset, $per_page);
1175
-        if (isset($this->_req_data['s'])) {
1176
-            $sstr = '%' . $this->_req_data['s'] . '%';
1177
-            $_where['OR'] = array(
1178
-                'TKT_name'        => array('LIKE', $sstr),
1179
-                'TKT_description' => array('LIKE', $sstr),
1180
-            );
1181
-        }
1182
-        $query_params = array(
1183
-            $_where,
1184
-            'order_by' => $orderby,
1185
-            'limit'    => $limit,
1186
-            'group_by' => 'TKT_ID',
1187
-        );
1188
-        if ($count) {
1189
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1190
-        } else {
1191
-            return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1192
-        }
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * @param bool $trash
1198
-     * @throws EE_Error
1199
-     */
1200
-    protected function _trash_or_restore_ticket($trash = false)
1201
-    {
1202
-        $success = 1;
1203
-        $TKT = EEM_Ticket::instance();
1204
-        // checkboxes?
1205
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1206
-            // if array has more than one element then success message should be plural
1207
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1208
-            // cycle thru the boxes
1209
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1210
-                if ($trash) {
1211
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1212
-                        $success = 0;
1213
-                    }
1214
-                } else {
1215
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1216
-                        $success = 0;
1217
-                    }
1218
-                }
1219
-            }
1220
-        } else {
1221
-            // grab single id and trash
1222
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1223
-            if ($trash) {
1224
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1225
-                    $success = 0;
1226
-                }
1227
-            } else {
1228
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1229
-                    $success = 0;
1230
-                }
1231
-            }
1232
-        }
1233
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1234
-        $query_args = array(
1235
-            'action' => 'ticket_list_table',
1236
-            'status' => $trash ? '' : 'trashed',
1237
-        );
1238
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1239
-    }
1240
-
1241
-
1242
-    /**
1243
-     * Handles trashing default ticket.
1244
-     */
1245
-    protected function _delete_ticket()
1246
-    {
1247
-        $success = 1;
1248
-        // checkboxes?
1249
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1250
-            // if array has more than one element then success message should be plural
1251
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1252
-            // cycle thru the boxes
1253
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1254
-                // delete
1255
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1256
-                    $success = 0;
1257
-                }
1258
-            }
1259
-        } else {
1260
-            // grab single id and trash
1261
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1262
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1263
-                $success = 0;
1264
-            }
1265
-        }
1266
-        $action_desc = 'deleted';
1267
-        $query_args = array(
1268
-            'action' => 'ticket_list_table',
1269
-            'status' => 'trashed',
1270
-        );
1271
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1272
-        if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1273
-            array(array('TKT_is_default' => 1)),
1274
-            'TKT_ID',
1275
-            true
1276
-        )
1277
-        ) {
1278
-            $query_args = array();
1279
-        }
1280
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1281
-    }
1282
-
1283
-
1284
-    /**
1285
-     * @param int $TKT_ID
1286
-     * @return bool|int
1287
-     * @throws EE_Error
1288
-     */
1289
-    protected function _delete_the_ticket($TKT_ID)
1290
-    {
1291
-        $tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1292
-        $tkt->_remove_relations('Datetime');
1293
-        // delete all related prices first
1294
-        $tkt->delete_related_permanently('Price');
1295
-        return $tkt->delete_permanently();
1296
-    }
19
+	/**
20
+	 * Extend_Events_Admin_Page constructor.
21
+	 *
22
+	 * @param bool $routing
23
+	 */
24
+	public function __construct($routing = true)
25
+	{
26
+		parent::__construct($routing);
27
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
+		}
32
+	}
33
+
34
+
35
+	/**
36
+	 * Sets routes.
37
+	 */
38
+	protected function _extend_page_config()
39
+	{
40
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
+		// is there a evt_id in the request?
42
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
43
+			? $this->_req_data['EVT_ID']
44
+			: 0;
45
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
46
+		// tkt_id?
47
+		$tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
48
+			? $this->_req_data['TKT_ID']
49
+			: 0;
50
+		$new_page_routes = array(
51
+			'duplicate_event'          => array(
52
+				'func'       => '_duplicate_event',
53
+				'capability' => 'ee_edit_event',
54
+				'obj_id'     => $evt_id,
55
+				'noheader'   => true,
56
+			),
57
+			'ticket_list_table'        => array(
58
+				'func'       => '_tickets_overview_list_table',
59
+				'capability' => 'ee_read_default_tickets',
60
+			),
61
+			'trash_ticket'             => array(
62
+				'func'       => '_trash_or_restore_ticket',
63
+				'capability' => 'ee_delete_default_ticket',
64
+				'obj_id'     => $tkt_id,
65
+				'noheader'   => true,
66
+				'args'       => array('trash' => true),
67
+			),
68
+			'trash_tickets'            => array(
69
+				'func'       => '_trash_or_restore_ticket',
70
+				'capability' => 'ee_delete_default_tickets',
71
+				'noheader'   => true,
72
+				'args'       => array('trash' => true),
73
+			),
74
+			'restore_ticket'           => array(
75
+				'func'       => '_trash_or_restore_ticket',
76
+				'capability' => 'ee_delete_default_ticket',
77
+				'obj_id'     => $tkt_id,
78
+				'noheader'   => true,
79
+			),
80
+			'restore_tickets'          => array(
81
+				'func'       => '_trash_or_restore_ticket',
82
+				'capability' => 'ee_delete_default_tickets',
83
+				'noheader'   => true,
84
+			),
85
+			'delete_ticket'            => array(
86
+				'func'       => '_delete_ticket',
87
+				'capability' => 'ee_delete_default_ticket',
88
+				'obj_id'     => $tkt_id,
89
+				'noheader'   => true,
90
+			),
91
+			'delete_tickets'           => array(
92
+				'func'       => '_delete_ticket',
93
+				'capability' => 'ee_delete_default_tickets',
94
+				'noheader'   => true,
95
+			),
96
+			'import_page'              => array(
97
+				'func'       => '_import_page',
98
+				'capability' => 'import',
99
+			),
100
+			'import'                   => array(
101
+				'func'       => '_import_events',
102
+				'capability' => 'import',
103
+				'noheader'   => true,
104
+			),
105
+			'import_events'            => array(
106
+				'func'       => '_import_events',
107
+				'capability' => 'import',
108
+				'noheader'   => true,
109
+			),
110
+			'export_events'            => array(
111
+				'func'       => '_events_export',
112
+				'capability' => 'export',
113
+				'noheader'   => true,
114
+			),
115
+			'export_categories'        => array(
116
+				'func'       => '_categories_export',
117
+				'capability' => 'export',
118
+				'noheader'   => true,
119
+			),
120
+			'sample_export_file'       => array(
121
+				'func'       => '_sample_export_file',
122
+				'capability' => 'export',
123
+				'noheader'   => true,
124
+			),
125
+			'update_template_settings' => array(
126
+				'func'       => '_update_template_settings',
127
+				'capability' => 'manage_options',
128
+				'noheader'   => true,
129
+			),
130
+		);
131
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
132
+		// partial route/config override
133
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
134
+		$this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
135
+		$this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
136
+		$this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
137
+		$this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
138
+		$this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
139
+		// add tickets tab but only if there are more than one default ticket!
140
+		$tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
141
+			array(array('TKT_is_default' => 1)),
142
+			'TKT_ID',
143
+			true
144
+		);
145
+		if ($tkt_count > 1) {
146
+			$new_page_config = array(
147
+				'ticket_list_table' => array(
148
+					'nav'           => array(
149
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
150
+						'order' => 60,
151
+					),
152
+					'list_table'    => 'Tickets_List_Table',
153
+					'require_nonce' => false,
154
+				),
155
+			);
156
+		}
157
+		// template settings
158
+		$new_page_config['template_settings'] = array(
159
+			'nav'           => array(
160
+				'label' => esc_html__('Templates', 'event_espresso'),
161
+				'order' => 30,
162
+			),
163
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
164
+			'help_tabs'     => array(
165
+				'general_settings_templates_help_tab' => array(
166
+					'title'    => esc_html__('Templates', 'event_espresso'),
167
+					'filename' => 'general_settings_templates',
168
+				),
169
+			),
170
+			'help_tour'     => array('Templates_Help_Tour'),
171
+			'require_nonce' => false,
172
+		);
173
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
174
+		// add filters and actions
175
+		// modifying _views
176
+		add_filter(
177
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
178
+			array($this, 'add_additional_datetime_button'),
179
+			10,
180
+			2
181
+		);
182
+		add_filter(
183
+			'FHEE_event_datetime_metabox_clone_button_template',
184
+			array($this, 'add_datetime_clone_button'),
185
+			10,
186
+			2
187
+		);
188
+		add_filter(
189
+			'FHEE_event_datetime_metabox_timezones_template',
190
+			array($this, 'datetime_timezones_template'),
191
+			10,
192
+			2
193
+		);
194
+		// filters for event list table
195
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
196
+		add_filter(
197
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
198
+			array($this, 'extra_list_table_actions'),
199
+			10,
200
+			2
201
+		);
202
+		// legend item
203
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
204
+		add_action('admin_init', array($this, 'admin_init'));
205
+		// heartbeat stuff
206
+		add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
207
+	}
208
+
209
+
210
+	/**
211
+	 * admin_init
212
+	 */
213
+	public function admin_init()
214
+	{
215
+		EE_Registry::$i18n_js_strings = array_merge(
216
+			EE_Registry::$i18n_js_strings,
217
+			array(
218
+				'image_confirm'          => esc_html__(
219
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
220
+					'event_espresso'
221
+				),
222
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
223
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
224
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
225
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
226
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
227
+			)
228
+		);
229
+	}
230
+
231
+
232
+	/**
233
+	 * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
234
+	 * accordingly.
235
+	 *
236
+	 * @param array $response The existing heartbeat response array.
237
+	 * @param array $data     The incoming data package.
238
+	 * @return array  possibly appended response.
239
+	 */
240
+	public function heartbeat_response($response, $data)
241
+	{
242
+		/**
243
+		 * check whether count of tickets is approaching the potential
244
+		 * limits for the server.
245
+		 */
246
+		if (! empty($data['input_count'])) {
247
+			$response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
248
+				$data['input_count']
249
+			);
250
+		}
251
+		return $response;
252
+	}
253
+
254
+
255
+	/**
256
+	 * Add per page screen options to the default ticket list table view.
257
+	 */
258
+	protected function _add_screen_options_ticket_list_table()
259
+	{
260
+		$this->_per_page_screen_option();
261
+	}
262
+
263
+
264
+	/**
265
+	 * @param string $return
266
+	 * @param int    $id
267
+	 * @param string $new_title
268
+	 * @param string $new_slug
269
+	 * @return string
270
+	 */
271
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
272
+	{
273
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
274
+		// make sure this is only when editing
275
+		if (! empty($id)) {
276
+			$href = EE_Admin_Page::add_query_args_and_nonce(
277
+				array('action' => 'duplicate_event', 'EVT_ID' => $id),
278
+				$this->_admin_base_url
279
+			);
280
+			$title = esc_attr__('Duplicate Event', 'event_espresso');
281
+			$return .= '<a href="'
282
+					   . $href
283
+					   . '" title="'
284
+					   . $title
285
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
286
+					   . $title
287
+					   . '</a>';
288
+		}
289
+		return $return;
290
+	}
291
+
292
+
293
+	/**
294
+	 * Set the list table views for the default ticket list table view.
295
+	 */
296
+	public function _set_list_table_views_ticket_list_table()
297
+	{
298
+		$this->_views = array(
299
+			'all'     => array(
300
+				'slug'        => 'all',
301
+				'label'       => esc_html__('All', 'event_espresso'),
302
+				'count'       => 0,
303
+				'bulk_action' => array(
304
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
305
+				),
306
+			),
307
+			'trashed' => array(
308
+				'slug'        => 'trashed',
309
+				'label'       => esc_html__('Trash', 'event_espresso'),
310
+				'count'       => 0,
311
+				'bulk_action' => array(
312
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
313
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
314
+				),
315
+			),
316
+		);
317
+	}
318
+
319
+
320
+	/**
321
+	 * Enqueue scripts and styles for the event editor.
322
+	 */
323
+	public function load_scripts_styles_edit()
324
+	{
325
+		wp_register_script(
326
+			'ee-event-editor-heartbeat',
327
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
328
+			array('ee_admin_js', 'heartbeat'),
329
+			EVENT_ESPRESSO_VERSION,
330
+			true
331
+		);
332
+		wp_enqueue_script('ee-accounting');
333
+		// styles
334
+		wp_enqueue_style('espresso-ui-theme');
335
+		wp_enqueue_script('event_editor_js');
336
+		wp_enqueue_script('ee-event-editor-heartbeat');
337
+	}
338
+
339
+
340
+	/**
341
+	 * Returns template for the additional datetime.
342
+	 *
343
+	 * @param $template
344
+	 * @param $template_args
345
+	 * @return mixed
346
+	 * @throws DomainException
347
+	 */
348
+	public function add_additional_datetime_button($template, $template_args)
349
+	{
350
+		return EEH_Template::display_template(
351
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
352
+			$template_args,
353
+			true
354
+		);
355
+	}
356
+
357
+
358
+	/**
359
+	 * Returns the template for cloning a datetime.
360
+	 *
361
+	 * @param $template
362
+	 * @param $template_args
363
+	 * @return mixed
364
+	 * @throws DomainException
365
+	 */
366
+	public function add_datetime_clone_button($template, $template_args)
367
+	{
368
+		return EEH_Template::display_template(
369
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
370
+			$template_args,
371
+			true
372
+		);
373
+	}
374
+
375
+
376
+	/**
377
+	 * Returns the template for datetime timezones.
378
+	 *
379
+	 * @param $template
380
+	 * @param $template_args
381
+	 * @return mixed
382
+	 * @throws DomainException
383
+	 */
384
+	public function datetime_timezones_template($template, $template_args)
385
+	{
386
+		return EEH_Template::display_template(
387
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
388
+			$template_args,
389
+			true
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * Sets the views for the default list table view.
396
+	 */
397
+	protected function _set_list_table_views_default()
398
+	{
399
+		parent::_set_list_table_views_default();
400
+		$new_views = array(
401
+			'today' => array(
402
+				'slug'        => 'today',
403
+				'label'       => esc_html__('Today', 'event_espresso'),
404
+				'count'       => $this->total_events_today(),
405
+				'bulk_action' => array(
406
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
407
+				),
408
+			),
409
+			'month' => array(
410
+				'slug'        => 'month',
411
+				'label'       => esc_html__('This Month', 'event_espresso'),
412
+				'count'       => $this->total_events_this_month(),
413
+				'bulk_action' => array(
414
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
415
+				),
416
+			),
417
+		);
418
+		$this->_views = array_merge($this->_views, $new_views);
419
+	}
420
+
421
+
422
+	/**
423
+	 * Returns the extra action links for the default list table view.
424
+	 *
425
+	 * @param array     $action_links
426
+	 * @param \EE_Event $event
427
+	 * @return array
428
+	 * @throws EE_Error
429
+	 */
430
+	public function extra_list_table_actions(array $action_links, \EE_Event $event)
431
+	{
432
+		if (EE_Registry::instance()->CAP->current_user_can(
433
+			'ee_read_registrations',
434
+			'espresso_registrations_reports',
435
+			$event->ID()
436
+		)
437
+		) {
438
+			$reports_query_args = array(
439
+				'action' => 'reports',
440
+				'EVT_ID' => $event->ID(),
441
+			);
442
+			$reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
443
+			$action_links[] = '<a href="'
444
+							  . $reports_link
445
+							  . '" title="'
446
+							  . esc_attr__('View Report', 'event_espresso')
447
+							  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
448
+							  . "\n\t";
449
+		}
450
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
451
+			EE_Registry::instance()->load_helper('MSG_Template');
452
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
453
+				'see_notifications_for',
454
+				null,
455
+				array('EVT_ID' => $event->ID())
456
+			);
457
+		}
458
+		return $action_links;
459
+	}
460
+
461
+
462
+	/**
463
+	 * @param $items
464
+	 * @return mixed
465
+	 */
466
+	public function additional_legend_items($items)
467
+	{
468
+		if (EE_Registry::instance()->CAP->current_user_can(
469
+			'ee_read_registrations',
470
+			'espresso_registrations_reports'
471
+		)
472
+		) {
473
+			$items['reports'] = array(
474
+				'class' => 'dashicons dashicons-chart-bar',
475
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
476
+			);
477
+		}
478
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
479
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
480
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
481
+				$items['view_related_messages'] = array(
482
+					'class' => $related_for_icon['css_class'],
483
+					'desc'  => $related_for_icon['label'],
484
+				);
485
+			}
486
+		}
487
+		return $items;
488
+	}
489
+
490
+
491
+	/**
492
+	 * This is the callback method for the duplicate event route
493
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
494
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
495
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
496
+	 * After duplication the redirect is to the new event edit page.
497
+	 *
498
+	 * @return void
499
+	 * @access protected
500
+	 * @throws EE_Error If EE_Event is not available with given ID
501
+	 */
502
+	protected function _duplicate_event()
503
+	{
504
+		// first make sure the ID for the event is in the request.
505
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
506
+		if (! isset($this->_req_data['EVT_ID'])) {
507
+			EE_Error::add_error(
508
+				esc_html__(
509
+					'In order to duplicate an event an Event ID is required.  None was given.',
510
+					'event_espresso'
511
+				),
512
+				__FILE__,
513
+				__FUNCTION__,
514
+				__LINE__
515
+			);
516
+			$this->_redirect_after_action(false, '', '', array(), true);
517
+			return;
518
+		}
519
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
520
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
521
+		if (! $orig_event instanceof EE_Event) {
522
+			throw new EE_Error(
523
+				sprintf(
524
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
525
+					$this->_req_data['EVT_ID']
526
+				)
527
+			);
528
+		}
529
+		// k now let's clone the $orig_event before getting relations
530
+		$new_event = clone $orig_event;
531
+		// original datetimes
532
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
533
+		// other original relations
534
+		$orig_ven = $orig_event->get_many_related('Venue');
535
+		// reset the ID and modify other details to make it clear this is a dupe
536
+		$new_event->set('EVT_ID', 0);
537
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
538
+		$new_event->set('EVT_name', $new_name);
539
+		$new_event->set(
540
+			'EVT_slug',
541
+			wp_unique_post_slug(
542
+				sanitize_title($orig_event->name()),
543
+				0,
544
+				'publish',
545
+				'espresso_events',
546
+				0
547
+			)
548
+		);
549
+		$new_event->set('status', 'draft');
550
+		// duplicate discussion settings
551
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
552
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
553
+		// save the new event
554
+		$new_event->save();
555
+		// venues
556
+		foreach ($orig_ven as $ven) {
557
+			$new_event->_add_relation_to($ven, 'Venue');
558
+		}
559
+		$new_event->save();
560
+		// now we need to get the question group relations and handle that
561
+		// first primary question groups
562
+		$orig_primary_qgs = $orig_event->get_many_related(
563
+			'Question_Group',
564
+			array(array('Event_Question_Group.EQG_primary' => 1))
565
+		);
566
+		if (! empty($orig_primary_qgs)) {
567
+			foreach ($orig_primary_qgs as $id => $obj) {
568
+				if ($obj instanceof EE_Question_Group) {
569
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
570
+				}
571
+			}
572
+		}
573
+		// next additional attendee question groups
574
+		$orig_additional_qgs = $orig_event->get_many_related(
575
+			'Question_Group',
576
+			array(array('Event_Question_Group.EQG_primary' => 0))
577
+		);
578
+		if (! empty($orig_additional_qgs)) {
579
+			foreach ($orig_additional_qgs as $id => $obj) {
580
+				if ($obj instanceof EE_Question_Group) {
581
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
582
+				}
583
+			}
584
+		}
585
+
586
+		$new_event->save();
587
+
588
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
589
+		$cloned_tickets = array();
590
+		foreach ($orig_datetimes as $orig_dtt) {
591
+			if (! $orig_dtt instanceof EE_Datetime) {
592
+				continue;
593
+			}
594
+			$new_dtt = clone $orig_dtt;
595
+			$orig_tkts = $orig_dtt->tickets();
596
+			// save new dtt then add to event
597
+			$new_dtt->set('DTT_ID', 0);
598
+			$new_dtt->set('DTT_sold', 0);
599
+			$new_dtt->set_reserved(0);
600
+			$new_dtt->save();
601
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
602
+			$new_event->save();
603
+			// now let's get the ticket relations setup.
604
+			foreach ((array) $orig_tkts as $orig_tkt) {
605
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
606
+				if (! $orig_tkt instanceof EE_Ticket) {
607
+					continue;
608
+				}
609
+				// is this ticket archived?  If it is then let's skip
610
+				if ($orig_tkt->get('TKT_deleted')) {
611
+					continue;
612
+				}
613
+				// does this original ticket already exist in the clone_tickets cache?
614
+				//  If so we'll just use the new ticket from it.
615
+				if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
616
+					$new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
617
+				} else {
618
+					$new_tkt = clone $orig_tkt;
619
+					// get relations on the $orig_tkt that we need to setup.
620
+					$orig_prices = $orig_tkt->prices();
621
+					$new_tkt->set('TKT_ID', 0);
622
+					$new_tkt->set('TKT_sold', 0);
623
+					$new_tkt->set('TKT_reserved', 0);
624
+					$new_tkt->save(); // make sure new ticket has ID.
625
+					// price relations on new ticket need to be setup.
626
+					foreach ($orig_prices as $orig_price) {
627
+						$new_price = clone $orig_price;
628
+						$new_price->set('PRC_ID', 0);
629
+						$new_price->save();
630
+						$new_tkt->_add_relation_to($new_price, 'Price');
631
+						$new_tkt->save();
632
+					}
633
+
634
+					do_action(
635
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
636
+						$orig_tkt,
637
+						$new_tkt,
638
+						$orig_prices,
639
+						$orig_event,
640
+						$orig_dtt,
641
+						$new_dtt
642
+					);
643
+				}
644
+				// k now we can add the new ticket as a relation to the new datetime
645
+				// and make sure its added to our cached $cloned_tickets array
646
+				// for use with later datetimes that have the same ticket.
647
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
648
+				$new_dtt->save();
649
+				$cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
650
+			}
651
+		}
652
+		// clone taxonomy information
653
+		$taxonomies_to_clone_with = apply_filters(
654
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
655
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
656
+		);
657
+		// get terms for original event (notice)
658
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
659
+		// loop through terms and add them to new event.
660
+		foreach ($orig_terms as $term) {
661
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
662
+		}
663
+
664
+		// duplicate other core WP_Post items for this event.
665
+		// post thumbnail (feature image).
666
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
667
+		if ($feature_image_id) {
668
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
669
+		}
670
+
671
+		// duplicate page_template setting
672
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
673
+		if ($page_template) {
674
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
675
+		}
676
+
677
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
678
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
679
+		if ($new_event->ID()) {
680
+			$redirect_args = array(
681
+				'post'   => $new_event->ID(),
682
+				'action' => 'edit',
683
+			);
684
+			EE_Error::add_success(
685
+				esc_html__(
686
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
687
+					'event_espresso'
688
+				)
689
+			);
690
+		} else {
691
+			$redirect_args = array(
692
+				'action' => 'default',
693
+			);
694
+			EE_Error::add_error(
695
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
696
+				__FILE__,
697
+				__FUNCTION__,
698
+				__LINE__
699
+			);
700
+		}
701
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
702
+	}
703
+
704
+
705
+	/**
706
+	 * Generates output for the import page.
707
+	 *
708
+	 * @throws DomainException
709
+	 */
710
+	protected function _import_page()
711
+	{
712
+		$title = esc_html__('Import', 'event_espresso');
713
+		$intro = esc_html__(
714
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
715
+			'event_espresso'
716
+		);
717
+		$form_url = EVENTS_ADMIN_URL;
718
+		$action = 'import_events';
719
+		$type = 'csv';
720
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
721
+			$title,
722
+			$intro,
723
+			$form_url,
724
+			$action,
725
+			$type
726
+		);
727
+		$this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
728
+			array('action' => 'sample_export_file'),
729
+			$this->_admin_base_url
730
+		);
731
+		$content = EEH_Template::display_template(
732
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
733
+			$this->_template_args,
734
+			true
735
+		);
736
+		$this->_template_args['admin_page_content'] = $content;
737
+		$this->display_admin_page_with_sidebar();
738
+	}
739
+
740
+
741
+	/**
742
+	 * _import_events
743
+	 * This handles displaying the screen and running imports for importing events.
744
+	 *
745
+	 * @return void
746
+	 */
747
+	protected function _import_events()
748
+	{
749
+		require_once(EE_CLASSES . 'EE_Import.class.php');
750
+		$success = EE_Import::instance()->import();
751
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
752
+	}
753
+
754
+
755
+	/**
756
+	 * _events_export
757
+	 * Will export all (or just the given event) to a Excel compatible file.
758
+	 *
759
+	 * @access protected
760
+	 * @return void
761
+	 */
762
+	protected function _events_export()
763
+	{
764
+		if (isset($this->_req_data['EVT_ID'])) {
765
+			$event_ids = $this->_req_data['EVT_ID'];
766
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
767
+			$event_ids = $this->_req_data['EVT_IDs'];
768
+		} else {
769
+			$event_ids = null;
770
+		}
771
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
772
+		$new_request_args = array(
773
+			'export' => 'report',
774
+			'action' => 'all_event_data',
775
+			'EVT_ID' => $event_ids,
776
+		);
777
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
778
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
779
+			require_once(EE_CLASSES . 'EE_Export.class.php');
780
+			$EE_Export = EE_Export::instance($this->_req_data);
781
+			$EE_Export->export();
782
+		}
783
+	}
784
+
785
+
786
+	/**
787
+	 * handle category exports()
788
+	 *
789
+	 * @return void
790
+	 */
791
+	protected function _categories_export()
792
+	{
793
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
794
+		$new_request_args = array(
795
+			'export'       => 'report',
796
+			'action'       => 'categories',
797
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
798
+		);
799
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
800
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
801
+			require_once(EE_CLASSES . 'EE_Export.class.php');
802
+			$EE_Export = EE_Export::instance($this->_req_data);
803
+			$EE_Export->export();
804
+		}
805
+	}
806
+
807
+
808
+	/**
809
+	 * Creates a sample CSV file for importing
810
+	 */
811
+	protected function _sample_export_file()
812
+	{
813
+		// require_once(EE_CLASSES . 'EE_Export.class.php');
814
+		EE_Export::instance()->export_sample();
815
+	}
816
+
817
+
818
+	/*************        Template Settings        *************/
819
+	/**
820
+	 * Generates template settings page output
821
+	 *
822
+	 * @throws DomainException
823
+	 * @throws EE_Error
824
+	 */
825
+	protected function _template_settings()
826
+	{
827
+		$this->_template_args['values'] = $this->_yes_no_values;
828
+		/**
829
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
830
+		 * from General_Settings_Admin_Page to here.
831
+		 */
832
+		$this->_template_args = apply_filters(
833
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
834
+			$this->_template_args
835
+		);
836
+		$this->_set_add_edit_form_tags('update_template_settings');
837
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
838
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
839
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
840
+			$this->_template_args,
841
+			true
842
+		);
843
+		$this->display_admin_page_with_sidebar();
844
+	}
845
+
846
+
847
+	/**
848
+	 * Handler for updating template settings.
849
+	 *
850
+	 * @throws InvalidInterfaceException
851
+	 * @throws InvalidDataTypeException
852
+	 * @throws InvalidArgumentException
853
+	 */
854
+	protected function _update_template_settings()
855
+	{
856
+		/**
857
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
858
+		 * from General_Settings_Admin_Page to here.
859
+		 */
860
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
861
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
862
+			EE_Registry::instance()->CFG->template_settings,
863
+			$this->_req_data
864
+		);
865
+		// update custom post type slugs and detect if we need to flush rewrite rules
866
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
867
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
868
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
869
+			: EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
870
+		$what = 'Template Settings';
871
+		$success = $this->_update_espresso_configuration(
872
+			$what,
873
+			EE_Registry::instance()->CFG->template_settings,
874
+			__FILE__,
875
+			__FUNCTION__,
876
+			__LINE__
877
+		);
878
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
879
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
880
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
881
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
882
+			);
883
+			$rewrite_rules->flush();
884
+		}
885
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
886
+	}
887
+
888
+
889
+	/**
890
+	 * _premium_event_editor_meta_boxes
891
+	 * add all metaboxes related to the event_editor
892
+	 *
893
+	 * @access protected
894
+	 * @return void
895
+	 * @throws EE_Error
896
+	 */
897
+	protected function _premium_event_editor_meta_boxes()
898
+	{
899
+		$this->verify_cpt_object();
900
+		add_meta_box(
901
+			'espresso_event_editor_event_options',
902
+			esc_html__('Event Registration Options', 'event_espresso'),
903
+			array($this, 'registration_options_meta_box'),
904
+			$this->page_slug,
905
+			'side',
906
+			'core'
907
+		);
908
+	}
909
+
910
+
911
+	/**
912
+	 * override caf metabox
913
+	 *
914
+	 * @return void
915
+	 * @throws DomainException
916
+	 */
917
+	public function registration_options_meta_box()
918
+	{
919
+		$yes_no_values = array(
920
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
921
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
922
+		);
923
+		$default_reg_status_values = EEM_Registration::reg_status_array(
924
+			array(
925
+				EEM_Registration::status_id_cancelled,
926
+				EEM_Registration::status_id_declined,
927
+				EEM_Registration::status_id_incomplete,
928
+				EEM_Registration::status_id_wait_list,
929
+			),
930
+			true
931
+		);
932
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
933
+		$template_args['_event'] = $this->_cpt_model_obj;
934
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
935
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
936
+			'default_reg_status',
937
+			$default_reg_status_values,
938
+			$this->_cpt_model_obj->default_registration_status()
939
+		);
940
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
941
+			'display_desc',
942
+			$yes_no_values,
943
+			$this->_cpt_model_obj->display_description()
944
+		);
945
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
946
+			'display_ticket_selector',
947
+			$yes_no_values,
948
+			$this->_cpt_model_obj->display_ticket_selector(),
949
+			'',
950
+			'',
951
+			false
952
+		);
953
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
954
+			'EVT_default_registration_status',
955
+			$default_reg_status_values,
956
+			$this->_cpt_model_obj->default_registration_status()
957
+		);
958
+		$template_args['additional_registration_options'] = apply_filters(
959
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
960
+			'',
961
+			$template_args,
962
+			$yes_no_values,
963
+			$default_reg_status_values
964
+		);
965
+		EEH_Template::display_template(
966
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
967
+			$template_args
968
+		);
969
+	}
970
+
971
+
972
+
973
+	/**
974
+	 * wp_list_table_mods for caf
975
+	 * ============================
976
+	 */
977
+	/**
978
+	 * hook into list table filters and provide filters for caffeinated list table
979
+	 *
980
+	 * @param  array $old_filters    any existing filters present
981
+	 * @param  array $list_table_obj the list table object
982
+	 * @return array                  new filters
983
+	 */
984
+	public function list_table_filters($old_filters, $list_table_obj)
985
+	{
986
+		$filters = array();
987
+		// first month/year filters
988
+		$filters[] = $this->espresso_event_months_dropdown();
989
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
990
+		// active status dropdown
991
+		if ($status !== 'draft') {
992
+			$filters[] = $this->active_status_dropdown(
993
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
994
+			);
995
+		}
996
+		// category filter
997
+		$filters[] = $this->category_dropdown();
998
+		return array_merge($old_filters, $filters);
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * espresso_event_months_dropdown
1004
+	 *
1005
+	 * @access public
1006
+	 * @return string                dropdown listing month/year selections for events.
1007
+	 */
1008
+	public function espresso_event_months_dropdown()
1009
+	{
1010
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
1011
+		// Note we need to include any other filters that are set!
1012
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1013
+		// categories?
1014
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1015
+			? $this->_req_data['EVT_CAT']
1016
+			: null;
1017
+		// active status?
1018
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1019
+		$cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1020
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * returns a list of "active" statuses on the event
1026
+	 *
1027
+	 * @param  string $current_value whatever the current active status is
1028
+	 * @return string
1029
+	 */
1030
+	public function active_status_dropdown($current_value = '')
1031
+	{
1032
+		$select_name = 'active_status';
1033
+		$values = array(
1034
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1035
+			'active'   => esc_html__('Active', 'event_espresso'),
1036
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1037
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1038
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1039
+		);
1040
+		$id = 'id="espresso-active-status-dropdown-filter"';
1041
+		$class = 'wide';
1042
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 * output a dropdown of the categories for the category filter on the event admin list table
1048
+	 *
1049
+	 * @access  public
1050
+	 * @return string html
1051
+	 */
1052
+	public function category_dropdown()
1053
+	{
1054
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1055
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1056
+	}
1057
+
1058
+
1059
+	/**
1060
+	 * get total number of events today
1061
+	 *
1062
+	 * @access public
1063
+	 * @return int
1064
+	 * @throws EE_Error
1065
+	 */
1066
+	public function total_events_today()
1067
+	{
1068
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1069
+			'DTT_EVT_start',
1070
+			date('Y-m-d') . ' 00:00:00',
1071
+			'Y-m-d H:i:s',
1072
+			'UTC'
1073
+		);
1074
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1075
+			'DTT_EVT_start',
1076
+			date('Y-m-d') . ' 23:59:59',
1077
+			'Y-m-d H:i:s',
1078
+			'UTC'
1079
+		);
1080
+		$where = array(
1081
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1082
+		);
1083
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1084
+		return $count;
1085
+	}
1086
+
1087
+
1088
+	/**
1089
+	 * get total number of events this month
1090
+	 *
1091
+	 * @access public
1092
+	 * @return int
1093
+	 * @throws EE_Error
1094
+	 */
1095
+	public function total_events_this_month()
1096
+	{
1097
+		// Dates
1098
+		$this_year_r = date('Y');
1099
+		$this_month_r = date('m');
1100
+		$days_this_month = date('t');
1101
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1102
+			'DTT_EVT_start',
1103
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1104
+			'Y-m-d H:i:s',
1105
+			'UTC'
1106
+		);
1107
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1108
+			'DTT_EVT_start',
1109
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1110
+			'Y-m-d H:i:s',
1111
+			'UTC'
1112
+		);
1113
+		$where = array(
1114
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1115
+		);
1116
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1117
+		return $count;
1118
+	}
1119
+
1120
+
1121
+	/** DEFAULT TICKETS STUFF **/
1122
+
1123
+	/**
1124
+	 * Output default tickets list table view.
1125
+	 */
1126
+	public function _tickets_overview_list_table()
1127
+	{
1128
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1129
+		$this->display_admin_list_table_page_with_no_sidebar();
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 * @param int  $per_page
1135
+	 * @param bool $count
1136
+	 * @param bool $trashed
1137
+	 * @return \EE_Soft_Delete_Base_Class[]|int
1138
+	 */
1139
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1140
+	{
1141
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1142
+		$order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1143
+		switch ($orderby) {
1144
+			case 'TKT_name':
1145
+				$orderby = array('TKT_name' => $order);
1146
+				break;
1147
+			case 'TKT_price':
1148
+				$orderby = array('TKT_price' => $order);
1149
+				break;
1150
+			case 'TKT_uses':
1151
+				$orderby = array('TKT_uses' => $order);
1152
+				break;
1153
+			case 'TKT_min':
1154
+				$orderby = array('TKT_min' => $order);
1155
+				break;
1156
+			case 'TKT_max':
1157
+				$orderby = array('TKT_max' => $order);
1158
+				break;
1159
+			case 'TKT_qty':
1160
+				$orderby = array('TKT_qty' => $order);
1161
+				break;
1162
+		}
1163
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1164
+			? $this->_req_data['paged']
1165
+			: 1;
1166
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1167
+			? $this->_req_data['perpage']
1168
+			: $per_page;
1169
+		$_where = array(
1170
+			'TKT_is_default' => 1,
1171
+			'TKT_deleted'    => $trashed,
1172
+		);
1173
+		$offset = ($current_page - 1) * $per_page;
1174
+		$limit = array($offset, $per_page);
1175
+		if (isset($this->_req_data['s'])) {
1176
+			$sstr = '%' . $this->_req_data['s'] . '%';
1177
+			$_where['OR'] = array(
1178
+				'TKT_name'        => array('LIKE', $sstr),
1179
+				'TKT_description' => array('LIKE', $sstr),
1180
+			);
1181
+		}
1182
+		$query_params = array(
1183
+			$_where,
1184
+			'order_by' => $orderby,
1185
+			'limit'    => $limit,
1186
+			'group_by' => 'TKT_ID',
1187
+		);
1188
+		if ($count) {
1189
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1190
+		} else {
1191
+			return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1192
+		}
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * @param bool $trash
1198
+	 * @throws EE_Error
1199
+	 */
1200
+	protected function _trash_or_restore_ticket($trash = false)
1201
+	{
1202
+		$success = 1;
1203
+		$TKT = EEM_Ticket::instance();
1204
+		// checkboxes?
1205
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1206
+			// if array has more than one element then success message should be plural
1207
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1208
+			// cycle thru the boxes
1209
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1210
+				if ($trash) {
1211
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1212
+						$success = 0;
1213
+					}
1214
+				} else {
1215
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1216
+						$success = 0;
1217
+					}
1218
+				}
1219
+			}
1220
+		} else {
1221
+			// grab single id and trash
1222
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1223
+			if ($trash) {
1224
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1225
+					$success = 0;
1226
+				}
1227
+			} else {
1228
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1229
+					$success = 0;
1230
+				}
1231
+			}
1232
+		}
1233
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1234
+		$query_args = array(
1235
+			'action' => 'ticket_list_table',
1236
+			'status' => $trash ? '' : 'trashed',
1237
+		);
1238
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1239
+	}
1240
+
1241
+
1242
+	/**
1243
+	 * Handles trashing default ticket.
1244
+	 */
1245
+	protected function _delete_ticket()
1246
+	{
1247
+		$success = 1;
1248
+		// checkboxes?
1249
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1250
+			// if array has more than one element then success message should be plural
1251
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1252
+			// cycle thru the boxes
1253
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1254
+				// delete
1255
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1256
+					$success = 0;
1257
+				}
1258
+			}
1259
+		} else {
1260
+			// grab single id and trash
1261
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1262
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1263
+				$success = 0;
1264
+			}
1265
+		}
1266
+		$action_desc = 'deleted';
1267
+		$query_args = array(
1268
+			'action' => 'ticket_list_table',
1269
+			'status' => 'trashed',
1270
+		);
1271
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1272
+		if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1273
+			array(array('TKT_is_default' => 1)),
1274
+			'TKT_ID',
1275
+			true
1276
+		)
1277
+		) {
1278
+			$query_args = array();
1279
+		}
1280
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1281
+	}
1282
+
1283
+
1284
+	/**
1285
+	 * @param int $TKT_ID
1286
+	 * @return bool|int
1287
+	 * @throws EE_Error
1288
+	 */
1289
+	protected function _delete_the_ticket($TKT_ID)
1290
+	{
1291
+		$tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1292
+		$tkt->_remove_relations('Datetime');
1293
+		// delete all related prices first
1294
+		$tkt->delete_related_permanently('Price');
1295
+		return $tkt->delete_permanently();
1296
+	}
1297 1297
 }
Please login to merge, or discard this patch.