Completed
Branch FET/11183/improvements-to-pue-... (232f50)
by
unknown
43:46 queued 26:36
created
core/data_migration_scripts/EE_DMS_Core_4_1_0.dms.php 1 patch
Indentation   +1137 added lines, -1137 removed lines patch added patch discarded remove patch
@@ -12,11 +12,11 @@  discard block
 block discarded – undo
12 12
 $stages = glob(EE_CORE . 'data_migration_scripts/4_1_0_stages/*');
13 13
 $class_to_filepath = array();
14 14
 if ( ! empty($stages)) {
15
-    foreach ($stages as $filepath) {
16
-        $matches = array();
17
-        preg_match('~4_1_0_stages/(.*).dmsstage.php~', $filepath, $matches);
18
-        $class_to_filepath[$matches[1]] = $filepath;
19
-    }
15
+	foreach ($stages as $filepath) {
16
+		$matches = array();
17
+		preg_match('~4_1_0_stages/(.*).dmsstage.php~', $filepath, $matches);
18
+		$class_to_filepath[$matches[1]] = $filepath;
19
+	}
20 20
 }
21 21
 //give addons a chance to autoload their stages too
22 22
 $class_to_filepath = apply_filters('FHEE__EE_DMS_4_1_0__autoloaded_stages', $class_to_filepath);
@@ -44,91 +44,91 @@  discard block
 block discarded – undo
44 44
 
45 45
 
46 46
 
47
-    /**
48
-     * EE_DMS_Core_4_1_0 constructor.
49
-     *
50
-     * @param TableManager  $table_manager
51
-     * @param TableAnalysis $table_analysis
52
-     */
53
-    public function __construct(TableManager $table_manager = null, TableAnalysis $table_analysis = null)
54
-    {
55
-        $this->_pretty_name = esc_html__("Data Migration from Event Espresso 3 to Event Espresso 4.1.0", "event_espresso");
56
-        $this->_priority = 10;
57
-        $this->_migration_stages = array(
58
-                new EE_DMS_4_1_0_org_options(),
59
-                new EE_DMS_4_1_0_shortcodes(),
60
-                new EE_DMS_4_1_0_gateways(),
61
-                new EE_DMS_4_1_0_events(),
62
-                new EE_DMS_4_1_0_prices(),
63
-                new EE_DMS_4_1_0_category_details(),
64
-                new EE_DMS_4_1_0_event_category(),
65
-                new EE_DMS_4_1_0_venues(),
66
-                new EE_DMS_4_1_0_event_venue(),
67
-                new EE_DMS_4_1_0_question_groups(),
68
-                new EE_DMS_4_1_0_questions(),
69
-                new EE_DMS_4_1_0_question_group_question(),
70
-                new EE_DMS_4_1_0_event_question_group(),
71
-                new EE_DMS_4_1_0_attendees(),
72
-                new EE_DMS_4_1_0_line_items(),
73
-                new EE_DMS_4_1_0_answers(),
74
-                new EE_DMS_4_1_0_checkins(),
75
-        );
76
-        parent::__construct($table_manager, $table_analysis);
77
-    }
78
-
79
-
80
-
81
-    /**
82
-     * Checks if this 3.1 Check-in table exists. If it doesn't we can't migrate Check-ins
83
-     *
84
-     * @global wpdb $wpdb
85
-     * @return boolean
86
-     */
87
-    private function _checkin_table_exists()
88
-    {
89
-        global $wpdb;
90
-        $results = $wpdb->get_results("SHOW TABLES LIKE '" . $wpdb->prefix . "events_attendee_checkin" . "'");
91
-        if ($results) {
92
-            return true;
93
-        } else {
94
-            return false;
95
-        }
96
-    }
97
-
98
-
99
-
100
-    public function can_migrate_from_version($version_array)
101
-    {
102
-        $version_string = $version_array['Core'];
103
-        if (version_compare($version_string, '4.0.0', '<=') && version_compare($version_string, '3.1.26', '>=')) {
47
+	/**
48
+	 * EE_DMS_Core_4_1_0 constructor.
49
+	 *
50
+	 * @param TableManager  $table_manager
51
+	 * @param TableAnalysis $table_analysis
52
+	 */
53
+	public function __construct(TableManager $table_manager = null, TableAnalysis $table_analysis = null)
54
+	{
55
+		$this->_pretty_name = esc_html__("Data Migration from Event Espresso 3 to Event Espresso 4.1.0", "event_espresso");
56
+		$this->_priority = 10;
57
+		$this->_migration_stages = array(
58
+				new EE_DMS_4_1_0_org_options(),
59
+				new EE_DMS_4_1_0_shortcodes(),
60
+				new EE_DMS_4_1_0_gateways(),
61
+				new EE_DMS_4_1_0_events(),
62
+				new EE_DMS_4_1_0_prices(),
63
+				new EE_DMS_4_1_0_category_details(),
64
+				new EE_DMS_4_1_0_event_category(),
65
+				new EE_DMS_4_1_0_venues(),
66
+				new EE_DMS_4_1_0_event_venue(),
67
+				new EE_DMS_4_1_0_question_groups(),
68
+				new EE_DMS_4_1_0_questions(),
69
+				new EE_DMS_4_1_0_question_group_question(),
70
+				new EE_DMS_4_1_0_event_question_group(),
71
+				new EE_DMS_4_1_0_attendees(),
72
+				new EE_DMS_4_1_0_line_items(),
73
+				new EE_DMS_4_1_0_answers(),
74
+				new EE_DMS_4_1_0_checkins(),
75
+		);
76
+		parent::__construct($table_manager, $table_analysis);
77
+	}
78
+
79
+
80
+
81
+	/**
82
+	 * Checks if this 3.1 Check-in table exists. If it doesn't we can't migrate Check-ins
83
+	 *
84
+	 * @global wpdb $wpdb
85
+	 * @return boolean
86
+	 */
87
+	private function _checkin_table_exists()
88
+	{
89
+		global $wpdb;
90
+		$results = $wpdb->get_results("SHOW TABLES LIKE '" . $wpdb->prefix . "events_attendee_checkin" . "'");
91
+		if ($results) {
92
+			return true;
93
+		} else {
94
+			return false;
95
+		}
96
+	}
97
+
98
+
99
+
100
+	public function can_migrate_from_version($version_array)
101
+	{
102
+		$version_string = $version_array['Core'];
103
+		if (version_compare($version_string, '4.0.0', '<=') && version_compare($version_string, '3.1.26', '>=')) {
104 104
 //			echo "$version_string can be migrated fro";
105
-            return true;
106
-        } elseif ( ! $version_string) {
105
+			return true;
106
+		} elseif ( ! $version_string) {
107 107
 //			echo "no version string provided: $version_string";
108
-            //no version string provided... this must be pre 4.1
109
-            //because since 4.1 we're
110
-            return false;//changed mind. dont want people thinking they should migrate yet because they cant
111
-        } else {
108
+			//no version string provided... this must be pre 4.1
109
+			//because since 4.1 we're
110
+			return false;//changed mind. dont want people thinking they should migrate yet because they cant
111
+		} else {
112 112
 //			echo "$version_string doesnt apply";
113
-            return false;
114
-        }
115
-    }
113
+			return false;
114
+		}
115
+	}
116 116
 
117 117
 
118 118
 
119
-    public function schema_changes_before_migration()
120
-    {
121
-        //relies on 4.1's EEH_Activation::create_table
122
-        require_once(EE_HELPERS . 'EEH_Activation.helper.php');
123
-        $table_name = 'esp_answer';
124
-        $sql = " ANS_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
119
+	public function schema_changes_before_migration()
120
+	{
121
+		//relies on 4.1's EEH_Activation::create_table
122
+		require_once(EE_HELPERS . 'EEH_Activation.helper.php');
123
+		$table_name = 'esp_answer';
124
+		$sql = " ANS_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
125 125
 					REG_ID INT UNSIGNED NOT NULL,
126 126
 					QST_ID INT UNSIGNED NOT NULL,
127 127
 					ANS_value TEXT NOT NULL,
128 128
 					PRIMARY KEY  (ANS_ID)";
129
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
130
-        $table_name = 'esp_attendee_meta';
131
-        $sql = "ATTM_ID INT(10) UNSIGNED NOT	NULL AUTO_INCREMENT,
129
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
130
+		$table_name = 'esp_attendee_meta';
131
+		$sql = "ATTM_ID INT(10) UNSIGNED NOT	NULL AUTO_INCREMENT,
132 132
 						ATT_ID BIGINT(20) UNSIGNED NOT NULL,
133 133
 						ATT_fname VARCHAR(45) NOT NULL,
134 134
 						ATT_lname VARCHAR(45) NOT	NULL,
@@ -144,9 +144,9 @@  discard block
 block discarded – undo
144 144
 								KEY ATT_fname (ATT_fname),
145 145
 								KEY ATT_lname (ATT_lname),
146 146
 								KEY ATT_email (ATT_email)";
147
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
148
-        $table_name = 'esp_country';
149
-        $sql = "CNT_ISO VARCHAR(2) COLLATE utf8_bin NOT NULL,
147
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
148
+		$table_name = 'esp_country';
149
+		$sql = "CNT_ISO VARCHAR(2) COLLATE utf8_bin NOT NULL,
150 150
 					  CNT_ISO3 VARCHAR(3) COLLATE utf8_bin NOT NULL,
151 151
 					  RGN_ID TINYINT(3) UNSIGNED DEFAULT NULL,
152 152
 					  CNT_name VARCHAR(45) COLLATE utf8_bin NOT NULL,
@@ -162,9 +162,9 @@  discard block
 block discarded – undo
162 162
 					  CNT_is_EU TINYINT(1) DEFAULT '0',
163 163
 					  CNT_active TINYINT(1) DEFAULT '0',
164 164
 					  PRIMARY KEY  (CNT_ISO)";
165
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
166
-        $table_name = 'esp_datetime';
167
-        $sql = "DTT_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
165
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
166
+		$table_name = 'esp_datetime';
167
+		$sql = "DTT_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
168 168
 				  EVT_ID BIGINT(20) UNSIGNED NOT NULL,
169 169
 				  DTT_EVT_start DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
170 170
 				  DTT_EVT_end DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
@@ -177,9 +177,9 @@  discard block
 block discarded – undo
177 177
 						PRIMARY KEY  (DTT_ID),
178 178
 						KEY EVT_ID (EVT_ID),
179 179
 						KEY DTT_is_primary (DTT_is_primary)";
180
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
181
-        $table_name = 'esp_event_meta';
182
-        $sql = "
180
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
181
+		$table_name = 'esp_event_meta';
182
+		$sql = "
183 183
 			EVTM_ID INT NOT NULL AUTO_INCREMENT,
184 184
 			EVT_ID BIGINT(20) UNSIGNED NOT NULL,
185 185
 			EVT_display_desc TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
@@ -194,31 +194,31 @@  discard block
 block discarded – undo
194 194
 			EVT_external_URL VARCHAR(200) NULL,
195 195
 			EVT_donations TINYINT(1) NULL,
196 196
 			PRIMARY KEY  (EVTM_ID)";
197
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
198
-        $table_name = 'esp_event_question_group';
199
-        $sql = "EQG_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
197
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
198
+		$table_name = 'esp_event_question_group';
199
+		$sql = "EQG_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
200 200
 					EVT_ID BIGINT(20) UNSIGNED NOT NULL,
201 201
 					QSG_ID INT UNSIGNED NOT NULL,
202 202
 					EQG_primary TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
203 203
 					PRIMARY KEY  (EQG_ID)";
204
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
205
-        $table_name = 'esp_event_venue';
206
-        $sql = "EVV_ID INT(11) NOT NULL AUTO_INCREMENT,
204
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
205
+		$table_name = 'esp_event_venue';
206
+		$sql = "EVV_ID INT(11) NOT NULL AUTO_INCREMENT,
207 207
 				EVT_ID BIGINT(20) UNSIGNED NOT NULL,
208 208
 				VNU_ID BIGINT(20) UNSIGNED NOT NULL,
209 209
 				EVV_primary TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
210 210
 				PRIMARY KEY  (EVV_ID)";
211
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
212
-        $table_name = 'esp_extra_meta';
213
-        $sql = "EXM_ID INT(11) NOT NULL AUTO_INCREMENT,
211
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
212
+		$table_name = 'esp_extra_meta';
213
+		$sql = "EXM_ID INT(11) NOT NULL AUTO_INCREMENT,
214 214
 				OBJ_ID INT(11) DEFAULT NULL,
215 215
 				EXM_type VARCHAR(45) DEFAULT NULL,
216 216
 				EXM_key VARCHAR(45) DEFAULT NULL,
217 217
 				EXM_value TEXT,
218 218
 				PRIMARY KEY  (EXM_ID)";
219
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
220
-        $table_name = 'esp_line_item';
221
-        $sql = "LIN_ID INT(11) NOT NULL AUTO_INCREMENT,
219
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
220
+		$table_name = 'esp_line_item';
221
+		$sql = "LIN_ID INT(11) NOT NULL AUTO_INCREMENT,
222 222
 				LIN_code VARCHAR(245) NOT NULL DEFAULT '',
223 223
 				TXN_ID INT(11) DEFAULT NULL,
224 224
 				LIN_name VARCHAR(245) NOT NULL DEFAULT '',
@@ -234,18 +234,18 @@  discard block
 block discarded – undo
234 234
 				OBJ_ID INT(11) DEFAULT NULL,
235 235
 				OBJ_type VARCHAR(45)DEFAULT NULL,
236 236
 				PRIMARY KEY  (LIN_ID)";
237
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
238
-        $table_name = 'esp_message_template';
239
-        $sql = "MTP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
237
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
238
+		$table_name = 'esp_message_template';
239
+		$sql = "MTP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
240 240
 					GRP_ID INT(10) UNSIGNED NOT NULL,
241 241
 					MTP_context VARCHAR(50) NOT NULL,
242 242
 					MTP_template_field VARCHAR(30) NOT NULL,
243 243
 					MTP_content TEXT NOT NULL,
244 244
 					PRIMARY KEY  (MTP_ID),
245 245
 					KEY GRP_ID (GRP_ID)";
246
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
247
-        $table_name = 'esp_message_template_group';
248
-        $sql = "GRP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
246
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
247
+		$table_name = 'esp_message_template_group';
248
+		$sql = "GRP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
249 249
 					EVT_ID BIGINT(20) UNSIGNED DEFAULT NULL,
250 250
 					MTP_user_id INT(10) NOT NULL DEFAULT '1',
251 251
 					MTP_messenger VARCHAR(30) NOT NULL,
@@ -257,9 +257,9 @@  discard block
 block discarded – undo
257 257
 					PRIMARY KEY  (GRP_ID),
258 258
 					KEY EVT_ID (EVT_ID),
259 259
 					KEY MTP_user_id (MTP_user_id)";
260
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
261
-        $table_name = 'esp_payment';
262
-        $sql = "PAY_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
260
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
261
+		$table_name = 'esp_payment';
262
+		$sql = "PAY_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
263 263
 					TXN_ID INT(10) UNSIGNED DEFAULT NULL,
264 264
 					STS_ID VARCHAR(3) COLLATE utf8_bin DEFAULT NULL,
265 265
 					PAY_timestamp DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
@@ -275,9 +275,9 @@  discard block
 block discarded – undo
275 275
 					PRIMARY KEY  (PAY_ID),
276 276
 					KEY TXN_ID (TXN_ID),
277 277
 					KEY PAY_timestamp (PAY_timestamp)";
278
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
279
-        $table_name = "esp_ticket";
280
-        $sql = "TKT_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
278
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
279
+		$table_name = "esp_ticket";
280
+		$sql = "TKT_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
281 281
 					  TTM_ID INT(10) UNSIGNED NOT NULL,
282 282
 					  TKT_name VARCHAR(245) NOT NULL DEFAULT '',
283 283
 					  TKT_description TEXT NOT NULL,
@@ -296,28 +296,28 @@  discard block
 block discarded – undo
296 296
 					  TKT_parent INT(10) UNSIGNED DEFAULT '0',
297 297
 					  TKT_deleted TINYINT(1) NOT NULL DEFAULT '0',
298 298
 					  PRIMARY KEY  (TKT_ID)";
299
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
300
-        $table_name = "esp_ticket_price";
301
-        $sql = "TKP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
299
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
300
+		$table_name = "esp_ticket_price";
301
+		$sql = "TKP_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
302 302
 					  TKT_ID INT(10) UNSIGNED NOT NULL,
303 303
 					  PRC_ID INT(10) UNSIGNED NOT NULL,
304 304
 					  PRIMARY KEY  (TKP_ID)";
305
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
306
-        $table_name = "esp_datetime_ticket";
307
-        $sql = "DTK_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
305
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
306
+		$table_name = "esp_datetime_ticket";
307
+		$sql = "DTK_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
308 308
 					  DTT_ID INT(10) UNSIGNED NOT NULL,
309 309
 					  TKT_ID INT(10) UNSIGNED NOT NULL,
310 310
 					  PRIMARY KEY  (DTK_ID)";
311
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
312
-        $table_name = "esp_ticket_template";
313
-        $sql = "TTM_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
311
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
312
+		$table_name = "esp_ticket_template";
313
+		$sql = "TTM_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
314 314
 					  TTM_name VARCHAR(45) NOT NULL,
315 315
 					  TTM_description TEXT,
316 316
 					  TTM_file VARCHAR(45),
317 317
 					  PRIMARY KEY  (TTM_ID)";
318
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
319
-        $table_name = "esp_price";
320
-        $sql = "PRC_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
318
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
319
+		$table_name = "esp_price";
320
+		$sql = "PRC_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
321 321
 					  PRT_ID TINYINT(3) UNSIGNED NOT NULL,
322 322
 					  PRC_amount DECIMAL(10,3) NOT NULL DEFAULT '0.00',
323 323
 					  PRC_name VARCHAR(245) NOT NULL,
@@ -328,9 +328,9 @@  discard block
 block discarded – undo
328 328
 					  PRC_order TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
329 329
 					  PRC_parent INT(10) UNSIGNED DEFAULT 0,
330 330
 					  PRIMARY KEY  (PRC_ID)";
331
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
332
-        $table_name = "esp_price_type";
333
-        $sql = "PRT_ID TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
331
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
332
+		$table_name = "esp_price_type";
333
+		$sql = "PRT_ID TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
334 334
 				  PRT_name VARCHAR(45) NOT NULL,
335 335
 				  PBT_ID TINYINT(3) UNSIGNED NOT NULL DEFAULT '1',
336 336
 				  PRT_is_percent TINYINT(1) NOT NULL DEFAULT '0',
@@ -338,9 +338,9 @@  discard block
 block discarded – undo
338 338
 				  PRT_deleted TINYINT(1) NOT NULL DEFAULT '0',
339 339
 				  UNIQUE KEY PRT_name_UNIQUE (PRT_name),
340 340
 				  PRIMARY KEY  (PRT_ID)";
341
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
342
-        $table_name = 'esp_question';
343
-        $sql = 'QST_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
341
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
342
+		$table_name = 'esp_question';
343
+		$sql = 'QST_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
344 344
 					QST_display_text TEXT NOT NULL,
345 345
 					QST_admin_label VARCHAR(255) NOT NULL,
346 346
 					QST_system VARCHAR(25) DEFAULT NULL,
@@ -352,10 +352,10 @@  discard block
 block discarded – undo
352 352
 					QST_wp_user BIGINT UNSIGNED NULL,
353 353
 					QST_deleted TINYINT UNSIGNED NOT NULL DEFAULT 0,
354 354
 					PRIMARY KEY  (QST_ID)';
355
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
356
-        $this->_get_table_manager()->dropIndex('esp_question_group', 'QSG_identifier_UNIQUE');
357
-        $table_name = 'esp_question_group';
358
-        $sql = 'QSG_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
355
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
356
+		$this->_get_table_manager()->dropIndex('esp_question_group', 'QSG_identifier_UNIQUE');
357
+		$table_name = 'esp_question_group';
358
+		$sql = 'QSG_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
359 359
 					QSG_name VARCHAR(255) NOT NULL,
360 360
 					QSG_identifier VARCHAR(100) NOT NULL,
361 361
 					QSG_desc TEXT NULL,
@@ -366,23 +366,23 @@  discard block
 block discarded – undo
366 366
 					QSG_deleted TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
367 367
 					PRIMARY KEY  (QSG_ID),
368 368
 					UNIQUE KEY QSG_identifier_UNIQUE (QSG_identifier ASC)';
369
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
370
-        $table_name = 'esp_question_group_question';
371
-        $sql = "QGQ_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
369
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
370
+		$table_name = 'esp_question_group_question';
371
+		$sql = "QGQ_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
372 372
 					QSG_ID INT UNSIGNED NOT NULL,
373 373
 					QST_ID INT UNSIGNED NOT NULL,
374 374
 					PRIMARY KEY  (QGQ_ID) ";
375
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
376
-        $table_name = 'esp_question_option';
377
-        $sql = "QSO_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
375
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
376
+		$table_name = 'esp_question_option';
377
+		$sql = "QSO_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
378 378
 					QSO_value VARCHAR(255) NOT NULL,
379 379
 					QSO_desc TEXT NOT NULL,
380 380
 					QST_ID INT UNSIGNED NOT NULL,
381 381
 					QSO_deleted TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
382 382
 					PRIMARY KEY  (QSO_ID)";
383
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
384
-        $table_name = 'esp_registration';
385
-        $sql = "REG_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
383
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
384
+		$table_name = 'esp_registration';
385
+		$sql = "REG_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
386 386
 					  EVT_ID BIGINT(20) UNSIGNED NOT NULL,
387 387
 					  ATT_ID BIGINT(20) UNSIGNED NOT NULL,
388 388
 					  TXN_ID INT(10) UNSIGNED NOT NULL,
@@ -405,25 +405,25 @@  discard block
 block discarded – undo
405 405
 					  KEY STS_ID (STS_ID),
406 406
 					  KEY REG_url_link (REG_url_link),
407 407
 					  KEY REG_code (REG_code)";
408
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
409
-        $table_name = 'esp_checkin';
410
-        $sql = "CHK_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
408
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB ');
409
+		$table_name = 'esp_checkin';
410
+		$sql = "CHK_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
411 411
 					REG_ID INT(10) UNSIGNED NOT NULL,
412 412
 					DTT_ID INT(10) UNSIGNED NOT NULL,
413 413
 					CHK_in TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
414 414
 					CHK_timestamp DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
415 415
 					PRIMARY KEY  (CHK_ID)";
416
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
417
-        $table_name = 'esp_state';
418
-        $sql = "STA_ID smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT,
416
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
417
+		$table_name = 'esp_state';
418
+		$sql = "STA_ID smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT,
419 419
 					  CNT_ISO VARCHAR(2) COLLATE utf8_bin NOT NULL,
420 420
 					  STA_abbrev VARCHAR(6) COLLATE utf8_bin NOT NULL,
421 421
 					  STA_name VARCHAR(100) COLLATE utf8_bin NOT NULL,
422 422
 					  STA_active TINYINT(1) DEFAULT '1',
423 423
 					  PRIMARY KEY  (STA_ID)";
424
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
425
-        $table_name = 'esp_status';
426
-        $sql = "STS_ID VARCHAR(3) COLLATE utf8_bin NOT NULL,
424
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
425
+		$table_name = 'esp_status';
426
+		$sql = "STS_ID VARCHAR(3) COLLATE utf8_bin NOT NULL,
427 427
 					  STS_code VARCHAR(45) COLLATE utf8_bin NOT NULL,
428 428
 					  STS_type set('event','registration','transaction','payment','email') COLLATE utf8_bin NOT NULL,
429 429
 					  STS_can_edit TINYINT(1) NOT NULL DEFAULT 0,
@@ -431,9 +431,9 @@  discard block
 block discarded – undo
431 431
 					  STS_open TINYINT(1) NOT NULL DEFAULT 1,
432 432
 					  UNIQUE KEY STS_ID_UNIQUE (STS_ID),
433 433
 					  KEY STS_type (STS_type)";
434
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
435
-        $table_name = 'esp_transaction';
436
-        $sql = "TXN_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
434
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
435
+		$table_name = 'esp_transaction';
436
+		$sql = "TXN_ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
437 437
 					  TXN_timestamp DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
438 438
 					  TXN_total DECIMAL(10,3) DEFAULT '0.00',
439 439
 					  TXN_paid DECIMAL(10,3) NOT NULL DEFAULT '0.00',
@@ -443,9 +443,9 @@  discard block
 block discarded – undo
443 443
 					  PRIMARY KEY  (TXN_ID),
444 444
 					  KEY TXN_timestamp (TXN_timestamp),
445 445
 					  KEY STS_ID (STS_ID)";
446
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
447
-        $table_name = 'esp_venue_meta';
448
-        $sql = "VNUM_ID INT(11) NOT NULL AUTO_INCREMENT,
446
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
447
+		$table_name = 'esp_venue_meta';
448
+		$sql = "VNUM_ID INT(11) NOT NULL AUTO_INCREMENT,
449 449
 			VNU_ID BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
450 450
 			VNU_address VARCHAR(255) DEFAULT NULL,
451 451
 			VNU_address2 VARCHAR(255) DEFAULT NULL,
@@ -463,52 +463,52 @@  discard block
 block discarded – undo
463 463
 			PRIMARY KEY  (VNUM_ID),
464 464
 			KEY STA_ID (STA_ID),
465 465
 			KEY CNT_ISO (CNT_ISO)";
466
-        $this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
467
-        //setting up the DEFAULT stats and countries is also essential for the data migrations to run
468
-        //(because many need to convert old string states to foreign keys into the states table)
469
-        $this->insert_default_states();
470
-        $this->insert_default_countries();
471
-        //setting up DEFAULT prices, price types, and tickets is also essential for the price migrations
472
-        $this->insert_default_price_types();
473
-        $this->insert_default_prices();
474
-        $this->insert_default_tickets();
475
-        //setting up the config wp option pretty well counts as a 'schema change', or at least should happen ehre
476
-        EE_Config::instance()->update_espresso_config(false, true);
477
-        return true;
478
-    }
479
-
480
-
481
-
482
-    /**
483
-     * Yes we could have cleaned up the ee3 tables here. But just in case someone
484
-     * didn't backup their DB, and decides they want ot keep using EE3, we'll
485
-     * leave them for now. Mayeb remove them in 4.5 or something.
486
-     *
487
-     * @return boolean
488
-     */
489
-    public function schema_changes_after_migration()
490
-    {
491
-        return true;
492
-    }
493
-
494
-
495
-
496
-    /**
497
-     * insert_default_states
498
-     *
499
-     * @access public
500
-     * @static
501
-     * @return void
502
-     */
503
-    public function insert_default_states()
504
-    {
505
-        global $wpdb;
506
-        $state_table = $wpdb->prefix . "esp_state";
507
-        if ($this->_get_table_analysis()->tableExists($state_table)) {
508
-            $SQL = "SELECT COUNT('STA_ID') FROM " . $state_table;
509
-            $states = $wpdb->get_var($SQL);
510
-            if ( ! $states) {
511
-                $SQL = "INSERT INTO " . $state_table . "
466
+		$this->_table_is_new_in_this_version($table_name, $sql, 'ENGINE=InnoDB');
467
+		//setting up the DEFAULT stats and countries is also essential for the data migrations to run
468
+		//(because many need to convert old string states to foreign keys into the states table)
469
+		$this->insert_default_states();
470
+		$this->insert_default_countries();
471
+		//setting up DEFAULT prices, price types, and tickets is also essential for the price migrations
472
+		$this->insert_default_price_types();
473
+		$this->insert_default_prices();
474
+		$this->insert_default_tickets();
475
+		//setting up the config wp option pretty well counts as a 'schema change', or at least should happen ehre
476
+		EE_Config::instance()->update_espresso_config(false, true);
477
+		return true;
478
+	}
479
+
480
+
481
+
482
+	/**
483
+	 * Yes we could have cleaned up the ee3 tables here. But just in case someone
484
+	 * didn't backup their DB, and decides they want ot keep using EE3, we'll
485
+	 * leave them for now. Mayeb remove them in 4.5 or something.
486
+	 *
487
+	 * @return boolean
488
+	 */
489
+	public function schema_changes_after_migration()
490
+	{
491
+		return true;
492
+	}
493
+
494
+
495
+
496
+	/**
497
+	 * insert_default_states
498
+	 *
499
+	 * @access public
500
+	 * @static
501
+	 * @return void
502
+	 */
503
+	public function insert_default_states()
504
+	{
505
+		global $wpdb;
506
+		$state_table = $wpdb->prefix . "esp_state";
507
+		if ($this->_get_table_analysis()->tableExists($state_table)) {
508
+			$SQL = "SELECT COUNT('STA_ID') FROM " . $state_table;
509
+			$states = $wpdb->get_var($SQL);
510
+			if ( ! $states) {
511
+				$SQL = "INSERT INTO " . $state_table . "
512 512
 				(STA_ID, CNT_ISO, STA_abbrev, STA_name, STA_active) VALUES
513 513
 				(1, 'US', 'AK', 'Alaska', 1),
514 514
 				(2, 'US', 'AL', 'Alabama', 1),
@@ -579,29 +579,29 @@  discard block
 block discarded – undo
579 579
 				(67, 'CA', 'PE', 'Prince Edward Island', 1),
580 580
 				(68, 'CA', 'QC', 'Quebec', 1),
581 581
 				(69, 'CA', 'SK', 'Saskatchewan', 1);";
582
-                $wpdb->query($SQL);
583
-            }
584
-        }
585
-    }
586
-
587
-
588
-
589
-    /**
590
-     * insert_default_countries
591
-     *
592
-     * @access public
593
-     * @static
594
-     * @return void
595
-     */
596
-    public function insert_default_countries()
597
-    {
598
-        global $wpdb;
599
-        $country_table = $wpdb->prefix . "esp_country";
600
-        if ($this->_get_table_analysis()->tableExists($country_table)) {
601
-            $SQL = "SELECT COUNT('CNT_ISO') FROM " . $country_table;
602
-            $countries = $wpdb->get_var($SQL);
603
-            if ( ! $countries) {
604
-                $SQL = "INSERT INTO " . $country_table . "
582
+				$wpdb->query($SQL);
583
+			}
584
+		}
585
+	}
586
+
587
+
588
+
589
+	/**
590
+	 * insert_default_countries
591
+	 *
592
+	 * @access public
593
+	 * @static
594
+	 * @return void
595
+	 */
596
+	public function insert_default_countries()
597
+	{
598
+		global $wpdb;
599
+		$country_table = $wpdb->prefix . "esp_country";
600
+		if ($this->_get_table_analysis()->tableExists($country_table)) {
601
+			$SQL = "SELECT COUNT('CNT_ISO') FROM " . $country_table;
602
+			$countries = $wpdb->get_var($SQL);
603
+			if ( ! $countries) {
604
+				$SQL = "INSERT INTO " . $country_table . "
605 605
 				(CNT_ISO, CNT_ISO3, RGN_ID, CNT_name, CNT_cur_code, CNT_cur_single, CNT_cur_plural, CNT_cur_sign, CNT_cur_sign_b4, CNT_cur_dec_plc, CNT_tel_code, CNT_is_EU, CNT_active) VALUES
606 606
 				('AD', 'AND', 0, 'Andorra', 'EUR', 'Euro', 'Euros', '€', 1, 2, '+376', 0, 0),
607 607
 				('AE', 'ARE', 0, 'United Arab Emirates', 'AED', 'Dirham', 'Dirhams', 'د.إ', 1, 2, '+971', 0, 0),
@@ -829,941 +829,941 @@  discard block
 block discarded – undo
829 829
 				('ZA', 'ZAF', 0, 'South Africa', 'ZAR', 'Rand', 'Rands', 'R', 1, 2, '+27', 0, 0),
830 830
 				('ZM', 'ZMB', 0, 'Zambia', 'ZMK', 'Kwacha', 'Kwachas', '', 1, 2, '+260', 0, 0),
831 831
 				('ZW', 'ZWE', 0, 'Zimbabwe', 'ZWD', 'Dollar', 'Dollars', 'Z$', 1, 2, '+263', 0, 0);";
832
-                $wpdb->query($SQL);
833
-            }
834
-        }
835
-    }
836
-
837
-
838
-
839
-    /**
840
-     * insert_default_price_types
841
-     *
842
-     * @access public
843
-     * @static
844
-     * @return void
845
-     */
846
-    public function insert_default_price_types()
847
-    {
848
-        global $wpdb;
849
-        $price_type_table = $wpdb->prefix . "esp_price_type";
850
-        if ($this->_get_table_analysis()->tableExists($price_type_table)) {
851
-            $SQL = 'SELECT COUNT(PRT_ID) FROM ' . $price_type_table;
852
-            $price_types_exist = $wpdb->get_var($SQL);
853
-            if ( ! $price_types_exist) {
854
-                $SQL = "INSERT INTO $price_type_table ( PRT_ID, PRT_name, PBT_ID, PRT_is_percent, PRT_order, PRT_deleted ) VALUES
832
+				$wpdb->query($SQL);
833
+			}
834
+		}
835
+	}
836
+
837
+
838
+
839
+	/**
840
+	 * insert_default_price_types
841
+	 *
842
+	 * @access public
843
+	 * @static
844
+	 * @return void
845
+	 */
846
+	public function insert_default_price_types()
847
+	{
848
+		global $wpdb;
849
+		$price_type_table = $wpdb->prefix . "esp_price_type";
850
+		if ($this->_get_table_analysis()->tableExists($price_type_table)) {
851
+			$SQL = 'SELECT COUNT(PRT_ID) FROM ' . $price_type_table;
852
+			$price_types_exist = $wpdb->get_var($SQL);
853
+			if ( ! $price_types_exist) {
854
+				$SQL = "INSERT INTO $price_type_table ( PRT_ID, PRT_name, PBT_ID, PRT_is_percent, PRT_order, PRT_deleted ) VALUES
855 855
 							(1, '" . esc_html__('Base Price', 'event_espresso') . "', 1,  0, 0, 0),
856 856
 							(2, '" . esc_html__('Percent Discount', 'event_espresso') . "', 2,  1, 20, 0),
857 857
 							(3, '" . esc_html__('Fixed Discount', 'event_espresso') . "', 2,  0, 30, 0),
858 858
 							(4, '" . esc_html__('Percent Surcharge', 'event_espresso') . "', 3,  1, 40, 0),
859 859
 							(5, '" . esc_html__('Fixed Surcharge', 'event_espresso') . "', 3,  0, 50, 0);";
860
-                $SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_price_types__SQL', $SQL);
861
-                $wpdb->query($SQL);
862
-            }
863
-        }
864
-    }
865
-
866
-
867
-
868
-    /**
869
-     * insert_default_prices. We assume we're upgrading to regular here.
870
-     * If we're INSTALLING 4.1 CAF, then we add a few extra DEFAULT prices
871
-     * when EEH_Activaion's initialize_db_content is called via  ahook in
872
-     * EE_BRewing_regular
873
-     *
874
-     * @access public
875
-     * @static
876
-     * @return void
877
-     */
878
-    public function insert_default_prices()
879
-    {
880
-        global $wpdb;
881
-        $price_table = $wpdb->prefix . "esp_price";
882
-        if ($this->_get_table_analysis()->tableExists($price_table)) {
883
-            $SQL = 'SELECT COUNT(PRC_ID) FROM ' . $price_table;
884
-            $prices_exist = $wpdb->get_var($SQL);
885
-            if ( ! $prices_exist) {
886
-                $SQL = "INSERT INTO $price_table
860
+				$SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_price_types__SQL', $SQL);
861
+				$wpdb->query($SQL);
862
+			}
863
+		}
864
+	}
865
+
866
+
867
+
868
+	/**
869
+	 * insert_default_prices. We assume we're upgrading to regular here.
870
+	 * If we're INSTALLING 4.1 CAF, then we add a few extra DEFAULT prices
871
+	 * when EEH_Activaion's initialize_db_content is called via  ahook in
872
+	 * EE_BRewing_regular
873
+	 *
874
+	 * @access public
875
+	 * @static
876
+	 * @return void
877
+	 */
878
+	public function insert_default_prices()
879
+	{
880
+		global $wpdb;
881
+		$price_table = $wpdb->prefix . "esp_price";
882
+		if ($this->_get_table_analysis()->tableExists($price_table)) {
883
+			$SQL = 'SELECT COUNT(PRC_ID) FROM ' . $price_table;
884
+			$prices_exist = $wpdb->get_var($SQL);
885
+			if ( ! $prices_exist) {
886
+				$SQL = "INSERT INTO $price_table
887 887
 							(PRC_ID, PRT_ID, PRC_amount, PRC_name, PRC_desc,  PRC_is_default, PRC_overrides, PRC_order, PRC_deleted, PRC_parent ) VALUES
888 888
 							(1, 1, '0.00', 'Free Admission', '', 1, NULL, 0, 0, 0);";
889
-                $SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_prices__SQL', $SQL);
890
-                $wpdb->query($SQL);
891
-            }
892
-        }
893
-    }
894
-
895
-
896
-
897
-    /**
898
-     * insert DEFAULT ticket
899
-     *
900
-     * @access public
901
-     * @static
902
-     * @return void
903
-     */
904
-    public function insert_default_tickets()
905
-    {
906
-        global $wpdb;
907
-        $ticket_table = $wpdb->prefix . "esp_ticket";
908
-        if ($this->_get_table_analysis()->tableExists($ticket_table)) {
909
-            $SQL = 'SELECT COUNT(TKT_ID) FROM ' . $ticket_table;
910
-            $tickets_exist = $wpdb->get_var($SQL);
911
-            if ( ! $tickets_exist) {
912
-                $SQL = "INSERT INTO $ticket_table
889
+				$SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_prices__SQL', $SQL);
890
+				$wpdb->query($SQL);
891
+			}
892
+		}
893
+	}
894
+
895
+
896
+
897
+	/**
898
+	 * insert DEFAULT ticket
899
+	 *
900
+	 * @access public
901
+	 * @static
902
+	 * @return void
903
+	 */
904
+	public function insert_default_tickets()
905
+	{
906
+		global $wpdb;
907
+		$ticket_table = $wpdb->prefix . "esp_ticket";
908
+		if ($this->_get_table_analysis()->tableExists($ticket_table)) {
909
+			$SQL = 'SELECT COUNT(TKT_ID) FROM ' . $ticket_table;
910
+			$tickets_exist = $wpdb->get_var($SQL);
911
+			if ( ! $tickets_exist) {
912
+				$SQL = "INSERT INTO $ticket_table
913 913
 					( TKT_ID, TTM_ID, TKT_name, TKT_description, TKT_qty, TKT_sold, TKT_uses, TKT_min, TKT_max, TKT_price, TKT_start_date, TKT_end_date, TKT_taxable, TKT_order, TKT_row, TKT_is_default, TKT_parent, TKT_deleted ) VALUES
914 914
 					( 1, 0, '"
915
-                       . esc_html__("Free Ticket", "event_espresso")
916
-                       . "', '', 100, 0, -1, 0, -1, 0.00, '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, 0, 1, 1, 0, 0);";
917
-                $SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_tickets__SQL', $SQL);
918
-                $wpdb->query($SQL);
919
-            }
920
-        }
921
-        $ticket_price_table = $wpdb->prefix . "esp_ticket_price";
922
-        if ($this->_get_table_analysis()->tableExists($ticket_price_table)) {
923
-            $SQL = 'SELECT COUNT(TKP_ID) FROM ' . $ticket_price_table;
924
-            $ticket_prc_exist = $wpdb->get_var($SQL);
925
-            if ( ! $ticket_prc_exist) {
926
-                $SQL = "INSERT INTO $ticket_price_table
915
+					   . esc_html__("Free Ticket", "event_espresso")
916
+					   . "', '', 100, 0, -1, 0, -1, 0.00, '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, 0, 1, 1, 0, 0);";
917
+				$SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_tickets__SQL', $SQL);
918
+				$wpdb->query($SQL);
919
+			}
920
+		}
921
+		$ticket_price_table = $wpdb->prefix . "esp_ticket_price";
922
+		if ($this->_get_table_analysis()->tableExists($ticket_price_table)) {
923
+			$SQL = 'SELECT COUNT(TKP_ID) FROM ' . $ticket_price_table;
924
+			$ticket_prc_exist = $wpdb->get_var($SQL);
925
+			if ( ! $ticket_prc_exist) {
926
+				$SQL = "INSERT INTO $ticket_price_table
927 927
 				( TKP_ID, TKT_ID, PRC_ID ) VALUES
928 928
 				( 1, 1, 1 )
929 929
 				";
930
-                $SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_tickets__SQL__ticket_price', $SQL);
931
-                $wpdb->query($SQL);
932
-            }
933
-        }
934
-    }
935
-
936
-
937
-
938
-    /**
939
-     * Gets a country entry as an array, or creates one if none is found. Much like EEM_Country::instance()->get_one(),
940
-     * but is independent of outside code which can change in future versions of EE. Also, $country_name CAN be a 3.1
941
-     * country ID (int), a 2-letter ISO, 3-letter ISO, or name
942
-     *
943
-     * @global type  $wpdb
944
-     * @param string $country_name
945
-     * @return array where keys are columns, values are column values
946
-     */
947
-    public function get_or_create_country($country_name)
948
-    {
949
-        if ( ! $country_name) {
950
-            throw new EE_Error(esc_html__("Could not get a country because country name is blank", "event_espresso"));
951
-        }
952
-        global $wpdb;
953
-        $country_table = $wpdb->prefix . "esp_country";
954
-        if (is_int($country_name)) {
955
-            $country_name = $this->get_iso_from_3_1_country_id($country_name);
956
-        }
957
-        $country = $wpdb->get_row($wpdb->prepare("SELECT * FROM $country_table WHERE
930
+				$SQL = apply_filters('FHEE__EE_DMS_4_1_0__insert_default_tickets__SQL__ticket_price', $SQL);
931
+				$wpdb->query($SQL);
932
+			}
933
+		}
934
+	}
935
+
936
+
937
+
938
+	/**
939
+	 * Gets a country entry as an array, or creates one if none is found. Much like EEM_Country::instance()->get_one(),
940
+	 * but is independent of outside code which can change in future versions of EE. Also, $country_name CAN be a 3.1
941
+	 * country ID (int), a 2-letter ISO, 3-letter ISO, or name
942
+	 *
943
+	 * @global type  $wpdb
944
+	 * @param string $country_name
945
+	 * @return array where keys are columns, values are column values
946
+	 */
947
+	public function get_or_create_country($country_name)
948
+	{
949
+		if ( ! $country_name) {
950
+			throw new EE_Error(esc_html__("Could not get a country because country name is blank", "event_espresso"));
951
+		}
952
+		global $wpdb;
953
+		$country_table = $wpdb->prefix . "esp_country";
954
+		if (is_int($country_name)) {
955
+			$country_name = $this->get_iso_from_3_1_country_id($country_name);
956
+		}
957
+		$country = $wpdb->get_row($wpdb->prepare("SELECT * FROM $country_table WHERE
958 958
 			CNT_ISO LIKE %s OR
959 959
 			CNT_ISO3 LIKE %s OR
960 960
 			CNT_name LIKE %s LIMIT 1", $country_name, $country_name, $country_name), ARRAY_A);
961
-        if ( ! $country) {
962
-            //insert a new one then
963
-            $cols_n_values = array(
964
-                    'CNT_ISO'         => $this->_find_available_country_iso(2),
965
-                    'CNT_ISO3'        => $this->_find_available_country_iso(3),
966
-                    'RGN_ID'          => 0,
967
-                    'CNT_name'        => $country_name,
968
-                    'CNT_cur_code'    => 'USD',
969
-                    'CNT_cur_single'  => 'Dollar',
970
-                    'CNT_cur_plural'  => 'Dollars',
971
-                    'CNT_cur_sign'    => '&#36;',
972
-                    'CNT_cur_sign_b4' => true,
973
-                    'CNT_cur_dec_plc' => 2,
974
-                    'CNT_cur_dec_mrk' => '.',
975
-                    'CNT_cur_thsnds'  => ',',
976
-                    'CNT_tel_code'    => '+1',
977
-                    'CNT_is_EU'       => false,
978
-                    'CNT_active'      => true,
979
-            );
980
-            $data_types = array(
981
-                    '%s',//CNT_ISO
982
-                    '%s',//CNT_ISO3
983
-                    '%d',//RGN_ID
984
-                    '%s',//CNT_name
985
-                    '%s',//CNT_cur_code
986
-                    '%s',//CNT_cur_single
987
-                    '%s',//CNT_cur_plural
988
-                    '%s',//CNT_cur_sign
989
-                    '%d',//CNT_cur_sign_b4
990
-                    '%d',//CNT_cur_dec_plc
991
-                    '%s',//CNT_cur_dec_mrk
992
-                    '%s',//CNT_cur_thsnds
993
-                    '%s',//CNT_tel_code
994
-                    '%d',//CNT_is_EU
995
-                    '%d',//CNT_active
996
-            );
997
-            $success = $wpdb->insert($country_table,
998
-                    $cols_n_values,
999
-                    $data_types);
1000
-            if ( ! $success) {
1001
-                throw new EE_Error($this->_create_error_message_for_db_insertion('N/A',
1002
-                        array('country_id' => $country_name), $country_table, $cols_n_values, $data_types));
1003
-            }
1004
-            $country = $cols_n_values;
1005
-        }
1006
-        return $country;
1007
-    }
1008
-
1009
-
1010
-
1011
-    /**
1012
-     * finds a country iso which hasnt been used yet
1013
-     *
1014
-     * @global type $wpdb
1015
-     * @return string
1016
-     */
1017
-    private function _find_available_country_iso($num_letters = 2)
1018
-    {
1019
-        global $wpdb;
1020
-        $country_table = $wpdb->prefix . "esp_country";
1021
-        $attempts = 0;
1022
-        do {
1023
-            $current_iso = strtoupper(wp_generate_password($num_letters, false));
1024
-            $country_with_that_iso = $wpdb->get_var($wpdb->prepare("SELECT count(CNT_ISO) FROM "
1025
-                                                                   . $country_table
1026
-                                                                   . " WHERE CNT_ISO=%s", $current_iso));
1027
-            $attempts++;
1028
-            //keep going until we find an available country code, or we arbitrarily
1029
-            //decide we've tried this enough. Somehow they have way too many countries
1030
-            //(probably because they're mis-using the EE3 country_id like a custom question)
1031
-        } while (intval($country_with_that_iso) && $attempts < 200);
1032
-        return $current_iso;
1033
-    }
1034
-
1035
-
1036
-
1037
-    /**
1038
-     * Gets a state entry as an array, or creates one if none is found. Much like EEM_State::instance()->get_one(), but
1039
-     * is independent of outside code which can change in future versions of EE
1040
-     *
1041
-     * @global type  $wpdb
1042
-     * @param string $state_name
1043
-     * @return array where keys are columns, values are column values
1044
-     */
1045
-    public function get_or_create_state($state_name, $country_name = '')
1046
-    {
1047
-        if ( ! $state_name) {
1048
-            throw new EE_Error(esc_html__("Could not get-or-create state because no state name was provided",
1049
-                    "event_espresso"));
1050
-        }
1051
-        try {
1052
-            $country = $this->get_or_create_country($country_name);
1053
-            $country_iso = $country['CNT_ISO'];
1054
-        } catch (EE_Error $e) {
1055
-            $country_iso = $this->get_default_country_iso();
1056
-        }
1057
-        global $wpdb;
1058
-        $state_table = $wpdb->prefix . "esp_state";
1059
-        $state = $wpdb->get_row($wpdb->prepare("SELECT * FROM $state_table WHERE
961
+		if ( ! $country) {
962
+			//insert a new one then
963
+			$cols_n_values = array(
964
+					'CNT_ISO'         => $this->_find_available_country_iso(2),
965
+					'CNT_ISO3'        => $this->_find_available_country_iso(3),
966
+					'RGN_ID'          => 0,
967
+					'CNT_name'        => $country_name,
968
+					'CNT_cur_code'    => 'USD',
969
+					'CNT_cur_single'  => 'Dollar',
970
+					'CNT_cur_plural'  => 'Dollars',
971
+					'CNT_cur_sign'    => '&#36;',
972
+					'CNT_cur_sign_b4' => true,
973
+					'CNT_cur_dec_plc' => 2,
974
+					'CNT_cur_dec_mrk' => '.',
975
+					'CNT_cur_thsnds'  => ',',
976
+					'CNT_tel_code'    => '+1',
977
+					'CNT_is_EU'       => false,
978
+					'CNT_active'      => true,
979
+			);
980
+			$data_types = array(
981
+					'%s',//CNT_ISO
982
+					'%s',//CNT_ISO3
983
+					'%d',//RGN_ID
984
+					'%s',//CNT_name
985
+					'%s',//CNT_cur_code
986
+					'%s',//CNT_cur_single
987
+					'%s',//CNT_cur_plural
988
+					'%s',//CNT_cur_sign
989
+					'%d',//CNT_cur_sign_b4
990
+					'%d',//CNT_cur_dec_plc
991
+					'%s',//CNT_cur_dec_mrk
992
+					'%s',//CNT_cur_thsnds
993
+					'%s',//CNT_tel_code
994
+					'%d',//CNT_is_EU
995
+					'%d',//CNT_active
996
+			);
997
+			$success = $wpdb->insert($country_table,
998
+					$cols_n_values,
999
+					$data_types);
1000
+			if ( ! $success) {
1001
+				throw new EE_Error($this->_create_error_message_for_db_insertion('N/A',
1002
+						array('country_id' => $country_name), $country_table, $cols_n_values, $data_types));
1003
+			}
1004
+			$country = $cols_n_values;
1005
+		}
1006
+		return $country;
1007
+	}
1008
+
1009
+
1010
+
1011
+	/**
1012
+	 * finds a country iso which hasnt been used yet
1013
+	 *
1014
+	 * @global type $wpdb
1015
+	 * @return string
1016
+	 */
1017
+	private function _find_available_country_iso($num_letters = 2)
1018
+	{
1019
+		global $wpdb;
1020
+		$country_table = $wpdb->prefix . "esp_country";
1021
+		$attempts = 0;
1022
+		do {
1023
+			$current_iso = strtoupper(wp_generate_password($num_letters, false));
1024
+			$country_with_that_iso = $wpdb->get_var($wpdb->prepare("SELECT count(CNT_ISO) FROM "
1025
+																   . $country_table
1026
+																   . " WHERE CNT_ISO=%s", $current_iso));
1027
+			$attempts++;
1028
+			//keep going until we find an available country code, or we arbitrarily
1029
+			//decide we've tried this enough. Somehow they have way too many countries
1030
+			//(probably because they're mis-using the EE3 country_id like a custom question)
1031
+		} while (intval($country_with_that_iso) && $attempts < 200);
1032
+		return $current_iso;
1033
+	}
1034
+
1035
+
1036
+
1037
+	/**
1038
+	 * Gets a state entry as an array, or creates one if none is found. Much like EEM_State::instance()->get_one(), but
1039
+	 * is independent of outside code which can change in future versions of EE
1040
+	 *
1041
+	 * @global type  $wpdb
1042
+	 * @param string $state_name
1043
+	 * @return array where keys are columns, values are column values
1044
+	 */
1045
+	public function get_or_create_state($state_name, $country_name = '')
1046
+	{
1047
+		if ( ! $state_name) {
1048
+			throw new EE_Error(esc_html__("Could not get-or-create state because no state name was provided",
1049
+					"event_espresso"));
1050
+		}
1051
+		try {
1052
+			$country = $this->get_or_create_country($country_name);
1053
+			$country_iso = $country['CNT_ISO'];
1054
+		} catch (EE_Error $e) {
1055
+			$country_iso = $this->get_default_country_iso();
1056
+		}
1057
+		global $wpdb;
1058
+		$state_table = $wpdb->prefix . "esp_state";
1059
+		$state = $wpdb->get_row($wpdb->prepare("SELECT * FROM $state_table WHERE
1060 1060
 			(STA_abbrev LIKE %s OR
1061 1061
 			STA_name LIKE %s) AND
1062 1062
 			CNT_ISO LIKE %s LIMIT 1", $state_name, $state_name, $country_iso), ARRAY_A);
1063
-        if ( ! $state) {
1064
-            //insert a new one then
1065
-            $cols_n_values = array(
1066
-                    'CNT_ISO'    => $country_iso,
1067
-                    'STA_abbrev' => substr($state_name, 0, 6),
1068
-                    'STA_name'   => $state_name,
1069
-                    'STA_active' => true,
1070
-            );
1071
-            $data_types = array(
1072
-                    '%s',//CNT_ISO
1073
-                    '%s',//STA_abbrev
1074
-                    '%s',//STA_name
1075
-                    '%d',//STA_active
1076
-            );
1077
-            $success = $wpdb->insert($state_table, $cols_n_values, $data_types);
1078
-            if ( ! $success) {
1079
-                throw new EE_Error($this->_create_error_message_for_db_insertion('N/A',
1080
-                        array('state' => $state_name, 'country_id' => $country_name), $state_table, $cols_n_values,
1081
-                        $data_types));
1082
-            }
1083
-            $state = $cols_n_values;
1084
-            $state['STA_ID'] = $wpdb->insert_id;
1085
-        }
1086
-        return $state;
1087
-    }
1088
-
1089
-
1090
-
1091
-    /**
1092
-     * Fixes times like "5:00 PM" into the expected 24-hour format "17:00".
1093
-     * THis is actually just copied from the 3.1 JSON API because it needed to do the exact same thing
1094
-     *
1095
-     * @param type $timeString
1096
-     * @return string in the php DATETIME format: "G:i" (24-hour format hour with leading zeros, a colon, and minutes
1097
-     *                with leading zeros)
1098
-     */
1099
-    public function convertTimeFromAMPM($timeString)
1100
-    {
1101
-        $matches = array();
1102
-        preg_match("~(\\d*):(\\d*)~", $timeString, $matches);
1103
-        if ( ! $matches || count($matches) < 3) {
1104
-            $hour = '00';
1105
-            $minutes = '00';
1106
-        } else {
1107
-            $hour = intval($matches[1]);
1108
-            $minutes = $matches[2];
1109
-        }
1110
-        if (strpos($timeString, 'PM') || strpos($timeString, 'pm')) {
1111
-            $hour = intval($hour) + 12;
1112
-        }
1113
-        $hour = str_pad("$hour", 2, '0', STR_PAD_LEFT);
1114
-        $minutes = str_pad("$minutes", 2, '0', STR_PAD_LEFT);
1115
-        return "$hour:$minutes";
1116
-    }
1117
-
1118
-
1119
-
1120
-    /**
1121
-     * Gets the ISO3 fora country given its 3.1 country ID.
1122
-     *
1123
-     * @param int $country_id
1124
-     * @return string the country's ISO3 code
1125
-     */
1126
-    public function get_iso_from_3_1_country_id($country_id)
1127
-    {
1128
-        $old_countries = array(
1129
-                array(64, 'United States', 'US', 'USA', 1),
1130
-                array(15, 'Australia', 'AU', 'AUS', 1),
1131
-                array(39, 'Canada', 'CA', 'CAN', 1),
1132
-                array(171, 'United Kingdom', 'GB', 'GBR', 1),
1133
-                array(70, 'France', 'FR', 'FRA', 2),
1134
-                array(111, 'Italy', 'IT', 'ITA', 2),
1135
-                array(63, 'Spain', 'ES', 'ESP', 2),
1136
-                array(1, 'Afghanistan', 'AF', 'AFG', 1),
1137
-                array(2, 'Albania', 'AL', 'ALB', 1),
1138
-                array(3, 'Germany', 'DE', 'DEU', 2),
1139
-                array(198, 'Switzerland', 'CH', 'CHE', 1),
1140
-                array(87, 'Netherlands', 'NL', 'NLD', 2),
1141
-                array(197, 'Sweden', 'SE', 'SWE', 1),
1142
-                array(230, 'Akrotiri and Dhekelia', 'CY', 'CYP', 2),
1143
-                array(4, 'Andorra', 'AD', 'AND', 2),
1144
-                array(5, 'Angola', 'AO', 'AGO', 1),
1145
-                array(6, 'Anguilla', 'AI', 'AIA', 1),
1146
-                array(7, 'Antarctica', 'AQ', 'ATA', 1),
1147
-                array(8, 'Antigua and Barbuda', 'AG', 'ATG', 1),
1148
-                array(10, 'Saudi Arabia', 'SA', 'SAU', 1),
1149
-                array(11, 'Algeria', 'DZ', 'DZA', 1),
1150
-                array(12, 'Argentina', 'AR', 'ARG', 1),
1151
-                array(13, 'Armenia', 'AM', 'ARM', 1),
1152
-                array(14, 'Aruba', 'AW', 'ABW', 1),
1153
-                array(16, 'Austria', 'AT', 'AUT', 2),
1154
-                array(17, 'Azerbaijan', 'AZ', 'AZE', 1),
1155
-                array(18, 'Bahamas', 'BS', 'BHS', 1),
1156
-                array(19, 'Bahrain', 'BH', 'BHR', 1),
1157
-                array(20, 'Bangladesh', 'BD', 'BGD', 1),
1158
-                array(21, 'Barbados', 'BB', 'BRB', 1),
1159
-                array(22, 'Belgium ', 'BE', 'BEL', 2),
1160
-                array(23, 'Belize', 'BZ', 'BLZ', 1),
1161
-                array(24, 'Benin', 'BJ', 'BEN', 1),
1162
-                array(25, 'Bermudas', 'BM', 'BMU', 1),
1163
-                array(26, 'Belarus', 'BY', 'BLR', 1),
1164
-                array(27, 'Bolivia', 'BO', 'BOL', 1),
1165
-                array(28, 'Bosnia and Herzegovina', 'BA', 'BIH', 1),
1166
-                array(29, 'Botswana', 'BW', 'BWA', 1),
1167
-                array(96, 'Bouvet Island', 'BV', 'BVT', 1),
1168
-                array(30, 'Brazil', 'BR', 'BRA', 1),
1169
-                array(31, 'Brunei', 'BN', 'BRN', 1),
1170
-                array(32, 'Bulgaria', 'BG', 'BGR', 1),
1171
-                array(33, 'Burkina Faso', 'BF', 'BFA', 1),
1172
-                array(34, 'Burundi', 'BI', 'BDI', 1),
1173
-                array(35, 'Bhutan', 'BT', 'BTN', 1),
1174
-                array(36, 'Cape Verde', 'CV', 'CPV', 1),
1175
-                array(37, 'Cambodia', 'KH', 'KHM', 1),
1176
-                array(38, 'Cameroon', 'CM', 'CMR', 1),
1177
-                array(98, 'Cayman Islands', 'KY', 'CYM', 1),
1178
-                array(172, 'Central African Republic', 'CF', 'CAF', 1),
1179
-                array(40, 'Chad', 'TD', 'TCD', 1),
1180
-                array(41, 'Chile', 'CL', 'CHL', 1),
1181
-                array(42, 'China', 'CN', 'CHN', 1),
1182
-                array(105, 'Christmas Island', 'CX', 'CXR', 1),
1183
-                array(43, 'Cyprus', 'CY', 'CYP', 2),
1184
-                array(99, 'Cocos Island', 'CC', 'CCK', 1),
1185
-                array(100, 'Cook Islands', 'CK', 'COK', 1),
1186
-                array(44, 'Colombia', 'CO', 'COL', 1),
1187
-                array(45, 'Comoros', 'KM', 'COM', 1),
1188
-                array(46, 'Congo', 'CG', 'COG', 1),
1189
-                array(47, 'North Korea', 'KP', 'PRK', 1),
1190
-                array(50, 'Costa Rica', 'CR', 'CRI', 1),
1191
-                array(51, 'Croatia', 'HR', 'HRV', 1),
1192
-                array(52, 'Cuba', 'CU', 'CUB', 1),
1193
-                array(173, 'Czech Republic', 'CZ', 'CZE', 1),
1194
-                array(53, 'Denmark', 'DK', 'DNK', 1),
1195
-                array(54, 'Djibouti', 'DJ', 'DJI', 1),
1196
-                array(55, 'Dominica', 'DM', 'DMA', 1),
1197
-                array(174, 'Dominican Republic', 'DO', 'DOM', 1),
1198
-                array(56, 'Ecuador', 'EC', 'ECU', 1),
1199
-                array(57, 'Egypt', 'EG', 'EGY', 1),
1200
-                array(58, 'El Salvador', 'SV', 'SLV', 1),
1201
-                array(60, 'Eritrea', 'ER', 'ERI', 1),
1202
-                array(61, 'Slovakia', 'SK', 'SVK', 2),
1203
-                array(62, 'Slovenia', 'SI', 'SVN', 2),
1204
-                array(65, 'Estonia', 'EE', 'EST', 2),
1205
-                array(66, 'Ethiopia', 'ET', 'ETH', 1),
1206
-                array(102, 'Faroe islands', 'FO', 'FRO', 1),
1207
-                array(103, 'Falkland Islands', 'FK', 'FLK', 1),
1208
-                array(67, 'Fiji', 'FJ', 'FJI', 1),
1209
-                array(69, 'Finland', 'FI', 'FIN', 2),
1210
-                array(71, 'Gabon', 'GA', 'GAB', 1),
1211
-                array(72, 'Gambia', 'GM', 'GMB', 1),
1212
-                array(73, 'Georgia', 'GE', 'GEO', 1),
1213
-                array(74, 'Ghana', 'GH', 'GHA', 1),
1214
-                array(75, 'Gibraltar', 'GI', 'GIB', 1),
1215
-                array(76, 'Greece', 'GR', 'GRC', 2),
1216
-                array(77, 'Grenada', 'GD', 'GRD', 1),
1217
-                array(78, 'Greenland', 'GL', 'GRL', 1),
1218
-                array(79, 'Guadeloupe', 'GP', 'GLP', 1),
1219
-                array(80, 'Guam', 'GU', 'GUM', 1),
1220
-                array(81, 'Guatemala', 'GT', 'GTM', 1),
1221
-                array(82, 'Guinea', 'GN', 'GIN', 1),
1222
-                array(83, 'Equatorial Guinea', 'GQ', 'GNQ', 1),
1223
-                array(84, 'Guinea-Bissau', 'GW', 'GNB', 1),
1224
-                array(85, 'Guyana', 'GY', 'GUY', 1),
1225
-                array(86, 'Haiti', 'HT', 'HTI', 1),
1226
-                array(88, 'Honduras', 'HN', 'HND', 1),
1227
-                array(89, 'Hong Kong', 'HK', 'HKG', 1),
1228
-                array(90, 'Hungary', 'HU', 'HUN', 1),
1229
-                array(91, 'India', 'IN', 'IND', 1),
1230
-                array(205, 'British Indian Ocean Territory', 'IO', 'IOT', 1),
1231
-                array(92, 'Indonesia', 'ID', 'IDN', 1),
1232
-                array(93, 'Iraq', 'IQ', 'IRQ', 1),
1233
-                array(94, 'Iran', 'IR', 'IRN', 1),
1234
-                array(95, 'Ireland', 'IE', 'IRL', 2),
1235
-                array(97, 'Iceland', 'IS', 'ISL', 1),
1236
-                array(110, 'Israel', 'IL', 'ISR', 1),
1237
-                array(49, 'Ivory Coast ', 'CI', 'CIV', 1),
1238
-                array(112, 'Jamaica', 'JM', 'JAM', 1),
1239
-                array(113, 'Japan', 'JP', 'JPN', 1),
1240
-                array(114, 'Jordan', 'JO', 'JOR', 1),
1241
-                array(115, 'Kazakhstan', 'KZ', 'KAZ', 1),
1242
-                array(116, 'Kenya', 'KE', 'KEN', 1),
1243
-                array(117, 'Kyrgyzstan', 'KG', 'KGZ', 1),
1244
-                array(118, 'Kiribati', 'KI', 'KIR', 1),
1245
-                array(48, 'South Korea', 'KR', 'KOR', 1),
1246
-                array(228, 'Kosovo', 'XK', 'XKV', 2),
1247
-                // there is no official ISO code for Kosovo yet (http://geonames.wordpress.com/2010/03/08/xk-country-code-for-kosovo/) so using a temporary country code and a modified 3 character code for ISO code -- this should be updated if/when Kosovo gets its own ISO code
1248
-                array(119, 'Kuwait', 'KW', 'KWT', 1),
1249
-                array(120, 'Laos', 'LA', 'LAO', 1),
1250
-                array(121, 'Latvia', 'LV', 'LVA', 2),
1251
-                array(122, 'Lesotho', 'LS', 'LSO', 1),
1252
-                array(123, 'Lebanon', 'LB', 'LBN', 1),
1253
-                array(124, 'Liberia', 'LR', 'LBR', 1),
1254
-                array(125, 'Libya', 'LY', 'LBY', 1),
1255
-                array(126, 'Liechtenstein', 'LI', 'LIE', 1),
1256
-                array(127, 'Lithuania', 'LT', 'LTU', 2),
1257
-                array(128, 'Luxemburg', 'LU', 'LUX', 2),
1258
-                array(129, 'Macao', 'MO', 'MAC', 1),
1259
-                array(130, 'Macedonia', 'MK', 'MKD', 1),
1260
-                array(131, 'Madagascar', 'MG', 'MDG', 1),
1261
-                array(132, 'Malaysia', 'MY', 'MYS', 1),
1262
-                array(133, 'Malawi', 'MW', 'MWI', 1),
1263
-                array(134, 'Maldivas', 'MV', 'MDV', 1),
1264
-                array(135, 'Mali', 'ML', 'MLI', 1),
1265
-                array(136, 'Malta', 'MT', 'MLT', 2),
1266
-                array(101, 'Northern Marianas', 'MP', 'MNP', 1),
1267
-                array(137, 'Morocco', 'MA', 'MAR', 1),
1268
-                array(104, 'Marshall islands', 'MH', 'MHL', 1),
1269
-                array(138, 'Martinique', 'MQ', 'MTQ', 1),
1270
-                array(139, 'Mauritius', 'MU', 'MUS', 1),
1271
-                array(140, 'Mauritania', 'MR', 'MRT', 1),
1272
-                array(141, 'Mayote', 'YT', 'MYT', 2),
1273
-                array(142, 'Mexico', 'MX', 'MEX', 1),
1274
-                array(143, 'Micronesia', 'FM', 'FSM', 1),
1275
-                array(144, 'Moldova', 'MD', 'MDA', 1),
1276
-                array(145, 'Monaco', 'MC', 'MCO', 2),
1277
-                array(146, 'Mongolia', 'MN', 'MNG', 1),
1278
-                array(147, 'Montserrat', 'MS', 'MSR', 1),
1279
-                array(227, 'Montenegro', 'ME', 'MNE', 2),
1280
-                array(148, 'Mozambique', 'MZ', 'MOZ', 1),
1281
-                array(149, 'Myanmar', 'MM', 'MMR', 1),
1282
-                array(150, 'Namibia', 'NA', 'NAM', 1),
1283
-                array(151, 'Nauru', 'NR', 'NRU', 1),
1284
-                array(152, 'Nepal', 'NP', 'NPL', 1),
1285
-                array(9, 'Netherlands Antilles', 'AN', 'ANT', 1),
1286
-                array(153, 'Nicaragua', 'NI', 'NIC', 1),
1287
-                array(154, 'Niger', 'NE', 'NER', 1),
1288
-                array(155, 'Nigeria', 'NG', 'NGA', 1),
1289
-                array(156, 'Niue', 'NU', 'NIU', 1),
1290
-                array(157, 'Norway', 'NO', 'NOR', 1),
1291
-                array(158, 'New Caledonia', 'NC', 'NCL', 1),
1292
-                array(159, 'New Zealand', 'NZ', 'NZL', 1),
1293
-                array(160, 'Oman', 'OM', 'OMN', 1),
1294
-                array(161, 'Pakistan', 'PK', 'PAK', 1),
1295
-                array(162, 'Palau', 'PW', 'PLW', 1),
1296
-                array(163, 'Panama', 'PA', 'PAN', 1),
1297
-                array(164, 'Papua New Guinea', 'PG', 'PNG', 1),
1298
-                array(165, 'Paraguay', 'PY', 'PRY', 1),
1299
-                array(166, 'Peru', 'PE', 'PER', 1),
1300
-                array(68, 'Philippines', 'PH', 'PHL', 1),
1301
-                array(167, 'Poland', 'PL', 'POL', 1),
1302
-                array(168, 'Portugal', 'PT', 'PRT', 2),
1303
-                array(169, 'Puerto Rico', 'PR', 'PRI', 1),
1304
-                array(170, 'Qatar', 'QA', 'QAT', 1),
1305
-                array(176, 'Rwanda', 'RW', 'RWA', 1),
1306
-                array(177, 'Romania', 'RO', 'ROM', 2),
1307
-                array(178, 'Russia', 'RU', 'RUS', 1),
1308
-                array(229, 'Saint Pierre and Miquelon', 'PM', 'SPM', 2),
1309
-                array(180, 'Samoa', 'WS', 'WSM', 1),
1310
-                array(181, 'American Samoa', 'AS', 'ASM', 1),
1311
-                array(183, 'San Marino', 'SM', 'SMR', 2),
1312
-                array(184, 'Saint Vincent and the Grenadines', 'VC', 'VCT', 1),
1313
-                array(185, 'Saint Helena', 'SH', 'SHN', 1),
1314
-                array(186, 'Saint Lucia', 'LC', 'LCA', 1),
1315
-                array(188, 'Senegal', 'SN', 'SEN', 1),
1316
-                array(189, 'Seychelles', 'SC', 'SYC', 1),
1317
-                array(190, 'Sierra Leona', 'SL', 'SLE', 1),
1318
-                array(191, 'Singapore', 'SG', 'SGP', 1),
1319
-                array(192, 'Syria', 'SY', 'SYR', 1),
1320
-                array(193, 'Somalia', 'SO', 'SOM', 1),
1321
-                array(194, 'Sri Lanka', 'LK', 'LKA', 1),
1322
-                array(195, 'South Africa', 'ZA', 'ZAF', 1),
1323
-                array(196, 'Sudan', 'SD', 'SDN', 1),
1324
-                array(199, 'Suriname', 'SR', 'SUR', 1),
1325
-                array(200, 'Swaziland', 'SZ', 'SWZ', 1),
1326
-                array(201, 'Thailand', 'TH', 'THA', 1),
1327
-                array(202, 'Taiwan', 'TW', 'TWN', 1),
1328
-                array(203, 'Tanzania', 'TZ', 'TZA', 1),
1329
-                array(204, 'Tajikistan', 'TJ', 'TJK', 1),
1330
-                array(206, 'Timor-Leste', 'TL', 'TLS', 1),
1331
-                array(207, 'Togo', 'TG', 'TGO', 1),
1332
-                array(208, 'Tokelau', 'TK', 'TKL', 1),
1333
-                array(209, 'Tonga', 'TO', 'TON', 1),
1334
-                array(210, 'Trinidad and Tobago', 'TT', 'TTO', 1),
1335
-                array(211, 'Tunisia', 'TN', 'TUN', 1),
1336
-                array(212, 'Turkmenistan', 'TM', 'TKM', 1),
1337
-                array(213, 'Turkey', 'TR', 'TUR', 1),
1338
-                array(214, 'Tuvalu', 'TV', 'TUV', 1),
1339
-                array(215, 'Ukraine', 'UA', 'UKR', 1),
1340
-                array(216, 'Uganda', 'UG', 'UGA', 1),
1341
-                array(59, 'United Arab Emirates', 'AE', 'ARE', 1),
1342
-                array(217, 'Uruguay', 'UY', 'URY', 1),
1343
-                array(218, 'Uzbekistan', 'UZ', 'UZB', 1),
1344
-                array(219, 'Vanuatu', 'VU', 'VUT', 1),
1345
-                array(220, 'Vatican City', 'VA', 'VAT', 2),
1346
-                array(221, 'Venezuela', 'VE', 'VEN', 1),
1347
-                array(222, 'Vietnam', 'VN', 'VNM', 1),
1348
-                array(108, 'Virgin Islands', 'VI', 'VIR', 1),
1349
-                array(223, 'Yemen', 'YE', 'YEM', 1),
1350
-                array(225, 'Zambia', 'ZM', 'ZMB', 1),
1351
-                array(226, 'Zimbabwe', 'ZW', 'ZWE', 1),
1352
-        );
1353
-        $country_iso = 'US';
1354
-        foreach ($old_countries as $country_array) {
1355
-            //note: index 0 is the 3.1 country ID
1356
-            if ($country_array[0] == $country_id) {
1357
-                //note: index 2 is the ISO
1358
-                $country_iso = $country_array[2];
1359
-                break;
1360
-            }
1361
-        }
1362
-        return $country_iso;
1363
-    }
1364
-
1365
-
1366
-
1367
-    /**
1368
-     * Gets the ISO3 for the
1369
-     *
1370
-     * @return string
1371
-     */
1372
-    public function get_default_country_iso()
1373
-    {
1374
-        $old_org_options = get_option('events_organization_settings');
1375
-        $iso = $this->get_iso_from_3_1_country_id($old_org_options['organization_country']);
1376
-        return $iso;
1377
-    }
1378
-
1379
-
1380
-
1381
-    /**
1382
-     * Converst a 3.1 payment status to its equivalent 4.1 regisration status
1383
-     *
1384
-     * @param string  $payment_status                   possible value for 3.1's evens_attendee.payment_status
1385
-     * @param boolean $this_thing_required_pre_approval whether the thing we're considering (the general setting's
1386
-     *                                                  DEFAULT payment status, the event's DEFAULT payment status, or
1387
-     *                                                  the attendee's payment status) required pre-approval.
1388
-     * @return string STS_ID for use in 4.1
1389
-     */
1390
-    public function convert_3_1_payment_status_to_4_1_STS_ID($payment_status, $this_thing_required_pre_approval = false)
1391
-    {
1392
-        //EE team can read the related discussion: https://app.asana.com/0/2400967562914/9418495544455
1393
-        if ($this_thing_required_pre_approval) {
1394
-            return 'RNA';
1395
-        } else {
1396
-            $mapping = $default_reg_stati_conversions = array(
1397
-                    'Completed'        => 'RAP',
1398
-                    ''                 => 'RPP',
1399
-                    'Incomplete'       => 'RPP',
1400
-                    'Pending'          => 'RAP',
1401
-                    //stati that only occurred on 3.1 attendees:
1402
-                    'Payment Declined' => 'RPP',
1403
-                    'Not Completed'    => 'RPP',
1404
-                    'Cancelled'        => 'RPP',
1405
-                    'Declined'         => 'RPP',
1406
-            );
1407
-        }
1408
-        return isset($mapping[$payment_status]) ? $mapping[$payment_status] : 'RNA';
1409
-    }
1410
-
1411
-
1412
-
1413
-    /**
1414
-     * Makes sure the 3.1's image url is converted to an image attachment post to the 4.1 CPT event
1415
-     * and sets it as the featured image on the CPT event
1416
-     *
1417
-     * @param type                            $old_event
1418
-     * @param type                            $new_cpt_id
1419
-     * @param  EE_Data_Migration_Script_Stage $migration_stage the stage which called this, where errors should be added
1420
-     * @return boolean whether or not we had to do the big job of creating an image attachment
1421
-     */
1422
-    public function convert_image_url_to_attachment_and_attach_to_post(
1423
-            $guid,
1424
-            $new_cpt_id,
1425
-            EE_Data_Migration_Script_Stage $migration_stage
1426
-    ) {
1427
-        $created_attachment_post = false;
1428
-        $guid = $this->_get_original_guid($guid);
1429
-        if ($guid) {
1430
-            //check for an existing attachment post with this guid
1431
-            $attachment_post_id = $this->_get_image_attachment_id_by_GUID($guid);
1432
-            if ( ! $attachment_post_id) {
1433
-                //post thumbnail with that GUID doesn't exist, we should create one
1434
-                $attachment_post_id = $this->_create_image_attachment_from_GUID($guid, $migration_stage);
1435
-                $created_attachment_post = true;
1436
-            }
1437
-            //double-check we actually have an attachment post
1438
-            if ($attachment_post_id) {
1439
-                update_post_meta($new_cpt_id, '_thumbnail_id', $attachment_post_id);
1440
-            } else {
1441
-                $migration_stage->add_error(sprintf(esc_html__("Could not update event image %s for CPT with ID %d, but attachments post ID is %d",
1442
-                        "event_espresso"), $guid, $new_cpt_id, $attachment_post_id));
1443
-            }
1444
-        }
1445
-        return $created_attachment_post;
1446
-    }
1447
-
1448
-
1449
-
1450
-    /**
1451
-     * In 3.1, the event thumbnail image DOESN'T point to the orignal image, but instead
1452
-     * to a large thumbnail (which has nearly the same GUID, except it adds "-{width}x{height}" before the filetype,
1453
-     * or whatever dimensions it is. Eg 'http://mysite.com/image1-300x400.jpg' instead of
1454
-     * 'http://mysite.com/image1.jpg' ). This function attempts to strip that off and get the original file, if it
1455
-     * exists
1456
-     *
1457
-     * @param string $guid_in_old_event
1458
-     * @return string either the original guid, or $guid_in_old_event if we couldn't figure out what the original was
1459
-     */
1460
-    private function _get_original_guid($guid_in_old_event)
1461
-    {
1462
-        $original_guid = preg_replace('~-\d*x\d*\.~', '.', $guid_in_old_event, 1);
1463
-        //do a head request to verify the file exists
1464
-        $head_response = wp_remote_head($original_guid);
1465
-        if ( ! $head_response instanceof WP_Error && $head_response['response']['message'] == 'OK') {
1466
-            return $original_guid;
1467
-        } else {
1468
-            return $guid_in_old_event;
1469
-        }
1470
-    }
1471
-
1472
-
1473
-
1474
-    /**
1475
-     * Creates an image attachment post for the GUID. If the GUID points to a remote image,
1476
-     * we download it to our uploads directory so that it can be properly processed (eg, creates different sizes of
1477
-     * thumbnails)
1478
-     *
1479
-     * @param type                           $guid
1480
-     * @param EE_Data_Migration_Script_Stage $migration_stage
1481
-     * @return int
1482
-     */
1483
-    private function _create_image_attachment_from_GUID($guid, EE_Data_Migration_Script_Stage $migration_stage)
1484
-    {
1485
-        if ( ! $guid) {
1486
-            $migration_stage->add_error(sprintf(esc_html__("Cannot create image attachment for a blank GUID!",
1487
-                    "event_espresso")));
1488
-            return 0;
1489
-        }
1490
-        $wp_filetype = wp_check_filetype(basename($guid), null);
1491
-        $wp_upload_dir = wp_upload_dir();
1492
-        //if the file is located remotely, download it to our uploads DIR, because wp_genereate_attachmnet_metadata needs the file to be local
1493
-        if (strpos($guid, $wp_upload_dir['url']) === false) {
1494
-            //image is located remotely. download it and place it in the uploads directory
1495
-            if ( ! is_readable($guid)) {
1496
-                $migration_stage->add_error(sprintf(esc_html__("Could not create image attachment from non-existent file: %s",
1497
-                        "event_espresso"), $guid));
1498
-                return 0;
1499
-            }
1500
-            $contents = file_get_contents($guid);
1501
-            if ($contents === false) {
1502
-                $migration_stage->add_error(sprintf(esc_html__("Could not read image at %s, and therefore couldnt create an attachment post for it.",
1503
-                        "event_espresso"), $guid));
1504
-                return false;
1505
-            }
1506
-            $local_filepath = $wp_upload_dir['path'] . DS . basename($guid);
1507
-            $savefile = fopen($local_filepath, 'w');
1508
-            fwrite($savefile, $contents);
1509
-            fclose($savefile);
1510
-            $guid = str_replace($wp_upload_dir['path'], $wp_upload_dir['url'], $local_filepath);
1511
-        } else {
1512
-            $local_filepath = str_replace($wp_upload_dir['url'], $wp_upload_dir['path'], $guid);
1513
-        }
1514
-        $attachment = array(
1515
-                'guid'           => $guid,
1516
-                'post_mime_type' => $wp_filetype['type'],
1517
-                'post_title'     => preg_replace('/\.[^.]+$/', '', basename($guid)),
1518
-                'post_content'   => '',
1519
-                'post_status'    => 'inherit',
1520
-        );
1521
-        $attach_id = wp_insert_attachment($attachment, $guid);
1522
-        if ( ! $attach_id) {
1523
-            $migration_stage->add_error(sprintf(esc_html__("Could not create image attachment post from image '%s'. Attachment data was %s.",
1524
-                    "event_espresso"), $guid, $this->_json_encode($attachment)));
1525
-            return $attach_id;
1526
-        }
1527
-        // you must first include the image.php file
1528
-        // for the function wp_generate_attachment_metadata() to work
1529
-        require_once(ABSPATH . 'wp-admin/includes/image.php');
1530
-        $attach_data = wp_generate_attachment_metadata($attach_id, $local_filepath);
1531
-        if ( ! $attach_data) {
1532
-            $migration_stage->add_error(sprintf(esc_html__("Coudl not genereate attachment metadata for attachment post %d with filepath %s and GUID %s. Please check the file was downloaded properly.",
1533
-                    "event_espresso"), $attach_id, $local_filepath, $guid));
1534
-            return $attach_id;
1535
-        }
1536
-        $metadata_save_result = wp_update_attachment_metadata($attach_id, $attach_data);
1537
-        if ( ! $metadata_save_result) {
1538
-            $migration_stage->add_error(sprintf(esc_html__("Could not update attachment metadata for attachment %d with data %s",
1539
-                    "event_espresso"), $attach_id, $this->_json_encode($attach_data)));
1540
-        }
1541
-        return $attach_id;
1542
-    }
1543
-
1544
-
1545
-
1546
-    /**
1547
-     * Finds the attachment post containing info about an image attachment given the GUID (link to the image itself),
1548
-     * and returns its ID.
1549
-     *
1550
-     * @global type  $wpdb
1551
-     * @param string $guid
1552
-     * @return int
1553
-     */
1554
-    private function _get_image_attachment_id_by_GUID($guid)
1555
-    {
1556
-        global $wpdb;
1557
-        $attachment_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid=%s LIMIT 1", $guid));
1558
-        return $attachment_id;
1559
-    }
1560
-
1561
-
1562
-
1563
-    /**
1564
-     * Returns a mysql-formatted DATETIME in UTC time, given a $DATETIME_string
1565
-     * (and optionally a timezone; if none is given, the wp DEFAULT is used)
1566
-     *
1567
-     * @param EE_Data_Migration_Script_base $stage
1568
-     * @param array                         $row_of_data , the row from the DB (as an array) we're trying to find the
1569
-     *                                                   UTC time for
1570
-     * @param string                        $DATETIME_string
1571
-     * @param string                        $timezone
1572
-     * @return string
1573
-     */
1574
-    public function convert_date_string_to_utc(
1575
-            EE_Data_Migration_Script_Stage $stage,
1576
-            $row_of_data,
1577
-            $DATETIME_string,
1578
-            $timezone = null
1579
-    ) {
1580
-        $original_tz = $timezone;
1581
-        if ( ! $timezone) {
1582
-            $timezone = $this->_get_wp_timezone();
1583
-        }
1584
-        if ( ! $timezone) {
1585
-            $stage->add_error(sprintf(esc_html__("Could not find timezone given %s for %s", "event_espresso"), $original_tz,
1586
-                    $row_of_data));
1587
-            $timezone = 'UTC';
1588
-        }
1589
-        try {
1590
-            $date_obj = new DateTime($DATETIME_string, new DateTimeZone($timezone));
1591
-            EEH_DTT_Helper::setTimezone($date_obj, new DateTimeZone('UTC'));
1592
-        } catch (Exception $e) {
1593
-            $stage->add_error(sprintf(esc_html__("Could not convert time string '%s' using timezone '%s' into a proper DATETIME. Using current time instead.",
1594
-                    "event_espresso"), $DATETIME_string, $timezone));
1595
-            $date_obj = new DateTime();
1596
-        }
1597
-        return $date_obj->format('Y-m-d H:i:s');
1598
-    }
1599
-
1600
-
1601
-
1602
-    /**
1603
-     * Gets the DEFAULT timezone string from wordpress (even if they set a gmt offset)
1604
-     *
1605
-     * @return string
1606
-     */
1607
-    private function _get_wp_timezone()
1608
-    {
1609
-        $timezone = empty($timezone) ? get_option('timezone_string') : $timezone;
1610
-        //if timezone is STILL empty then let's get the GMT offset and then set the timezone_string using our converter
1611
-        if (empty($timezone)) {
1612
-            //let's get a the WordPress UTC offset
1613
-            $offset = get_option('gmt_offset');
1614
-            $timezone = $this->timezone_convert_to_string_from_offset($offset);
1615
-        }
1616
-        return $timezone;
1617
-    }
1618
-
1619
-
1620
-
1621
-    /**
1622
-     * Gets the wordpress timezone string from a UTC offset
1623
-     *
1624
-     * @param int $offset
1625
-     * @return boolean
1626
-     */
1627
-    private function timezone_convert_to_string_from_offset($offset)
1628
-    {
1629
-        //shamelessly taken from bottom comment at http://ca1.php.net/manual/en/function.timezone-name-from-abbr.php because timezone_name_from_abbr() did NOT work as expected - its not reliable
1630
-        $offset *= 3600; // convert hour offset to seconds
1631
-        $abbrarray = timezone_abbreviations_list();
1632
-        foreach ($abbrarray as $abbr) {
1633
-            foreach ($abbr as $city) {
1634
-                if ($city['offset'] == $offset) {
1635
-                    return $city['timezone_id'];
1636
-                }
1637
-            }
1638
-        }
1639
-        return false;
1640
-    }
1641
-
1642
-
1643
-
1644
-    public function migration_page_hooks()
1645
-    {
1646
-        add_filter(
1647
-                'FHEE__ee_migration_page__header',
1648
-                array($this, '_migrate_page_hook_simplify_version_strings'),
1649
-                10,
1650
-                3
1651
-        );
1652
-        add_filter(
1653
-                'FHEE__ee_migration_page__p_after_header',
1654
-                array($this, '_migration_page_hook_simplify_next_db_state'),
1655
-                10,
1656
-                2
1657
-        );
1658
-        add_filter(
1659
-                'FHEE__ee_migration_page__option_1_main',
1660
-                array($this, '_migrate_page_hook_simplify_version_strings'),
1661
-                10,
1662
-                3
1663
-        );
1664
-        add_filter(
1665
-                'FHEE__ee_migration_page__option_1_button_text',
1666
-                array($this, '_migrate_page_hook_simplify_version_strings'),
1667
-                10,
1668
-                3
1669
-        );
1670
-        add_action(
1671
-                'AHEE__ee_migration_page__option_1_extra_details',
1672
-                array($this, '_migration_page_hook_option_1_extra_details'),
1673
-                10,
1674
-                3
1675
-        );
1676
-        add_filter(
1677
-                'FHEE__ee_migration_page__option_2_main',
1678
-                array($this, '_migrate_page_hook_simplify_version_strings'),
1679
-                10,
1680
-                4
1681
-        );
1682
-        add_filter(
1683
-                'FHEE__ee_migration_page__option_2_button_text',
1684
-                array($this, '_migration_page_hook_simplify_next_db_state'),
1685
-                10,
1686
-                2
1687
-        );
1688
-        add_filter(
1689
-                'FHEE__ee_migration_page__option_2_details',
1690
-                array($this, '_migration_page_hook_simplify_next_db_state'),
1691
-                10,
1692
-                2
1693
-        );
1694
-        add_action(
1695
-                'AHEE__ee_migration_page__after_migration_options_table',
1696
-                array($this, '_migration_page_hook_after_migration_options_table')
1697
-        );
1698
-        add_filter(
1699
-                'FHEE__ee_migration_page__done_migration_header',
1700
-                array($this, '_migration_page_hook_simplify_next_db_state'),
1701
-                10,
1702
-                2
1703
-        );
1704
-        add_filter(
1705
-                'FHEE__ee_migration_page__p_after_done_migration_header',
1706
-                array($this, '_migration_page_hook_simplify_next_db_state'),
1707
-                10,
1708
-                2
1709
-        );
1710
-        add_filter(
1711
-                'FHEE__ee_migration_page__migration_options_template',
1712
-                array($this,'use_migration_options_from_ee3_template')
1713
-        );
1714
-    }
1715
-
1716
-
1717
-
1718
-    public function _migrate_page_hook_simplify_version_strings(
1719
-            $old_content,
1720
-            $current_db_state,
1721
-            $next_db_state,
1722
-            $ultimate_db_state = null
1723
-    ) {
1724
-        return str_replace(array($current_db_state, $next_db_state, $ultimate_db_state),
1725
-                array(esc_html__('EE3', 'event_espresso'), esc_html__('EE4', 'event_espresso'), esc_html__("EE4", 'event_espresso')),
1726
-                $old_content);
1727
-    }
1728
-
1729
-
1730
-
1731
-    public function _migration_page_hook_simplify_next_db_state($old_content, $next_db_state)
1732
-    {
1733
-        return str_replace($next_db_state, esc_html__("EE4", 'event_espresso'), $old_content);
1734
-    }
1735
-
1736
-
1737
-
1738
-    public function _migration_page_hook_option_1_extra_details()
1739
-    {
1740
-        ?>
1063
+		if ( ! $state) {
1064
+			//insert a new one then
1065
+			$cols_n_values = array(
1066
+					'CNT_ISO'    => $country_iso,
1067
+					'STA_abbrev' => substr($state_name, 0, 6),
1068
+					'STA_name'   => $state_name,
1069
+					'STA_active' => true,
1070
+			);
1071
+			$data_types = array(
1072
+					'%s',//CNT_ISO
1073
+					'%s',//STA_abbrev
1074
+					'%s',//STA_name
1075
+					'%d',//STA_active
1076
+			);
1077
+			$success = $wpdb->insert($state_table, $cols_n_values, $data_types);
1078
+			if ( ! $success) {
1079
+				throw new EE_Error($this->_create_error_message_for_db_insertion('N/A',
1080
+						array('state' => $state_name, 'country_id' => $country_name), $state_table, $cols_n_values,
1081
+						$data_types));
1082
+			}
1083
+			$state = $cols_n_values;
1084
+			$state['STA_ID'] = $wpdb->insert_id;
1085
+		}
1086
+		return $state;
1087
+	}
1088
+
1089
+
1090
+
1091
+	/**
1092
+	 * Fixes times like "5:00 PM" into the expected 24-hour format "17:00".
1093
+	 * THis is actually just copied from the 3.1 JSON API because it needed to do the exact same thing
1094
+	 *
1095
+	 * @param type $timeString
1096
+	 * @return string in the php DATETIME format: "G:i" (24-hour format hour with leading zeros, a colon, and minutes
1097
+	 *                with leading zeros)
1098
+	 */
1099
+	public function convertTimeFromAMPM($timeString)
1100
+	{
1101
+		$matches = array();
1102
+		preg_match("~(\\d*):(\\d*)~", $timeString, $matches);
1103
+		if ( ! $matches || count($matches) < 3) {
1104
+			$hour = '00';
1105
+			$minutes = '00';
1106
+		} else {
1107
+			$hour = intval($matches[1]);
1108
+			$minutes = $matches[2];
1109
+		}
1110
+		if (strpos($timeString, 'PM') || strpos($timeString, 'pm')) {
1111
+			$hour = intval($hour) + 12;
1112
+		}
1113
+		$hour = str_pad("$hour", 2, '0', STR_PAD_LEFT);
1114
+		$minutes = str_pad("$minutes", 2, '0', STR_PAD_LEFT);
1115
+		return "$hour:$minutes";
1116
+	}
1117
+
1118
+
1119
+
1120
+	/**
1121
+	 * Gets the ISO3 fora country given its 3.1 country ID.
1122
+	 *
1123
+	 * @param int $country_id
1124
+	 * @return string the country's ISO3 code
1125
+	 */
1126
+	public function get_iso_from_3_1_country_id($country_id)
1127
+	{
1128
+		$old_countries = array(
1129
+				array(64, 'United States', 'US', 'USA', 1),
1130
+				array(15, 'Australia', 'AU', 'AUS', 1),
1131
+				array(39, 'Canada', 'CA', 'CAN', 1),
1132
+				array(171, 'United Kingdom', 'GB', 'GBR', 1),
1133
+				array(70, 'France', 'FR', 'FRA', 2),
1134
+				array(111, 'Italy', 'IT', 'ITA', 2),
1135
+				array(63, 'Spain', 'ES', 'ESP', 2),
1136
+				array(1, 'Afghanistan', 'AF', 'AFG', 1),
1137
+				array(2, 'Albania', 'AL', 'ALB', 1),
1138
+				array(3, 'Germany', 'DE', 'DEU', 2),
1139
+				array(198, 'Switzerland', 'CH', 'CHE', 1),
1140
+				array(87, 'Netherlands', 'NL', 'NLD', 2),
1141
+				array(197, 'Sweden', 'SE', 'SWE', 1),
1142
+				array(230, 'Akrotiri and Dhekelia', 'CY', 'CYP', 2),
1143
+				array(4, 'Andorra', 'AD', 'AND', 2),
1144
+				array(5, 'Angola', 'AO', 'AGO', 1),
1145
+				array(6, 'Anguilla', 'AI', 'AIA', 1),
1146
+				array(7, 'Antarctica', 'AQ', 'ATA', 1),
1147
+				array(8, 'Antigua and Barbuda', 'AG', 'ATG', 1),
1148
+				array(10, 'Saudi Arabia', 'SA', 'SAU', 1),
1149
+				array(11, 'Algeria', 'DZ', 'DZA', 1),
1150
+				array(12, 'Argentina', 'AR', 'ARG', 1),
1151
+				array(13, 'Armenia', 'AM', 'ARM', 1),
1152
+				array(14, 'Aruba', 'AW', 'ABW', 1),
1153
+				array(16, 'Austria', 'AT', 'AUT', 2),
1154
+				array(17, 'Azerbaijan', 'AZ', 'AZE', 1),
1155
+				array(18, 'Bahamas', 'BS', 'BHS', 1),
1156
+				array(19, 'Bahrain', 'BH', 'BHR', 1),
1157
+				array(20, 'Bangladesh', 'BD', 'BGD', 1),
1158
+				array(21, 'Barbados', 'BB', 'BRB', 1),
1159
+				array(22, 'Belgium ', 'BE', 'BEL', 2),
1160
+				array(23, 'Belize', 'BZ', 'BLZ', 1),
1161
+				array(24, 'Benin', 'BJ', 'BEN', 1),
1162
+				array(25, 'Bermudas', 'BM', 'BMU', 1),
1163
+				array(26, 'Belarus', 'BY', 'BLR', 1),
1164
+				array(27, 'Bolivia', 'BO', 'BOL', 1),
1165
+				array(28, 'Bosnia and Herzegovina', 'BA', 'BIH', 1),
1166
+				array(29, 'Botswana', 'BW', 'BWA', 1),
1167
+				array(96, 'Bouvet Island', 'BV', 'BVT', 1),
1168
+				array(30, 'Brazil', 'BR', 'BRA', 1),
1169
+				array(31, 'Brunei', 'BN', 'BRN', 1),
1170
+				array(32, 'Bulgaria', 'BG', 'BGR', 1),
1171
+				array(33, 'Burkina Faso', 'BF', 'BFA', 1),
1172
+				array(34, 'Burundi', 'BI', 'BDI', 1),
1173
+				array(35, 'Bhutan', 'BT', 'BTN', 1),
1174
+				array(36, 'Cape Verde', 'CV', 'CPV', 1),
1175
+				array(37, 'Cambodia', 'KH', 'KHM', 1),
1176
+				array(38, 'Cameroon', 'CM', 'CMR', 1),
1177
+				array(98, 'Cayman Islands', 'KY', 'CYM', 1),
1178
+				array(172, 'Central African Republic', 'CF', 'CAF', 1),
1179
+				array(40, 'Chad', 'TD', 'TCD', 1),
1180
+				array(41, 'Chile', 'CL', 'CHL', 1),
1181
+				array(42, 'China', 'CN', 'CHN', 1),
1182
+				array(105, 'Christmas Island', 'CX', 'CXR', 1),
1183
+				array(43, 'Cyprus', 'CY', 'CYP', 2),
1184
+				array(99, 'Cocos Island', 'CC', 'CCK', 1),
1185
+				array(100, 'Cook Islands', 'CK', 'COK', 1),
1186
+				array(44, 'Colombia', 'CO', 'COL', 1),
1187
+				array(45, 'Comoros', 'KM', 'COM', 1),
1188
+				array(46, 'Congo', 'CG', 'COG', 1),
1189
+				array(47, 'North Korea', 'KP', 'PRK', 1),
1190
+				array(50, 'Costa Rica', 'CR', 'CRI', 1),
1191
+				array(51, 'Croatia', 'HR', 'HRV', 1),
1192
+				array(52, 'Cuba', 'CU', 'CUB', 1),
1193
+				array(173, 'Czech Republic', 'CZ', 'CZE', 1),
1194
+				array(53, 'Denmark', 'DK', 'DNK', 1),
1195
+				array(54, 'Djibouti', 'DJ', 'DJI', 1),
1196
+				array(55, 'Dominica', 'DM', 'DMA', 1),
1197
+				array(174, 'Dominican Republic', 'DO', 'DOM', 1),
1198
+				array(56, 'Ecuador', 'EC', 'ECU', 1),
1199
+				array(57, 'Egypt', 'EG', 'EGY', 1),
1200
+				array(58, 'El Salvador', 'SV', 'SLV', 1),
1201
+				array(60, 'Eritrea', 'ER', 'ERI', 1),
1202
+				array(61, 'Slovakia', 'SK', 'SVK', 2),
1203
+				array(62, 'Slovenia', 'SI', 'SVN', 2),
1204
+				array(65, 'Estonia', 'EE', 'EST', 2),
1205
+				array(66, 'Ethiopia', 'ET', 'ETH', 1),
1206
+				array(102, 'Faroe islands', 'FO', 'FRO', 1),
1207
+				array(103, 'Falkland Islands', 'FK', 'FLK', 1),
1208
+				array(67, 'Fiji', 'FJ', 'FJI', 1),
1209
+				array(69, 'Finland', 'FI', 'FIN', 2),
1210
+				array(71, 'Gabon', 'GA', 'GAB', 1),
1211
+				array(72, 'Gambia', 'GM', 'GMB', 1),
1212
+				array(73, 'Georgia', 'GE', 'GEO', 1),
1213
+				array(74, 'Ghana', 'GH', 'GHA', 1),
1214
+				array(75, 'Gibraltar', 'GI', 'GIB', 1),
1215
+				array(76, 'Greece', 'GR', 'GRC', 2),
1216
+				array(77, 'Grenada', 'GD', 'GRD', 1),
1217
+				array(78, 'Greenland', 'GL', 'GRL', 1),
1218
+				array(79, 'Guadeloupe', 'GP', 'GLP', 1),
1219
+				array(80, 'Guam', 'GU', 'GUM', 1),
1220
+				array(81, 'Guatemala', 'GT', 'GTM', 1),
1221
+				array(82, 'Guinea', 'GN', 'GIN', 1),
1222
+				array(83, 'Equatorial Guinea', 'GQ', 'GNQ', 1),
1223
+				array(84, 'Guinea-Bissau', 'GW', 'GNB', 1),
1224
+				array(85, 'Guyana', 'GY', 'GUY', 1),
1225
+				array(86, 'Haiti', 'HT', 'HTI', 1),
1226
+				array(88, 'Honduras', 'HN', 'HND', 1),
1227
+				array(89, 'Hong Kong', 'HK', 'HKG', 1),
1228
+				array(90, 'Hungary', 'HU', 'HUN', 1),
1229
+				array(91, 'India', 'IN', 'IND', 1),
1230
+				array(205, 'British Indian Ocean Territory', 'IO', 'IOT', 1),
1231
+				array(92, 'Indonesia', 'ID', 'IDN', 1),
1232
+				array(93, 'Iraq', 'IQ', 'IRQ', 1),
1233
+				array(94, 'Iran', 'IR', 'IRN', 1),
1234
+				array(95, 'Ireland', 'IE', 'IRL', 2),
1235
+				array(97, 'Iceland', 'IS', 'ISL', 1),
1236
+				array(110, 'Israel', 'IL', 'ISR', 1),
1237
+				array(49, 'Ivory Coast ', 'CI', 'CIV', 1),
1238
+				array(112, 'Jamaica', 'JM', 'JAM', 1),
1239
+				array(113, 'Japan', 'JP', 'JPN', 1),
1240
+				array(114, 'Jordan', 'JO', 'JOR', 1),
1241
+				array(115, 'Kazakhstan', 'KZ', 'KAZ', 1),
1242
+				array(116, 'Kenya', 'KE', 'KEN', 1),
1243
+				array(117, 'Kyrgyzstan', 'KG', 'KGZ', 1),
1244
+				array(118, 'Kiribati', 'KI', 'KIR', 1),
1245
+				array(48, 'South Korea', 'KR', 'KOR', 1),
1246
+				array(228, 'Kosovo', 'XK', 'XKV', 2),
1247
+				// there is no official ISO code for Kosovo yet (http://geonames.wordpress.com/2010/03/08/xk-country-code-for-kosovo/) so using a temporary country code and a modified 3 character code for ISO code -- this should be updated if/when Kosovo gets its own ISO code
1248
+				array(119, 'Kuwait', 'KW', 'KWT', 1),
1249
+				array(120, 'Laos', 'LA', 'LAO', 1),
1250
+				array(121, 'Latvia', 'LV', 'LVA', 2),
1251
+				array(122, 'Lesotho', 'LS', 'LSO', 1),
1252
+				array(123, 'Lebanon', 'LB', 'LBN', 1),
1253
+				array(124, 'Liberia', 'LR', 'LBR', 1),
1254
+				array(125, 'Libya', 'LY', 'LBY', 1),
1255
+				array(126, 'Liechtenstein', 'LI', 'LIE', 1),
1256
+				array(127, 'Lithuania', 'LT', 'LTU', 2),
1257
+				array(128, 'Luxemburg', 'LU', 'LUX', 2),
1258
+				array(129, 'Macao', 'MO', 'MAC', 1),
1259
+				array(130, 'Macedonia', 'MK', 'MKD', 1),
1260
+				array(131, 'Madagascar', 'MG', 'MDG', 1),
1261
+				array(132, 'Malaysia', 'MY', 'MYS', 1),
1262
+				array(133, 'Malawi', 'MW', 'MWI', 1),
1263
+				array(134, 'Maldivas', 'MV', 'MDV', 1),
1264
+				array(135, 'Mali', 'ML', 'MLI', 1),
1265
+				array(136, 'Malta', 'MT', 'MLT', 2),
1266
+				array(101, 'Northern Marianas', 'MP', 'MNP', 1),
1267
+				array(137, 'Morocco', 'MA', 'MAR', 1),
1268
+				array(104, 'Marshall islands', 'MH', 'MHL', 1),
1269
+				array(138, 'Martinique', 'MQ', 'MTQ', 1),
1270
+				array(139, 'Mauritius', 'MU', 'MUS', 1),
1271
+				array(140, 'Mauritania', 'MR', 'MRT', 1),
1272
+				array(141, 'Mayote', 'YT', 'MYT', 2),
1273
+				array(142, 'Mexico', 'MX', 'MEX', 1),
1274
+				array(143, 'Micronesia', 'FM', 'FSM', 1),
1275
+				array(144, 'Moldova', 'MD', 'MDA', 1),
1276
+				array(145, 'Monaco', 'MC', 'MCO', 2),
1277
+				array(146, 'Mongolia', 'MN', 'MNG', 1),
1278
+				array(147, 'Montserrat', 'MS', 'MSR', 1),
1279
+				array(227, 'Montenegro', 'ME', 'MNE', 2),
1280
+				array(148, 'Mozambique', 'MZ', 'MOZ', 1),
1281
+				array(149, 'Myanmar', 'MM', 'MMR', 1),
1282
+				array(150, 'Namibia', 'NA', 'NAM', 1),
1283
+				array(151, 'Nauru', 'NR', 'NRU', 1),
1284
+				array(152, 'Nepal', 'NP', 'NPL', 1),
1285
+				array(9, 'Netherlands Antilles', 'AN', 'ANT', 1),
1286
+				array(153, 'Nicaragua', 'NI', 'NIC', 1),
1287
+				array(154, 'Niger', 'NE', 'NER', 1),
1288
+				array(155, 'Nigeria', 'NG', 'NGA', 1),
1289
+				array(156, 'Niue', 'NU', 'NIU', 1),
1290
+				array(157, 'Norway', 'NO', 'NOR', 1),
1291
+				array(158, 'New Caledonia', 'NC', 'NCL', 1),
1292
+				array(159, 'New Zealand', 'NZ', 'NZL', 1),
1293
+				array(160, 'Oman', 'OM', 'OMN', 1),
1294
+				array(161, 'Pakistan', 'PK', 'PAK', 1),
1295
+				array(162, 'Palau', 'PW', 'PLW', 1),
1296
+				array(163, 'Panama', 'PA', 'PAN', 1),
1297
+				array(164, 'Papua New Guinea', 'PG', 'PNG', 1),
1298
+				array(165, 'Paraguay', 'PY', 'PRY', 1),
1299
+				array(166, 'Peru', 'PE', 'PER', 1),
1300
+				array(68, 'Philippines', 'PH', 'PHL', 1),
1301
+				array(167, 'Poland', 'PL', 'POL', 1),
1302
+				array(168, 'Portugal', 'PT', 'PRT', 2),
1303
+				array(169, 'Puerto Rico', 'PR', 'PRI', 1),
1304
+				array(170, 'Qatar', 'QA', 'QAT', 1),
1305
+				array(176, 'Rwanda', 'RW', 'RWA', 1),
1306
+				array(177, 'Romania', 'RO', 'ROM', 2),
1307
+				array(178, 'Russia', 'RU', 'RUS', 1),
1308
+				array(229, 'Saint Pierre and Miquelon', 'PM', 'SPM', 2),
1309
+				array(180, 'Samoa', 'WS', 'WSM', 1),
1310
+				array(181, 'American Samoa', 'AS', 'ASM', 1),
1311
+				array(183, 'San Marino', 'SM', 'SMR', 2),
1312
+				array(184, 'Saint Vincent and the Grenadines', 'VC', 'VCT', 1),
1313
+				array(185, 'Saint Helena', 'SH', 'SHN', 1),
1314
+				array(186, 'Saint Lucia', 'LC', 'LCA', 1),
1315
+				array(188, 'Senegal', 'SN', 'SEN', 1),
1316
+				array(189, 'Seychelles', 'SC', 'SYC', 1),
1317
+				array(190, 'Sierra Leona', 'SL', 'SLE', 1),
1318
+				array(191, 'Singapore', 'SG', 'SGP', 1),
1319
+				array(192, 'Syria', 'SY', 'SYR', 1),
1320
+				array(193, 'Somalia', 'SO', 'SOM', 1),
1321
+				array(194, 'Sri Lanka', 'LK', 'LKA', 1),
1322
+				array(195, 'South Africa', 'ZA', 'ZAF', 1),
1323
+				array(196, 'Sudan', 'SD', 'SDN', 1),
1324
+				array(199, 'Suriname', 'SR', 'SUR', 1),
1325
+				array(200, 'Swaziland', 'SZ', 'SWZ', 1),
1326
+				array(201, 'Thailand', 'TH', 'THA', 1),
1327
+				array(202, 'Taiwan', 'TW', 'TWN', 1),
1328
+				array(203, 'Tanzania', 'TZ', 'TZA', 1),
1329
+				array(204, 'Tajikistan', 'TJ', 'TJK', 1),
1330
+				array(206, 'Timor-Leste', 'TL', 'TLS', 1),
1331
+				array(207, 'Togo', 'TG', 'TGO', 1),
1332
+				array(208, 'Tokelau', 'TK', 'TKL', 1),
1333
+				array(209, 'Tonga', 'TO', 'TON', 1),
1334
+				array(210, 'Trinidad and Tobago', 'TT', 'TTO', 1),
1335
+				array(211, 'Tunisia', 'TN', 'TUN', 1),
1336
+				array(212, 'Turkmenistan', 'TM', 'TKM', 1),
1337
+				array(213, 'Turkey', 'TR', 'TUR', 1),
1338
+				array(214, 'Tuvalu', 'TV', 'TUV', 1),
1339
+				array(215, 'Ukraine', 'UA', 'UKR', 1),
1340
+				array(216, 'Uganda', 'UG', 'UGA', 1),
1341
+				array(59, 'United Arab Emirates', 'AE', 'ARE', 1),
1342
+				array(217, 'Uruguay', 'UY', 'URY', 1),
1343
+				array(218, 'Uzbekistan', 'UZ', 'UZB', 1),
1344
+				array(219, 'Vanuatu', 'VU', 'VUT', 1),
1345
+				array(220, 'Vatican City', 'VA', 'VAT', 2),
1346
+				array(221, 'Venezuela', 'VE', 'VEN', 1),
1347
+				array(222, 'Vietnam', 'VN', 'VNM', 1),
1348
+				array(108, 'Virgin Islands', 'VI', 'VIR', 1),
1349
+				array(223, 'Yemen', 'YE', 'YEM', 1),
1350
+				array(225, 'Zambia', 'ZM', 'ZMB', 1),
1351
+				array(226, 'Zimbabwe', 'ZW', 'ZWE', 1),
1352
+		);
1353
+		$country_iso = 'US';
1354
+		foreach ($old_countries as $country_array) {
1355
+			//note: index 0 is the 3.1 country ID
1356
+			if ($country_array[0] == $country_id) {
1357
+				//note: index 2 is the ISO
1358
+				$country_iso = $country_array[2];
1359
+				break;
1360
+			}
1361
+		}
1362
+		return $country_iso;
1363
+	}
1364
+
1365
+
1366
+
1367
+	/**
1368
+	 * Gets the ISO3 for the
1369
+	 *
1370
+	 * @return string
1371
+	 */
1372
+	public function get_default_country_iso()
1373
+	{
1374
+		$old_org_options = get_option('events_organization_settings');
1375
+		$iso = $this->get_iso_from_3_1_country_id($old_org_options['organization_country']);
1376
+		return $iso;
1377
+	}
1378
+
1379
+
1380
+
1381
+	/**
1382
+	 * Converst a 3.1 payment status to its equivalent 4.1 regisration status
1383
+	 *
1384
+	 * @param string  $payment_status                   possible value for 3.1's evens_attendee.payment_status
1385
+	 * @param boolean $this_thing_required_pre_approval whether the thing we're considering (the general setting's
1386
+	 *                                                  DEFAULT payment status, the event's DEFAULT payment status, or
1387
+	 *                                                  the attendee's payment status) required pre-approval.
1388
+	 * @return string STS_ID for use in 4.1
1389
+	 */
1390
+	public function convert_3_1_payment_status_to_4_1_STS_ID($payment_status, $this_thing_required_pre_approval = false)
1391
+	{
1392
+		//EE team can read the related discussion: https://app.asana.com/0/2400967562914/9418495544455
1393
+		if ($this_thing_required_pre_approval) {
1394
+			return 'RNA';
1395
+		} else {
1396
+			$mapping = $default_reg_stati_conversions = array(
1397
+					'Completed'        => 'RAP',
1398
+					''                 => 'RPP',
1399
+					'Incomplete'       => 'RPP',
1400
+					'Pending'          => 'RAP',
1401
+					//stati that only occurred on 3.1 attendees:
1402
+					'Payment Declined' => 'RPP',
1403
+					'Not Completed'    => 'RPP',
1404
+					'Cancelled'        => 'RPP',
1405
+					'Declined'         => 'RPP',
1406
+			);
1407
+		}
1408
+		return isset($mapping[$payment_status]) ? $mapping[$payment_status] : 'RNA';
1409
+	}
1410
+
1411
+
1412
+
1413
+	/**
1414
+	 * Makes sure the 3.1's image url is converted to an image attachment post to the 4.1 CPT event
1415
+	 * and sets it as the featured image on the CPT event
1416
+	 *
1417
+	 * @param type                            $old_event
1418
+	 * @param type                            $new_cpt_id
1419
+	 * @param  EE_Data_Migration_Script_Stage $migration_stage the stage which called this, where errors should be added
1420
+	 * @return boolean whether or not we had to do the big job of creating an image attachment
1421
+	 */
1422
+	public function convert_image_url_to_attachment_and_attach_to_post(
1423
+			$guid,
1424
+			$new_cpt_id,
1425
+			EE_Data_Migration_Script_Stage $migration_stage
1426
+	) {
1427
+		$created_attachment_post = false;
1428
+		$guid = $this->_get_original_guid($guid);
1429
+		if ($guid) {
1430
+			//check for an existing attachment post with this guid
1431
+			$attachment_post_id = $this->_get_image_attachment_id_by_GUID($guid);
1432
+			if ( ! $attachment_post_id) {
1433
+				//post thumbnail with that GUID doesn't exist, we should create one
1434
+				$attachment_post_id = $this->_create_image_attachment_from_GUID($guid, $migration_stage);
1435
+				$created_attachment_post = true;
1436
+			}
1437
+			//double-check we actually have an attachment post
1438
+			if ($attachment_post_id) {
1439
+				update_post_meta($new_cpt_id, '_thumbnail_id', $attachment_post_id);
1440
+			} else {
1441
+				$migration_stage->add_error(sprintf(esc_html__("Could not update event image %s for CPT with ID %d, but attachments post ID is %d",
1442
+						"event_espresso"), $guid, $new_cpt_id, $attachment_post_id));
1443
+			}
1444
+		}
1445
+		return $created_attachment_post;
1446
+	}
1447
+
1448
+
1449
+
1450
+	/**
1451
+	 * In 3.1, the event thumbnail image DOESN'T point to the orignal image, but instead
1452
+	 * to a large thumbnail (which has nearly the same GUID, except it adds "-{width}x{height}" before the filetype,
1453
+	 * or whatever dimensions it is. Eg 'http://mysite.com/image1-300x400.jpg' instead of
1454
+	 * 'http://mysite.com/image1.jpg' ). This function attempts to strip that off and get the original file, if it
1455
+	 * exists
1456
+	 *
1457
+	 * @param string $guid_in_old_event
1458
+	 * @return string either the original guid, or $guid_in_old_event if we couldn't figure out what the original was
1459
+	 */
1460
+	private function _get_original_guid($guid_in_old_event)
1461
+	{
1462
+		$original_guid = preg_replace('~-\d*x\d*\.~', '.', $guid_in_old_event, 1);
1463
+		//do a head request to verify the file exists
1464
+		$head_response = wp_remote_head($original_guid);
1465
+		if ( ! $head_response instanceof WP_Error && $head_response['response']['message'] == 'OK') {
1466
+			return $original_guid;
1467
+		} else {
1468
+			return $guid_in_old_event;
1469
+		}
1470
+	}
1471
+
1472
+
1473
+
1474
+	/**
1475
+	 * Creates an image attachment post for the GUID. If the GUID points to a remote image,
1476
+	 * we download it to our uploads directory so that it can be properly processed (eg, creates different sizes of
1477
+	 * thumbnails)
1478
+	 *
1479
+	 * @param type                           $guid
1480
+	 * @param EE_Data_Migration_Script_Stage $migration_stage
1481
+	 * @return int
1482
+	 */
1483
+	private function _create_image_attachment_from_GUID($guid, EE_Data_Migration_Script_Stage $migration_stage)
1484
+	{
1485
+		if ( ! $guid) {
1486
+			$migration_stage->add_error(sprintf(esc_html__("Cannot create image attachment for a blank GUID!",
1487
+					"event_espresso")));
1488
+			return 0;
1489
+		}
1490
+		$wp_filetype = wp_check_filetype(basename($guid), null);
1491
+		$wp_upload_dir = wp_upload_dir();
1492
+		//if the file is located remotely, download it to our uploads DIR, because wp_genereate_attachmnet_metadata needs the file to be local
1493
+		if (strpos($guid, $wp_upload_dir['url']) === false) {
1494
+			//image is located remotely. download it and place it in the uploads directory
1495
+			if ( ! is_readable($guid)) {
1496
+				$migration_stage->add_error(sprintf(esc_html__("Could not create image attachment from non-existent file: %s",
1497
+						"event_espresso"), $guid));
1498
+				return 0;
1499
+			}
1500
+			$contents = file_get_contents($guid);
1501
+			if ($contents === false) {
1502
+				$migration_stage->add_error(sprintf(esc_html__("Could not read image at %s, and therefore couldnt create an attachment post for it.",
1503
+						"event_espresso"), $guid));
1504
+				return false;
1505
+			}
1506
+			$local_filepath = $wp_upload_dir['path'] . DS . basename($guid);
1507
+			$savefile = fopen($local_filepath, 'w');
1508
+			fwrite($savefile, $contents);
1509
+			fclose($savefile);
1510
+			$guid = str_replace($wp_upload_dir['path'], $wp_upload_dir['url'], $local_filepath);
1511
+		} else {
1512
+			$local_filepath = str_replace($wp_upload_dir['url'], $wp_upload_dir['path'], $guid);
1513
+		}
1514
+		$attachment = array(
1515
+				'guid'           => $guid,
1516
+				'post_mime_type' => $wp_filetype['type'],
1517
+				'post_title'     => preg_replace('/\.[^.]+$/', '', basename($guid)),
1518
+				'post_content'   => '',
1519
+				'post_status'    => 'inherit',
1520
+		);
1521
+		$attach_id = wp_insert_attachment($attachment, $guid);
1522
+		if ( ! $attach_id) {
1523
+			$migration_stage->add_error(sprintf(esc_html__("Could not create image attachment post from image '%s'. Attachment data was %s.",
1524
+					"event_espresso"), $guid, $this->_json_encode($attachment)));
1525
+			return $attach_id;
1526
+		}
1527
+		// you must first include the image.php file
1528
+		// for the function wp_generate_attachment_metadata() to work
1529
+		require_once(ABSPATH . 'wp-admin/includes/image.php');
1530
+		$attach_data = wp_generate_attachment_metadata($attach_id, $local_filepath);
1531
+		if ( ! $attach_data) {
1532
+			$migration_stage->add_error(sprintf(esc_html__("Coudl not genereate attachment metadata for attachment post %d with filepath %s and GUID %s. Please check the file was downloaded properly.",
1533
+					"event_espresso"), $attach_id, $local_filepath, $guid));
1534
+			return $attach_id;
1535
+		}
1536
+		$metadata_save_result = wp_update_attachment_metadata($attach_id, $attach_data);
1537
+		if ( ! $metadata_save_result) {
1538
+			$migration_stage->add_error(sprintf(esc_html__("Could not update attachment metadata for attachment %d with data %s",
1539
+					"event_espresso"), $attach_id, $this->_json_encode($attach_data)));
1540
+		}
1541
+		return $attach_id;
1542
+	}
1543
+
1544
+
1545
+
1546
+	/**
1547
+	 * Finds the attachment post containing info about an image attachment given the GUID (link to the image itself),
1548
+	 * and returns its ID.
1549
+	 *
1550
+	 * @global type  $wpdb
1551
+	 * @param string $guid
1552
+	 * @return int
1553
+	 */
1554
+	private function _get_image_attachment_id_by_GUID($guid)
1555
+	{
1556
+		global $wpdb;
1557
+		$attachment_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid=%s LIMIT 1", $guid));
1558
+		return $attachment_id;
1559
+	}
1560
+
1561
+
1562
+
1563
+	/**
1564
+	 * Returns a mysql-formatted DATETIME in UTC time, given a $DATETIME_string
1565
+	 * (and optionally a timezone; if none is given, the wp DEFAULT is used)
1566
+	 *
1567
+	 * @param EE_Data_Migration_Script_base $stage
1568
+	 * @param array                         $row_of_data , the row from the DB (as an array) we're trying to find the
1569
+	 *                                                   UTC time for
1570
+	 * @param string                        $DATETIME_string
1571
+	 * @param string                        $timezone
1572
+	 * @return string
1573
+	 */
1574
+	public function convert_date_string_to_utc(
1575
+			EE_Data_Migration_Script_Stage $stage,
1576
+			$row_of_data,
1577
+			$DATETIME_string,
1578
+			$timezone = null
1579
+	) {
1580
+		$original_tz = $timezone;
1581
+		if ( ! $timezone) {
1582
+			$timezone = $this->_get_wp_timezone();
1583
+		}
1584
+		if ( ! $timezone) {
1585
+			$stage->add_error(sprintf(esc_html__("Could not find timezone given %s for %s", "event_espresso"), $original_tz,
1586
+					$row_of_data));
1587
+			$timezone = 'UTC';
1588
+		}
1589
+		try {
1590
+			$date_obj = new DateTime($DATETIME_string, new DateTimeZone($timezone));
1591
+			EEH_DTT_Helper::setTimezone($date_obj, new DateTimeZone('UTC'));
1592
+		} catch (Exception $e) {
1593
+			$stage->add_error(sprintf(esc_html__("Could not convert time string '%s' using timezone '%s' into a proper DATETIME. Using current time instead.",
1594
+					"event_espresso"), $DATETIME_string, $timezone));
1595
+			$date_obj = new DateTime();
1596
+		}
1597
+		return $date_obj->format('Y-m-d H:i:s');
1598
+	}
1599
+
1600
+
1601
+
1602
+	/**
1603
+	 * Gets the DEFAULT timezone string from wordpress (even if they set a gmt offset)
1604
+	 *
1605
+	 * @return string
1606
+	 */
1607
+	private function _get_wp_timezone()
1608
+	{
1609
+		$timezone = empty($timezone) ? get_option('timezone_string') : $timezone;
1610
+		//if timezone is STILL empty then let's get the GMT offset and then set the timezone_string using our converter
1611
+		if (empty($timezone)) {
1612
+			//let's get a the WordPress UTC offset
1613
+			$offset = get_option('gmt_offset');
1614
+			$timezone = $this->timezone_convert_to_string_from_offset($offset);
1615
+		}
1616
+		return $timezone;
1617
+	}
1618
+
1619
+
1620
+
1621
+	/**
1622
+	 * Gets the wordpress timezone string from a UTC offset
1623
+	 *
1624
+	 * @param int $offset
1625
+	 * @return boolean
1626
+	 */
1627
+	private function timezone_convert_to_string_from_offset($offset)
1628
+	{
1629
+		//shamelessly taken from bottom comment at http://ca1.php.net/manual/en/function.timezone-name-from-abbr.php because timezone_name_from_abbr() did NOT work as expected - its not reliable
1630
+		$offset *= 3600; // convert hour offset to seconds
1631
+		$abbrarray = timezone_abbreviations_list();
1632
+		foreach ($abbrarray as $abbr) {
1633
+			foreach ($abbr as $city) {
1634
+				if ($city['offset'] == $offset) {
1635
+					return $city['timezone_id'];
1636
+				}
1637
+			}
1638
+		}
1639
+		return false;
1640
+	}
1641
+
1642
+
1643
+
1644
+	public function migration_page_hooks()
1645
+	{
1646
+		add_filter(
1647
+				'FHEE__ee_migration_page__header',
1648
+				array($this, '_migrate_page_hook_simplify_version_strings'),
1649
+				10,
1650
+				3
1651
+		);
1652
+		add_filter(
1653
+				'FHEE__ee_migration_page__p_after_header',
1654
+				array($this, '_migration_page_hook_simplify_next_db_state'),
1655
+				10,
1656
+				2
1657
+		);
1658
+		add_filter(
1659
+				'FHEE__ee_migration_page__option_1_main',
1660
+				array($this, '_migrate_page_hook_simplify_version_strings'),
1661
+				10,
1662
+				3
1663
+		);
1664
+		add_filter(
1665
+				'FHEE__ee_migration_page__option_1_button_text',
1666
+				array($this, '_migrate_page_hook_simplify_version_strings'),
1667
+				10,
1668
+				3
1669
+		);
1670
+		add_action(
1671
+				'AHEE__ee_migration_page__option_1_extra_details',
1672
+				array($this, '_migration_page_hook_option_1_extra_details'),
1673
+				10,
1674
+				3
1675
+		);
1676
+		add_filter(
1677
+				'FHEE__ee_migration_page__option_2_main',
1678
+				array($this, '_migrate_page_hook_simplify_version_strings'),
1679
+				10,
1680
+				4
1681
+		);
1682
+		add_filter(
1683
+				'FHEE__ee_migration_page__option_2_button_text',
1684
+				array($this, '_migration_page_hook_simplify_next_db_state'),
1685
+				10,
1686
+				2
1687
+		);
1688
+		add_filter(
1689
+				'FHEE__ee_migration_page__option_2_details',
1690
+				array($this, '_migration_page_hook_simplify_next_db_state'),
1691
+				10,
1692
+				2
1693
+		);
1694
+		add_action(
1695
+				'AHEE__ee_migration_page__after_migration_options_table',
1696
+				array($this, '_migration_page_hook_after_migration_options_table')
1697
+		);
1698
+		add_filter(
1699
+				'FHEE__ee_migration_page__done_migration_header',
1700
+				array($this, '_migration_page_hook_simplify_next_db_state'),
1701
+				10,
1702
+				2
1703
+		);
1704
+		add_filter(
1705
+				'FHEE__ee_migration_page__p_after_done_migration_header',
1706
+				array($this, '_migration_page_hook_simplify_next_db_state'),
1707
+				10,
1708
+				2
1709
+		);
1710
+		add_filter(
1711
+				'FHEE__ee_migration_page__migration_options_template',
1712
+				array($this,'use_migration_options_from_ee3_template')
1713
+		);
1714
+	}
1715
+
1716
+
1717
+
1718
+	public function _migrate_page_hook_simplify_version_strings(
1719
+			$old_content,
1720
+			$current_db_state,
1721
+			$next_db_state,
1722
+			$ultimate_db_state = null
1723
+	) {
1724
+		return str_replace(array($current_db_state, $next_db_state, $ultimate_db_state),
1725
+				array(esc_html__('EE3', 'event_espresso'), esc_html__('EE4', 'event_espresso'), esc_html__("EE4", 'event_espresso')),
1726
+				$old_content);
1727
+	}
1728
+
1729
+
1730
+
1731
+	public function _migration_page_hook_simplify_next_db_state($old_content, $next_db_state)
1732
+	{
1733
+		return str_replace($next_db_state, esc_html__("EE4", 'event_espresso'), $old_content);
1734
+	}
1735
+
1736
+
1737
+
1738
+	public function _migration_page_hook_option_1_extra_details()
1739
+	{
1740
+		?>
1741 1741
         <p><?php printf(esc_html__("Note: many of your EE3 shortcodes will be changed to EE4 shortcodes during this migration (among many other things). Should you revert to EE3, then you should restore to your backup or manually change the EE4 shortcodes back to their EE3 equivalents",
1742
-            "event_espresso")); ?></p><?php
1743
-    }
1742
+			"event_espresso")); ?></p><?php
1743
+	}
1744 1744
 
1745 1745
 
1746 1746
 
1747
-    public function _migration_page_hook_after_migration_options_table()
1748
-    {
1749
-        ?><p class="ee-attention">
1747
+	public function _migration_page_hook_after_migration_options_table()
1748
+	{
1749
+		?><p class="ee-attention">
1750 1750
         <strong><span class="reminder-spn"><?php _e("Important note to those using Event Espresso 3 addons: ",
1751
-                        "event_espresso"); ?></span></strong>
1751
+						"event_espresso"); ?></span></strong>
1752 1752
         <br/><?php _e("Unless an addon's description on our website explicitly states that it is compatible with EE4, you should consider it incompatible and know that it WILL NOT WORK correctly with this new version of Event Espresso 4 (EE4). As well, any data for incompatible addons will NOT BE MIGRATED until an updated EE4 compatible version of the addon is available. If you want, or need to keep using your EE3 addons, you should simply continue using EE3 until EE4 compatible versions of your addons become available. To continue using EE3 for now, just deactivate EE4 and reactivate EE3.",
1753
-            "event_espresso"); ?>
1753
+			"event_espresso"); ?>
1754 1754
         </p><?php
1755
-    }
1755
+	}
1756 1756
 
1757 1757
 
1758 1758
 
1759
-    /**
1760
-     * When showing the migration options, show more options and info than normal (ie, give folks the option
1761
-     * to start using EE4 without migrating. From EE3 that's fine, because it doesn't actually remove any data, because
1762
-     * EE4 doesn't have any yet. But when migrating from EE4 it would remove old data, so its not a great idea).
1763
-     * @param $template_filepath
1764
-     * @return string
1765
-     */
1766
-    public function use_migration_options_from_ee3_template( $template_filepath ) {
1767
-        return EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee3.template.php';
1768
-    }
1759
+	/**
1760
+	 * When showing the migration options, show more options and info than normal (ie, give folks the option
1761
+	 * to start using EE4 without migrating. From EE3 that's fine, because it doesn't actually remove any data, because
1762
+	 * EE4 doesn't have any yet. But when migrating from EE4 it would remove old data, so its not a great idea).
1763
+	 * @param $template_filepath
1764
+	 * @return string
1765
+	 */
1766
+	public function use_migration_options_from_ee3_template( $template_filepath ) {
1767
+		return EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee3.template.php';
1768
+	}
1769 1769
 }
Please login to merge, or discard this patch.
core/helpers/EEH_DTT_Helper.helper.php 1 patch
Indentation   +1027 added lines, -1027 removed lines patch added patch discarded remove patch
@@ -21,1031 +21,1031 @@
 block discarded – undo
21 21
 {
22 22
 
23 23
 
24
-    /**
25
-     * return the timezone set for the WP install
26
-     *
27
-     * @return string valid timezone string for PHP DateTimeZone() class
28
-     * @throws InvalidArgumentException
29
-     * @throws InvalidDataTypeException
30
-     * @throws InvalidInterfaceException
31
-     */
32
-    public static function get_timezone()
33
-    {
34
-        return EEH_DTT_Helper::get_valid_timezone_string();
35
-    }
36
-
37
-
38
-    /**
39
-     * get_valid_timezone_string
40
-     *    ensures that a valid timezone string is returned
41
-     *
42
-     * @param string $timezone_string
43
-     * @return string
44
-     * @throws InvalidArgumentException
45
-     * @throws InvalidDataTypeException
46
-     * @throws InvalidInterfaceException
47
-     */
48
-    public static function get_valid_timezone_string($timezone_string = '')
49
-    {
50
-        return self::getHelperAdapter()->getValidTimezoneString($timezone_string);
51
-    }
52
-
53
-
54
-    /**
55
-     * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
56
-     *
57
-     * @static
58
-     * @param  string $timezone_string Timezone string to check
59
-     * @param bool    $throw_error
60
-     * @return bool
61
-     * @throws InvalidArgumentException
62
-     * @throws InvalidDataTypeException
63
-     * @throws InvalidInterfaceException
64
-     */
65
-    public static function validate_timezone($timezone_string, $throw_error = true)
66
-    {
67
-        return self::getHelperAdapter()->validateTimezone($timezone_string, $throw_error);
68
-    }
69
-
70
-
71
-    /**
72
-     * This returns a string that can represent the provided gmt offset in format that can be passed into
73
-     * DateTimeZone.  This is NOT a string that can be passed as a value on the WordPress timezone_string option.
74
-     *
75
-     * @param float|string $gmt_offset
76
-     * @return string
77
-     * @throws InvalidArgumentException
78
-     * @throws InvalidDataTypeException
79
-     * @throws InvalidInterfaceException
80
-     */
81
-    public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
82
-    {
83
-        return self::getHelperAdapter()->getTimezoneStringFromGmtOffset($gmt_offset);
84
-    }
85
-
86
-
87
-    /**
88
-     * Gets the site's GMT offset based on either the timezone string
89
-     * (in which case teh gmt offset will vary depending on the location's
90
-     * observance of daylight savings time) or the gmt_offset wp option
91
-     *
92
-     * @return int seconds offset
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     */
97
-    public static function get_site_timezone_gmt_offset()
98
-    {
99
-        return self::getHelperAdapter()->getSiteTimezoneGmtOffset();
100
-    }
101
-
102
-
103
-    /**
104
-     * Depending on PHP version,
105
-     * there might not be valid current timezone strings to match these gmt_offsets in its timezone tables.
106
-     * To get around that, for these fringe timezones we bump them to a known valid offset.
107
-     * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
108
-     *
109
-     * @deprecated 4.9.54.rc    Developers this was always meant to only be an internally used method.  This will be
110
-     *                          removed in a future version of EE.
111
-     * @param int $gmt_offset
112
-     * @return int
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     */
117
-    public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
118
-    {
119
-        return self::getHelperAdapter()->adjustInvalidGmtOffsets($gmt_offset);
120
-    }
121
-
122
-
123
-    /**
124
-     * get_timezone_string_from_abbreviations_list
125
-     *
126
-     * @deprecated 4.9.54.rc  Developers, this was never intended to be public.  This is a soft deprecation for now.
127
-     *                        If you are using this, you'll want to work out an alternate way of getting the value.
128
-     * @param int  $gmt_offset
129
-     * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
130
-     * @return string
131
-     * @throws EE_Error
132
-     * @throws InvalidArgumentException
133
-     * @throws InvalidDataTypeException
134
-     * @throws InvalidInterfaceException
135
-     */
136
-    public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
137
-    {
138
-        $gmt_offset =  (int) $gmt_offset;
139
-        /** @var array[] $abbreviations */
140
-        $abbreviations = DateTimeZone::listAbbreviations();
141
-        foreach ($abbreviations as $abbreviation) {
142
-            foreach ($abbreviation as $timezone) {
143
-                if ((int) $timezone['offset'] === $gmt_offset && (bool) $timezone['dst'] === false) {
144
-                    try {
145
-                        $offset = self::get_timezone_offset(new DateTimeZone($timezone['timezone_id']));
146
-                        if ($offset !== $gmt_offset) {
147
-                            continue;
148
-                        }
149
-                        return $timezone['timezone_id'];
150
-                    } catch (Exception $e) {
151
-                        continue;
152
-                    }
153
-                }
154
-            }
155
-        }
156
-        //if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
157
-        if ($coerce === true) {
158
-            $timezone_string = self::get_timezone_string_from_abbreviations_list(
159
-                self::adjust_invalid_gmt_offsets($gmt_offset),
160
-                false
161
-            );
162
-            if ($timezone_string) {
163
-                return $timezone_string;
164
-            }
165
-        }
166
-        throw new EE_Error(
167
-            sprintf(
168
-                esc_html__(
169
-                    'The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
170
-                    'event_espresso'
171
-                ),
172
-                $gmt_offset / HOUR_IN_SECONDS,
173
-                '<a href="http://www.php.net/manual/en/timezones.php">',
174
-                '</a>'
175
-            )
176
-        );
177
-    }
178
-
179
-
180
-    /**
181
-     * Get Timezone Transitions
182
-     *
183
-     * @param DateTimeZone $date_time_zone
184
-     * @param int|null     $time
185
-     * @param bool         $first_only
186
-     * @return array
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     */
191
-    public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
192
-    {
193
-        return self::getHelperAdapter()->getTimezoneTransitions($date_time_zone, $time, $first_only);
194
-    }
195
-
196
-
197
-    /**
198
-     * Get Timezone Offset for given timezone object.
199
-     *
200
-     * @param DateTimeZone $date_time_zone
201
-     * @param null         $time
202
-     * @return mixed
203
-     * @throws InvalidArgumentException
204
-     * @throws InvalidDataTypeException
205
-     * @throws InvalidInterfaceException
206
-     */
207
-    public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
208
-    {
209
-        return self::getHelperAdapter()->getTimezoneOffset($date_time_zone, $time);
210
-    }
211
-
212
-
213
-    /**
214
-     * Prints a select input for the given timezone string.
215
-     * @param string $timezone_string
216
-     * @deprecatd 4.9.54.rc   Soft deprecation.  Consider using \EEH_DTT_Helper::wp_timezone_choice instead.
217
-     * @throws InvalidArgumentException
218
-     * @throws InvalidDataTypeException
219
-     * @throws InvalidInterfaceException
220
-     */
221
-    public static function timezone_select_input($timezone_string = '')
222
-    {
223
-        self::getHelperAdapter()->timezoneSelectInput($timezone_string);
224
-    }
225
-
226
-
227
-    /**
228
-     * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
229
-     * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
230
-     * the site is used.
231
-     * This is used typically when using a Unix timestamp any core WP functions that expect their specially
232
-     * computed timestamp (i.e. date_i18n() )
233
-     *
234
-     * @param int    $unix_timestamp                  if 0, then time() will be used.
235
-     * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
236
-     *                                                site will be used.
237
-     * @return int $unix_timestamp with the offset applied for the given timezone.
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     */
242
-    public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
243
-    {
244
-        return self::getHelperAdapter()->getTimestampWithOffset($unix_timestamp, $timezone_string);
245
-    }
246
-
247
-
248
-    /**
249
-     *    _set_date_time_field
250
-     *    modifies EE_Base_Class EE_Datetime_Field objects
251
-     *
252
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
253
-     * @param    DateTime    $DateTime            PHP DateTime object
254
-     * @param  string        $datetime_field_name the datetime fieldname to be manipulated
255
-     * @return EE_Base_Class
256
-     * @throws EE_Error
257
-     */
258
-    protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
259
-    {
260
-        // grab current datetime format
261
-        $current_format = $obj->get_format();
262
-        // set new full timestamp format
263
-        $obj->set_date_format(EE_Datetime_Field::mysql_date_format);
264
-        $obj->set_time_format(EE_Datetime_Field::mysql_time_format);
265
-        // set the new date value using a full timestamp format so that no data is lost
266
-        $obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
267
-        // reset datetime formats
268
-        $obj->set_date_format($current_format[0]);
269
-        $obj->set_time_format($current_format[1]);
270
-        return $obj;
271
-    }
272
-
273
-
274
-    /**
275
-     *    date_time_add
276
-     *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
277
-     *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
278
-     *
279
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
280
-     * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
281
-     * @param  string        $period              what you are adding. The options are (years, months, days, hours,
282
-     *                                            minutes, seconds) defaults to years
283
-     * @param  integer       $value               what you want to increment the time by
284
-     * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it
285
-     *                                            (chaining)
286
-     * @throws EE_Error
287
-     * @throws Exception
288
-     */
289
-    public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
290
-    {
291
-        //get the raw UTC date.
292
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
293
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
294
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
295
-    }
296
-
297
-
298
-    /**
299
-     *    date_time_subtract
300
-     *    same as date_time_add except subtracting value instead of adding.
301
-     *
302
-     * @param EE_Base_Class $obj
303
-     * @param  string       $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
304
-     * @param string        $period
305
-     * @param int           $value
306
-     * @return EE_Base_Class
307
-     * @throws EE_Error
308
-     * @throws Exception
309
-     */
310
-    public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
311
-    {
312
-        //get the raw UTC date
313
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
314
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
315
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
316
-    }
317
-
318
-
319
-    /**
320
-     * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
321
-     *
322
-     * @param  DateTime   $DateTime DateTime object
323
-     * @param  string     $period   a value to indicate what interval is being used in the calculation. The options are
324
-     *                              'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
325
-     * @param  int|string $value    What you want to increment the date by
326
-     * @param  string     $operand  What operand you wish to use for the calculation
327
-     * @return DateTime return whatever type came in.
328
-     * @throws Exception
329
-     * @throws EE_Error
330
-     */
331
-    protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
332
-    {
333
-        if (! $DateTime instanceof DateTime) {
334
-            throw new EE_Error(
335
-                sprintf(
336
-                    esc_html__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
337
-                    print_r($DateTime, true)
338
-                )
339
-            );
340
-        }
341
-        switch ($period) {
342
-            case 'years' :
343
-                $value = 'P' . $value . 'Y';
344
-                break;
345
-            case 'months' :
346
-                $value = 'P' . $value . 'M';
347
-                break;
348
-            case 'weeks' :
349
-                $value = 'P' . $value . 'W';
350
-                break;
351
-            case 'days' :
352
-                $value = 'P' . $value . 'D';
353
-                break;
354
-            case 'hours' :
355
-                $value = 'PT' . $value . 'H';
356
-                break;
357
-            case 'minutes' :
358
-                $value = 'PT' . $value . 'M';
359
-                break;
360
-            case 'seconds' :
361
-                $value = 'PT' . $value . 'S';
362
-                break;
363
-        }
364
-        switch ($operand) {
365
-            case '+':
366
-                $DateTime->add(new DateInterval($value));
367
-                break;
368
-            case '-':
369
-                $DateTime->sub(new DateInterval($value));
370
-                break;
371
-        }
372
-        return $DateTime;
373
-    }
374
-
375
-
376
-    /**
377
-     * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
378
-     *
379
-     * @param  int     $timestamp Unix timestamp
380
-     * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
381
-     *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
382
-     * @param  integer $value     What you want to increment the date by
383
-     * @param  string  $operand   What operand you wish to use for the calculation
384
-     * @return int
385
-     * @throws EE_Error
386
-     */
387
-    protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
388
-    {
389
-        if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
390
-            throw new EE_Error(
391
-                sprintf(
392
-                    esc_html__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
393
-                    print_r($timestamp, true)
394
-                )
395
-            );
396
-        }
397
-        switch ($period) {
398
-            case 'years' :
399
-                $value = YEAR_IN_SECONDS * $value;
400
-                break;
401
-            case 'months' :
402
-                $value = YEAR_IN_SECONDS / 12 * $value;
403
-                break;
404
-            case 'weeks' :
405
-                $value = WEEK_IN_SECONDS * $value;
406
-                break;
407
-            case 'days' :
408
-                $value = DAY_IN_SECONDS * $value;
409
-                break;
410
-            case 'hours' :
411
-                $value = HOUR_IN_SECONDS * $value;
412
-                break;
413
-            case 'minutes' :
414
-                $value = MINUTE_IN_SECONDS * $value;
415
-                break;
416
-        }
417
-        switch ($operand) {
418
-            case '+':
419
-                $timestamp += $value;
420
-                break;
421
-            case '-':
422
-                $timestamp -= $value;
423
-                break;
424
-        }
425
-        return $timestamp;
426
-    }
427
-
428
-
429
-    /**
430
-     * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
431
-     * parameters and returns the new timestamp or DateTime.
432
-     *
433
-     * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
434
-     * @param  string         $period                a value to indicate what interval is being used in the
435
-     *                                               calculation. The options are 'years', 'months', 'days', 'hours',
436
-     *                                               'minutes', 'seconds'. Defaults to years.
437
-     * @param  integer        $value                 What you want to increment the date by
438
-     * @param  string         $operand               What operand you wish to use for the calculation
439
-     * @return mixed string|DateTime          return whatever type came in.
440
-     * @throws Exception
441
-     * @throws EE_Error
442
-     */
443
-    public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
444
-    {
445
-        if ($DateTime_or_timestamp instanceof DateTime) {
446
-            return EEH_DTT_Helper::_modify_datetime_object(
447
-                $DateTime_or_timestamp,
448
-                $period,
449
-                $value,
450
-                $operand
451
-            );
452
-        }
453
-        if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
454
-            return EEH_DTT_Helper::_modify_timestamp(
455
-                $DateTime_or_timestamp,
456
-                $period,
457
-                $value,
458
-                $operand
459
-            );
460
-        }
461
-        //error
462
-        return $DateTime_or_timestamp;
463
-    }
464
-
465
-
466
-    /**
467
-     * The purpose of this helper method is to receive an incoming format string in php date/time format
468
-     * and spit out the js and moment.js equivalent formats.
469
-     * Note, if no format string is given, then it is assumed the user wants what is set for WP.
470
-     * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
471
-     * time picker.
472
-     *
473
-     * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
474
-     * @param string $date_format_string
475
-     * @param string $time_format_string
476
-     * @return array
477
-     *              array(
478
-     *              'js' => array (
479
-     *              'date' => //date format
480
-     *              'time' => //time format
481
-     *              ),
482
-     *              'moment' => //date and time format.
483
-     *              )
484
-     */
485
-    public static function convert_php_to_js_and_moment_date_formats(
486
-        $date_format_string = null,
487
-        $time_format_string = null
488
-    ) {
489
-        if ($date_format_string === null) {
490
-            $date_format_string = (string) get_option('date_format');
491
-        }
492
-        if ($time_format_string === null) {
493
-            $time_format_string = (string) get_option('time_format');
494
-        }
495
-        $date_format = self::_php_to_js_moment_converter($date_format_string);
496
-        $time_format = self::_php_to_js_moment_converter($time_format_string);
497
-        return array(
498
-            'js'     => array(
499
-                'date' => $date_format['js'],
500
-                'time' => $time_format['js'],
501
-            ),
502
-            'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
503
-        );
504
-    }
505
-
506
-
507
-    /**
508
-     * This converts incoming format string into js and moment variations.
509
-     *
510
-     * @param string $format_string incoming php format string
511
-     * @return array js and moment formats.
512
-     */
513
-    protected static function _php_to_js_moment_converter($format_string)
514
-    {
515
-        /**
516
-         * This is a map of symbols for formats.
517
-         * The index is the php symbol, the equivalent values are in the array.
518
-         *
519
-         * @var array
520
-         */
521
-        $symbols_map          = array(
522
-            // Day
523
-            //01
524
-            'd' => array(
525
-                'js'     => 'dd',
526
-                'moment' => 'DD',
527
-            ),
528
-            //Mon
529
-            'D' => array(
530
-                'js'     => 'D',
531
-                'moment' => 'ddd',
532
-            ),
533
-            //1,2,...31
534
-            'j' => array(
535
-                'js'     => 'd',
536
-                'moment' => 'D',
537
-            ),
538
-            //Monday
539
-            'l' => array(
540
-                'js'     => 'DD',
541
-                'moment' => 'dddd',
542
-            ),
543
-            //ISO numeric representation of the day of the week (1-6)
544
-            'N' => array(
545
-                'js'     => '',
546
-                'moment' => 'E',
547
-            ),
548
-            //st,nd.rd
549
-            'S' => array(
550
-                'js'     => '',
551
-                'moment' => 'o',
552
-            ),
553
-            //numeric representation of day of week (0-6)
554
-            'w' => array(
555
-                'js'     => '',
556
-                'moment' => 'd',
557
-            ),
558
-            //day of year starting from 0 (0-365)
559
-            'z' => array(
560
-                'js'     => 'o',
561
-                'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1
562
-            ),
563
-            // Week
564
-            //ISO-8601 week number of year (weeks starting on monday)
565
-            'W' => array(
566
-                'js'     => '',
567
-                'moment' => 'w',
568
-            ),
569
-            // Month
570
-            // January...December
571
-            'F' => array(
572
-                'js'     => 'MM',
573
-                'moment' => 'MMMM',
574
-            ),
575
-            //01...12
576
-            'm' => array(
577
-                'js'     => 'mm',
578
-                'moment' => 'MM',
579
-            ),
580
-            //Jan...Dec
581
-            'M' => array(
582
-                'js'     => 'M',
583
-                'moment' => 'MMM',
584
-            ),
585
-            //1-12
586
-            'n' => array(
587
-                'js'     => 'm',
588
-                'moment' => 'M',
589
-            ),
590
-            //number of days in given month
591
-            't' => array(
592
-                'js'     => '',
593
-                'moment' => '',
594
-            ),
595
-            // Year
596
-            //whether leap year or not 1/0
597
-            'L' => array(
598
-                'js'     => '',
599
-                'moment' => '',
600
-            ),
601
-            //ISO-8601 year number
602
-            'o' => array(
603
-                'js'     => '',
604
-                'moment' => 'GGGG',
605
-            ),
606
-            //1999...2003
607
-            'Y' => array(
608
-                'js'     => 'yy',
609
-                'moment' => 'YYYY',
610
-            ),
611
-            //99...03
612
-            'y' => array(
613
-                'js'     => 'y',
614
-                'moment' => 'YY',
615
-            ),
616
-            // Time
617
-            // am/pm
618
-            'a' => array(
619
-                'js'     => 'tt',
620
-                'moment' => 'a',
621
-            ),
622
-            // AM/PM
623
-            'A' => array(
624
-                'js'     => 'TT',
625
-                'moment' => 'A',
626
-            ),
627
-            // Swatch Internet Time?!?
628
-            'B' => array(
629
-                'js'     => '',
630
-                'moment' => '',
631
-            ),
632
-            //1...12
633
-            'g' => array(
634
-                'js'     => 'h',
635
-                'moment' => 'h',
636
-            ),
637
-            //0...23
638
-            'G' => array(
639
-                'js'     => 'H',
640
-                'moment' => 'H',
641
-            ),
642
-            //01...12
643
-            'h' => array(
644
-                'js'     => 'hh',
645
-                'moment' => 'hh',
646
-            ),
647
-            //00...23
648
-            'H' => array(
649
-                'js'     => 'HH',
650
-                'moment' => 'HH',
651
-            ),
652
-            //00..59
653
-            'i' => array(
654
-                'js'     => 'mm',
655
-                'moment' => 'mm',
656
-            ),
657
-            //seconds... 00...59
658
-            's' => array(
659
-                'js'     => 'ss',
660
-                'moment' => 'ss',
661
-            ),
662
-            //microseconds
663
-            'u' => array(
664
-                'js'     => '',
665
-                'moment' => '',
666
-            ),
667
-        );
668
-        $jquery_ui_format     = '';
669
-        $moment_format        = '';
670
-        $escaping             = false;
671
-        $format_string_length = strlen($format_string);
672
-        for ($i = 0; $i < $format_string_length; $i++) {
673
-            $char = $format_string[ $i ];
674
-            if ($char === '\\') { // PHP date format escaping character
675
-                $i++;
676
-                if ($escaping) {
677
-                    $jquery_ui_format .= $format_string[ $i ];
678
-                    $moment_format    .= $format_string[ $i ];
679
-                } else {
680
-                    $jquery_ui_format .= '\'' . $format_string[ $i ];
681
-                    $moment_format    .= $format_string[ $i ];
682
-                }
683
-                $escaping = true;
684
-            } else {
685
-                if ($escaping) {
686
-                    $jquery_ui_format .= "'";
687
-                    $moment_format    .= "'";
688
-                    $escaping         = false;
689
-                }
690
-                if (isset($symbols_map[ $char ])) {
691
-                    $jquery_ui_format .= $symbols_map[ $char ]['js'];
692
-                    $moment_format    .= $symbols_map[ $char ]['moment'];
693
-                } else {
694
-                    $jquery_ui_format .= $char;
695
-                    $moment_format    .= $char;
696
-                }
697
-            }
698
-        }
699
-        return array('js' => $jquery_ui_format, 'moment' => $moment_format);
700
-    }
701
-
702
-
703
-    /**
704
-     * This takes an incoming format string and validates it to ensure it will work fine with PHP.
705
-     *
706
-     * @param string $format_string   Incoming format string for php date().
707
-     * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
708
-     *                                errors is returned.  So for client code calling, check for is_array() to
709
-     *                                indicate failed validations.
710
-     */
711
-    public static function validate_format_string($format_string)
712
-    {
713
-        $error_msg = array();
714
-        //time format checks
715
-        switch (true) {
716
-            case   strpos($format_string, 'h') !== false  :
717
-            case   strpos($format_string, 'g') !== false :
718
-                /**
719
-                 * if the time string has a lowercase 'h' which == 12 hour time format and there
720
-                 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
721
-                 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
722
-                 */
723
-                if (stripos($format_string, 'A') === false) {
724
-                    $error_msg[] = esc_html__(
725
-                        'There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
726
-                        'event_espresso'
727
-                    );
728
-                }
729
-                break;
730
-        }
731
-        return empty($error_msg) ? true : $error_msg;
732
-    }
733
-
734
-
735
-    /**
736
-     *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
737
-     *     very next day then this method will return true.
738
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
739
-     *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
740
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
741
-     *
742
-     * @param mixed $date_1
743
-     * @param mixed $date_2
744
-     * @return bool
745
-     */
746
-    public static function dates_represent_one_24_hour_date($date_1, $date_2)
747
-    {
748
-
749
-        if (
750
-            (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime)
751
-            || ($date_1->format(EE_Datetime_Field::mysql_time_format) !== '00:00:00'
752
-                || $date_2->format(
753
-                    EE_Datetime_Field::mysql_time_format
754
-                ) !== '00:00:00')
755
-        ) {
756
-            return false;
757
-        }
758
-        return $date_2->format('U') - $date_1->format('U') === 86400;
759
-    }
760
-
761
-
762
-    /**
763
-     * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
764
-     * Functions.
765
-     *
766
-     * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
767
-     * @param string $field_for_interval The Database field that is the interval is applied to in the query.
768
-     * @return string
769
-     */
770
-    public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
771
-    {
772
-        try {
773
-            /** need to account for timezone offset on the selects */
774
-            $DateTimeZone = new DateTimeZone($timezone_string);
775
-        } catch (Exception $e) {
776
-            $DateTimeZone = null;
777
-        }
778
-        /**
779
-         * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
780
-         * Hence we do the calc for DateTimeZone::getOffset.
781
-         */
782
-        $offset         = $DateTimeZone instanceof DateTimeZone
783
-            ? $DateTimeZone->getOffset(new DateTime('now')) / HOUR_IN_SECONDS
784
-            : (float) get_option('gmt_offset');
785
-        $query_interval = $offset < 0
786
-            ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
787
-            : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
788
-        return $query_interval;
789
-    }
790
-
791
-
792
-    /**
793
-     * Retrieves the site's default timezone and returns it formatted so it's ready for display
794
-     * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
795
-     * and 'gmt_offset' WordPress options directly; or use the filter
796
-     * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
797
-     * (although note that we remove any HTML that may be added)
798
-     *
799
-     * @return string
800
-     */
801
-    public static function get_timezone_string_for_display()
802
-    {
803
-        $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
804
-        if (! empty($pretty_timezone)) {
805
-            return esc_html($pretty_timezone);
806
-        }
807
-        $timezone_string = get_option('timezone_string');
808
-        if ($timezone_string) {
809
-            static $mo_loaded = false;
810
-            // Load translations for continents and cities just like wp_timezone_choice does
811
-            if (! $mo_loaded) {
812
-                $locale = get_locale();
813
-                $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
814
-                load_textdomain('continents-cities', $mofile);
815
-                $mo_loaded = true;
816
-            }
817
-            //well that was easy.
818
-            $parts = explode('/', $timezone_string);
819
-            //remove the continent
820
-            unset($parts[0]);
821
-            $t_parts = array();
822
-            foreach ($parts as $part) {
823
-                $t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
824
-            }
825
-            return implode(' - ', $t_parts);
826
-        }
827
-        //they haven't set the timezone string, so let's return a string like "UTC+1"
828
-        $gmt_offset = get_option('gmt_offset');
829
-        $prefix     = (int) $gmt_offset >= 0 ? '+' : '';
830
-        $parts      = explode('.', (string) $gmt_offset);
831
-        if (count($parts) === 1) {
832
-            $parts[1] = '00';
833
-        } else {
834
-            //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
835
-            //to minutes, eg 30 or 15, respectively
836
-            $hour_fraction = (float) ('0.' . $parts[1]);
837
-            $parts[1]      = (string) $hour_fraction * 60;
838
-        }
839
-        return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
840
-    }
841
-
842
-
843
-
844
-    /**
845
-     * So PHP does this awesome thing where if you are trying to get a timestamp
846
-     * for a month using a string like "February" or "February 2017",
847
-     * and you don't specify a day as part of your string,
848
-     * then PHP will use whatever the current day of the month is.
849
-     * IF the current day of the month happens to be the 30th or 31st,
850
-     * then PHP gets really confused by a date like February 30,
851
-     * so instead of saying
852
-     *      "Hey February only has 28 days (this year)...
853
-     *      ...you must have meant the last day of the month!"
854
-     * PHP does the next most logical thing, and bumps the date up to March 2nd,
855
-     * because someone requesting February 30th obviously meant March 1st!
856
-     * The way around this is to always set the day to the first,
857
-     * so that the month will stay on the month you wanted.
858
-     * this method will add that "1" into your date regardless of the format.
859
-     *
860
-     * @param string $month
861
-     * @return string
862
-     */
863
-    public static function first_of_month_timestamp($month = '')
864
-    {
865
-        $month = (string) $month;
866
-        $year  = '';
867
-        // check if the incoming string has a year in it or not
868
-        if (preg_match('/\b\d{4}\b/', $month, $matches)) {
869
-            $year = $matches[0];
870
-            // ten remove that from the month string as well as any spaces
871
-            $month = trim(str_replace($year, '', $month));
872
-            // add a space before the year
873
-            $year = " {$year}";
874
-        }
875
-        // return timestamp for something like "February 1 2017"
876
-        return strtotime("{$month} 1{$year}");
877
-    }
878
-
879
-
880
-    /**
881
-     * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
882
-     * for this sites timezone, but the timestamp could be some other time GMT.
883
-     */
884
-    public static function tomorrow()
885
-    {
886
-        //The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive
887
-        //before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
888
-        //not an offset from midnight in UTC.  So if we're starting with UTC 00:00:00, then we want to make sure the
889
-        //final timestamp is equivalent to midnight in this timezone as represented in GMT.
890
-        return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1);
891
-    }
892
-
893
-
894
-    /**
895
-     * **
896
-     * Gives a nicely-formatted list of timezone strings.
897
-     * Copied from the core wp function by the same name so we could customize to remove UTC offsets.
898
-     *
899
-     * @since     4.9.40.rc.008
900
-     * @staticvar bool $mo_loaded
901
-     * @staticvar string $locale_loaded
902
-     * @param string $selected_zone Selected timezone.
903
-     * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
904
-     * @return string
905
-     */
906
-    public static function wp_timezone_choice($selected_zone, $locale = null)
907
-    {
908
-        static $mo_loaded = false, $locale_loaded = null;
909
-        $continents = array(
910
-            'Africa',
911
-            'America',
912
-            'Antarctica',
913
-            'Arctic',
914
-            'Asia',
915
-            'Atlantic',
916
-            'Australia',
917
-            'Europe',
918
-            'Indian',
919
-            'Pacific',
920
-        );
921
-        // Load translations for continents and cities.
922
-        if (! $mo_loaded || $locale !== $locale_loaded) {
923
-            $locale_loaded = $locale ? $locale : get_locale();
924
-            $mofile        = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
925
-            unload_textdomain('continents-cities');
926
-            load_textdomain('continents-cities', $mofile);
927
-            $mo_loaded = true;
928
-        }
929
-        $zone_data = array();
930
-        foreach (timezone_identifiers_list() as $zone) {
931
-            $zone = explode('/', $zone);
932
-            if (! in_array($zone[0], $continents, true)) {
933
-                continue;
934
-            }
935
-            // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
936
-            $exists      = array(
937
-                0 => isset($zone[0]) && $zone[0],
938
-                1 => isset($zone[1]) && $zone[1],
939
-                2 => isset($zone[2]) && $zone[2],
940
-            );
941
-            $exists[3]   = $exists[0] && $zone[0] !== 'Etc';
942
-            $exists[4]   = $exists[1] && $exists[3];
943
-            $exists[5]   = $exists[2] && $exists[3];
944
-            $zone_data[] = array(
945
-                'continent'   => $exists[0] ? $zone[0] : '',
946
-                'city'        => $exists[1] ? $zone[1] : '',
947
-                'subcity'     => $exists[2] ? $zone[2] : '',
948
-                't_continent' => $exists[3]
949
-                    ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities')
950
-                    : '',
951
-                't_city'      => $exists[4]
952
-                    ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities')
953
-                    : '',
954
-                't_subcity'   => $exists[5]
955
-                    ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities')
956
-                    : '',
957
-            );
958
-        }
959
-        usort($zone_data, '_wp_timezone_choice_usort_callback');
960
-        $structure = array();
961
-        if (empty($selected_zone)) {
962
-            $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
963
-        }
964
-        foreach ($zone_data as $key => $zone) {
965
-            // Build value in an array to join later
966
-            $value = array($zone['continent']);
967
-            if (empty($zone['city'])) {
968
-                // It's at the continent level (generally won't happen)
969
-                $display = $zone['t_continent'];
970
-            } else {
971
-                // It's inside a continent group
972
-                // Continent optgroup
973
-                if (! isset($zone_data[ $key - 1 ]) || $zone_data[ $key - 1 ]['continent'] !== $zone['continent']) {
974
-                    $label       = $zone['t_continent'];
975
-                    $structure[] = '<optgroup label="' . esc_attr($label) . '">';
976
-                }
977
-                // Add the city to the value
978
-                $value[] = $zone['city'];
979
-                $display = $zone['t_city'];
980
-                if (! empty($zone['subcity'])) {
981
-                    // Add the subcity to the value
982
-                    $value[] = $zone['subcity'];
983
-                    $display .= ' - ' . $zone['t_subcity'];
984
-                }
985
-            }
986
-            // Build the value
987
-            $value       = implode('/', $value);
988
-            $selected    = $value === $selected_zone ? ' selected="selected"' : '';
989
-            $structure[] = '<option value="' . esc_attr($value) . '"' . $selected . '>'
990
-                           . esc_html($display)
991
-                           . '</option>';
992
-            // Close continent optgroup
993
-            if (! empty($zone['city'])
994
-                && (
995
-                    ! isset($zone_data[ $key + 1 ])
996
-                    || (isset($zone_data[ $key + 1 ]) && $zone_data[ $key + 1 ]['continent'] !== $zone['continent'])
997
-                )
998
-            ) {
999
-                $structure[] = '</optgroup>';
1000
-            }
1001
-        }
1002
-        return implode("\n", $structure);
1003
-    }
1004
-
1005
-
1006
-    /**
1007
-     * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0
1008
-     *
1009
-     * @param int|WP_User $user_id
1010
-     * @return string
1011
-     */
1012
-    public static function get_user_locale($user_id = 0)
1013
-    {
1014
-        if (function_exists('get_user_locale')) {
1015
-            return get_user_locale($user_id);
1016
-        }
1017
-        return get_locale();
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Return the appropriate helper adapter for DTT related things.
1023
-     *
1024
-     * @return HelperInterface
1025
-     * @throws InvalidArgumentException
1026
-     * @throws InvalidDataTypeException
1027
-     * @throws InvalidInterfaceException
1028
-     */
1029
-    private static function getHelperAdapter() {
1030
-        $dtt_helper_fqcn = PHP_VERSION_ID < 50600
1031
-            ? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper'
1032
-            : 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper';
1033
-        return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn);
1034
-    }
1035
-
1036
-
1037
-    /**
1038
-     * Helper function for setting the timezone on a DateTime object.
1039
-     * This is implemented to standardize a workaround for a PHP bug outlined in
1040
-     * https://events.codebasehq.com/projects/event-espresso/tickets/11407 and
1041
-     * https://events.codebasehq.com/projects/event-espresso/tickets/11233
1042
-     *
1043
-     * @param DateTime     $datetime
1044
-     * @param DateTimeZone $timezone
1045
-     */
1046
-    public static function setTimezone(DateTime $datetime, DateTimeZone $timezone)
1047
-    {
1048
-        $datetime->setTimezone($timezone);
1049
-        $datetime->getTimestamp();
1050
-    }
24
+	/**
25
+	 * return the timezone set for the WP install
26
+	 *
27
+	 * @return string valid timezone string for PHP DateTimeZone() class
28
+	 * @throws InvalidArgumentException
29
+	 * @throws InvalidDataTypeException
30
+	 * @throws InvalidInterfaceException
31
+	 */
32
+	public static function get_timezone()
33
+	{
34
+		return EEH_DTT_Helper::get_valid_timezone_string();
35
+	}
36
+
37
+
38
+	/**
39
+	 * get_valid_timezone_string
40
+	 *    ensures that a valid timezone string is returned
41
+	 *
42
+	 * @param string $timezone_string
43
+	 * @return string
44
+	 * @throws InvalidArgumentException
45
+	 * @throws InvalidDataTypeException
46
+	 * @throws InvalidInterfaceException
47
+	 */
48
+	public static function get_valid_timezone_string($timezone_string = '')
49
+	{
50
+		return self::getHelperAdapter()->getValidTimezoneString($timezone_string);
51
+	}
52
+
53
+
54
+	/**
55
+	 * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
56
+	 *
57
+	 * @static
58
+	 * @param  string $timezone_string Timezone string to check
59
+	 * @param bool    $throw_error
60
+	 * @return bool
61
+	 * @throws InvalidArgumentException
62
+	 * @throws InvalidDataTypeException
63
+	 * @throws InvalidInterfaceException
64
+	 */
65
+	public static function validate_timezone($timezone_string, $throw_error = true)
66
+	{
67
+		return self::getHelperAdapter()->validateTimezone($timezone_string, $throw_error);
68
+	}
69
+
70
+
71
+	/**
72
+	 * This returns a string that can represent the provided gmt offset in format that can be passed into
73
+	 * DateTimeZone.  This is NOT a string that can be passed as a value on the WordPress timezone_string option.
74
+	 *
75
+	 * @param float|string $gmt_offset
76
+	 * @return string
77
+	 * @throws InvalidArgumentException
78
+	 * @throws InvalidDataTypeException
79
+	 * @throws InvalidInterfaceException
80
+	 */
81
+	public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
82
+	{
83
+		return self::getHelperAdapter()->getTimezoneStringFromGmtOffset($gmt_offset);
84
+	}
85
+
86
+
87
+	/**
88
+	 * Gets the site's GMT offset based on either the timezone string
89
+	 * (in which case teh gmt offset will vary depending on the location's
90
+	 * observance of daylight savings time) or the gmt_offset wp option
91
+	 *
92
+	 * @return int seconds offset
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 */
97
+	public static function get_site_timezone_gmt_offset()
98
+	{
99
+		return self::getHelperAdapter()->getSiteTimezoneGmtOffset();
100
+	}
101
+
102
+
103
+	/**
104
+	 * Depending on PHP version,
105
+	 * there might not be valid current timezone strings to match these gmt_offsets in its timezone tables.
106
+	 * To get around that, for these fringe timezones we bump them to a known valid offset.
107
+	 * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
108
+	 *
109
+	 * @deprecated 4.9.54.rc    Developers this was always meant to only be an internally used method.  This will be
110
+	 *                          removed in a future version of EE.
111
+	 * @param int $gmt_offset
112
+	 * @return int
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 */
117
+	public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
118
+	{
119
+		return self::getHelperAdapter()->adjustInvalidGmtOffsets($gmt_offset);
120
+	}
121
+
122
+
123
+	/**
124
+	 * get_timezone_string_from_abbreviations_list
125
+	 *
126
+	 * @deprecated 4.9.54.rc  Developers, this was never intended to be public.  This is a soft deprecation for now.
127
+	 *                        If you are using this, you'll want to work out an alternate way of getting the value.
128
+	 * @param int  $gmt_offset
129
+	 * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
130
+	 * @return string
131
+	 * @throws EE_Error
132
+	 * @throws InvalidArgumentException
133
+	 * @throws InvalidDataTypeException
134
+	 * @throws InvalidInterfaceException
135
+	 */
136
+	public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
137
+	{
138
+		$gmt_offset =  (int) $gmt_offset;
139
+		/** @var array[] $abbreviations */
140
+		$abbreviations = DateTimeZone::listAbbreviations();
141
+		foreach ($abbreviations as $abbreviation) {
142
+			foreach ($abbreviation as $timezone) {
143
+				if ((int) $timezone['offset'] === $gmt_offset && (bool) $timezone['dst'] === false) {
144
+					try {
145
+						$offset = self::get_timezone_offset(new DateTimeZone($timezone['timezone_id']));
146
+						if ($offset !== $gmt_offset) {
147
+							continue;
148
+						}
149
+						return $timezone['timezone_id'];
150
+					} catch (Exception $e) {
151
+						continue;
152
+					}
153
+				}
154
+			}
155
+		}
156
+		//if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
157
+		if ($coerce === true) {
158
+			$timezone_string = self::get_timezone_string_from_abbreviations_list(
159
+				self::adjust_invalid_gmt_offsets($gmt_offset),
160
+				false
161
+			);
162
+			if ($timezone_string) {
163
+				return $timezone_string;
164
+			}
165
+		}
166
+		throw new EE_Error(
167
+			sprintf(
168
+				esc_html__(
169
+					'The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
170
+					'event_espresso'
171
+				),
172
+				$gmt_offset / HOUR_IN_SECONDS,
173
+				'<a href="http://www.php.net/manual/en/timezones.php">',
174
+				'</a>'
175
+			)
176
+		);
177
+	}
178
+
179
+
180
+	/**
181
+	 * Get Timezone Transitions
182
+	 *
183
+	 * @param DateTimeZone $date_time_zone
184
+	 * @param int|null     $time
185
+	 * @param bool         $first_only
186
+	 * @return array
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 */
191
+	public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
192
+	{
193
+		return self::getHelperAdapter()->getTimezoneTransitions($date_time_zone, $time, $first_only);
194
+	}
195
+
196
+
197
+	/**
198
+	 * Get Timezone Offset for given timezone object.
199
+	 *
200
+	 * @param DateTimeZone $date_time_zone
201
+	 * @param null         $time
202
+	 * @return mixed
203
+	 * @throws InvalidArgumentException
204
+	 * @throws InvalidDataTypeException
205
+	 * @throws InvalidInterfaceException
206
+	 */
207
+	public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
208
+	{
209
+		return self::getHelperAdapter()->getTimezoneOffset($date_time_zone, $time);
210
+	}
211
+
212
+
213
+	/**
214
+	 * Prints a select input for the given timezone string.
215
+	 * @param string $timezone_string
216
+	 * @deprecatd 4.9.54.rc   Soft deprecation.  Consider using \EEH_DTT_Helper::wp_timezone_choice instead.
217
+	 * @throws InvalidArgumentException
218
+	 * @throws InvalidDataTypeException
219
+	 * @throws InvalidInterfaceException
220
+	 */
221
+	public static function timezone_select_input($timezone_string = '')
222
+	{
223
+		self::getHelperAdapter()->timezoneSelectInput($timezone_string);
224
+	}
225
+
226
+
227
+	/**
228
+	 * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
229
+	 * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
230
+	 * the site is used.
231
+	 * This is used typically when using a Unix timestamp any core WP functions that expect their specially
232
+	 * computed timestamp (i.e. date_i18n() )
233
+	 *
234
+	 * @param int    $unix_timestamp                  if 0, then time() will be used.
235
+	 * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
236
+	 *                                                site will be used.
237
+	 * @return int $unix_timestamp with the offset applied for the given timezone.
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 */
242
+	public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
243
+	{
244
+		return self::getHelperAdapter()->getTimestampWithOffset($unix_timestamp, $timezone_string);
245
+	}
246
+
247
+
248
+	/**
249
+	 *    _set_date_time_field
250
+	 *    modifies EE_Base_Class EE_Datetime_Field objects
251
+	 *
252
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
253
+	 * @param    DateTime    $DateTime            PHP DateTime object
254
+	 * @param  string        $datetime_field_name the datetime fieldname to be manipulated
255
+	 * @return EE_Base_Class
256
+	 * @throws EE_Error
257
+	 */
258
+	protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
259
+	{
260
+		// grab current datetime format
261
+		$current_format = $obj->get_format();
262
+		// set new full timestamp format
263
+		$obj->set_date_format(EE_Datetime_Field::mysql_date_format);
264
+		$obj->set_time_format(EE_Datetime_Field::mysql_time_format);
265
+		// set the new date value using a full timestamp format so that no data is lost
266
+		$obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
267
+		// reset datetime formats
268
+		$obj->set_date_format($current_format[0]);
269
+		$obj->set_time_format($current_format[1]);
270
+		return $obj;
271
+	}
272
+
273
+
274
+	/**
275
+	 *    date_time_add
276
+	 *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
277
+	 *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
278
+	 *
279
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
280
+	 * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
281
+	 * @param  string        $period              what you are adding. The options are (years, months, days, hours,
282
+	 *                                            minutes, seconds) defaults to years
283
+	 * @param  integer       $value               what you want to increment the time by
284
+	 * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it
285
+	 *                                            (chaining)
286
+	 * @throws EE_Error
287
+	 * @throws Exception
288
+	 */
289
+	public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
290
+	{
291
+		//get the raw UTC date.
292
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
293
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
294
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
295
+	}
296
+
297
+
298
+	/**
299
+	 *    date_time_subtract
300
+	 *    same as date_time_add except subtracting value instead of adding.
301
+	 *
302
+	 * @param EE_Base_Class $obj
303
+	 * @param  string       $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
304
+	 * @param string        $period
305
+	 * @param int           $value
306
+	 * @return EE_Base_Class
307
+	 * @throws EE_Error
308
+	 * @throws Exception
309
+	 */
310
+	public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
311
+	{
312
+		//get the raw UTC date
313
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
314
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
315
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
316
+	}
317
+
318
+
319
+	/**
320
+	 * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
321
+	 *
322
+	 * @param  DateTime   $DateTime DateTime object
323
+	 * @param  string     $period   a value to indicate what interval is being used in the calculation. The options are
324
+	 *                              'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
325
+	 * @param  int|string $value    What you want to increment the date by
326
+	 * @param  string     $operand  What operand you wish to use for the calculation
327
+	 * @return DateTime return whatever type came in.
328
+	 * @throws Exception
329
+	 * @throws EE_Error
330
+	 */
331
+	protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
332
+	{
333
+		if (! $DateTime instanceof DateTime) {
334
+			throw new EE_Error(
335
+				sprintf(
336
+					esc_html__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
337
+					print_r($DateTime, true)
338
+				)
339
+			);
340
+		}
341
+		switch ($period) {
342
+			case 'years' :
343
+				$value = 'P' . $value . 'Y';
344
+				break;
345
+			case 'months' :
346
+				$value = 'P' . $value . 'M';
347
+				break;
348
+			case 'weeks' :
349
+				$value = 'P' . $value . 'W';
350
+				break;
351
+			case 'days' :
352
+				$value = 'P' . $value . 'D';
353
+				break;
354
+			case 'hours' :
355
+				$value = 'PT' . $value . 'H';
356
+				break;
357
+			case 'minutes' :
358
+				$value = 'PT' . $value . 'M';
359
+				break;
360
+			case 'seconds' :
361
+				$value = 'PT' . $value . 'S';
362
+				break;
363
+		}
364
+		switch ($operand) {
365
+			case '+':
366
+				$DateTime->add(new DateInterval($value));
367
+				break;
368
+			case '-':
369
+				$DateTime->sub(new DateInterval($value));
370
+				break;
371
+		}
372
+		return $DateTime;
373
+	}
374
+
375
+
376
+	/**
377
+	 * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
378
+	 *
379
+	 * @param  int     $timestamp Unix timestamp
380
+	 * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
381
+	 *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
382
+	 * @param  integer $value     What you want to increment the date by
383
+	 * @param  string  $operand   What operand you wish to use for the calculation
384
+	 * @return int
385
+	 * @throws EE_Error
386
+	 */
387
+	protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
388
+	{
389
+		if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
390
+			throw new EE_Error(
391
+				sprintf(
392
+					esc_html__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
393
+					print_r($timestamp, true)
394
+				)
395
+			);
396
+		}
397
+		switch ($period) {
398
+			case 'years' :
399
+				$value = YEAR_IN_SECONDS * $value;
400
+				break;
401
+			case 'months' :
402
+				$value = YEAR_IN_SECONDS / 12 * $value;
403
+				break;
404
+			case 'weeks' :
405
+				$value = WEEK_IN_SECONDS * $value;
406
+				break;
407
+			case 'days' :
408
+				$value = DAY_IN_SECONDS * $value;
409
+				break;
410
+			case 'hours' :
411
+				$value = HOUR_IN_SECONDS * $value;
412
+				break;
413
+			case 'minutes' :
414
+				$value = MINUTE_IN_SECONDS * $value;
415
+				break;
416
+		}
417
+		switch ($operand) {
418
+			case '+':
419
+				$timestamp += $value;
420
+				break;
421
+			case '-':
422
+				$timestamp -= $value;
423
+				break;
424
+		}
425
+		return $timestamp;
426
+	}
427
+
428
+
429
+	/**
430
+	 * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
431
+	 * parameters and returns the new timestamp or DateTime.
432
+	 *
433
+	 * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
434
+	 * @param  string         $period                a value to indicate what interval is being used in the
435
+	 *                                               calculation. The options are 'years', 'months', 'days', 'hours',
436
+	 *                                               'minutes', 'seconds'. Defaults to years.
437
+	 * @param  integer        $value                 What you want to increment the date by
438
+	 * @param  string         $operand               What operand you wish to use for the calculation
439
+	 * @return mixed string|DateTime          return whatever type came in.
440
+	 * @throws Exception
441
+	 * @throws EE_Error
442
+	 */
443
+	public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
444
+	{
445
+		if ($DateTime_or_timestamp instanceof DateTime) {
446
+			return EEH_DTT_Helper::_modify_datetime_object(
447
+				$DateTime_or_timestamp,
448
+				$period,
449
+				$value,
450
+				$operand
451
+			);
452
+		}
453
+		if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
454
+			return EEH_DTT_Helper::_modify_timestamp(
455
+				$DateTime_or_timestamp,
456
+				$period,
457
+				$value,
458
+				$operand
459
+			);
460
+		}
461
+		//error
462
+		return $DateTime_or_timestamp;
463
+	}
464
+
465
+
466
+	/**
467
+	 * The purpose of this helper method is to receive an incoming format string in php date/time format
468
+	 * and spit out the js and moment.js equivalent formats.
469
+	 * Note, if no format string is given, then it is assumed the user wants what is set for WP.
470
+	 * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
471
+	 * time picker.
472
+	 *
473
+	 * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
474
+	 * @param string $date_format_string
475
+	 * @param string $time_format_string
476
+	 * @return array
477
+	 *              array(
478
+	 *              'js' => array (
479
+	 *              'date' => //date format
480
+	 *              'time' => //time format
481
+	 *              ),
482
+	 *              'moment' => //date and time format.
483
+	 *              )
484
+	 */
485
+	public static function convert_php_to_js_and_moment_date_formats(
486
+		$date_format_string = null,
487
+		$time_format_string = null
488
+	) {
489
+		if ($date_format_string === null) {
490
+			$date_format_string = (string) get_option('date_format');
491
+		}
492
+		if ($time_format_string === null) {
493
+			$time_format_string = (string) get_option('time_format');
494
+		}
495
+		$date_format = self::_php_to_js_moment_converter($date_format_string);
496
+		$time_format = self::_php_to_js_moment_converter($time_format_string);
497
+		return array(
498
+			'js'     => array(
499
+				'date' => $date_format['js'],
500
+				'time' => $time_format['js'],
501
+			),
502
+			'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
503
+		);
504
+	}
505
+
506
+
507
+	/**
508
+	 * This converts incoming format string into js and moment variations.
509
+	 *
510
+	 * @param string $format_string incoming php format string
511
+	 * @return array js and moment formats.
512
+	 */
513
+	protected static function _php_to_js_moment_converter($format_string)
514
+	{
515
+		/**
516
+		 * This is a map of symbols for formats.
517
+		 * The index is the php symbol, the equivalent values are in the array.
518
+		 *
519
+		 * @var array
520
+		 */
521
+		$symbols_map          = array(
522
+			// Day
523
+			//01
524
+			'd' => array(
525
+				'js'     => 'dd',
526
+				'moment' => 'DD',
527
+			),
528
+			//Mon
529
+			'D' => array(
530
+				'js'     => 'D',
531
+				'moment' => 'ddd',
532
+			),
533
+			//1,2,...31
534
+			'j' => array(
535
+				'js'     => 'd',
536
+				'moment' => 'D',
537
+			),
538
+			//Monday
539
+			'l' => array(
540
+				'js'     => 'DD',
541
+				'moment' => 'dddd',
542
+			),
543
+			//ISO numeric representation of the day of the week (1-6)
544
+			'N' => array(
545
+				'js'     => '',
546
+				'moment' => 'E',
547
+			),
548
+			//st,nd.rd
549
+			'S' => array(
550
+				'js'     => '',
551
+				'moment' => 'o',
552
+			),
553
+			//numeric representation of day of week (0-6)
554
+			'w' => array(
555
+				'js'     => '',
556
+				'moment' => 'd',
557
+			),
558
+			//day of year starting from 0 (0-365)
559
+			'z' => array(
560
+				'js'     => 'o',
561
+				'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1
562
+			),
563
+			// Week
564
+			//ISO-8601 week number of year (weeks starting on monday)
565
+			'W' => array(
566
+				'js'     => '',
567
+				'moment' => 'w',
568
+			),
569
+			// Month
570
+			// January...December
571
+			'F' => array(
572
+				'js'     => 'MM',
573
+				'moment' => 'MMMM',
574
+			),
575
+			//01...12
576
+			'm' => array(
577
+				'js'     => 'mm',
578
+				'moment' => 'MM',
579
+			),
580
+			//Jan...Dec
581
+			'M' => array(
582
+				'js'     => 'M',
583
+				'moment' => 'MMM',
584
+			),
585
+			//1-12
586
+			'n' => array(
587
+				'js'     => 'm',
588
+				'moment' => 'M',
589
+			),
590
+			//number of days in given month
591
+			't' => array(
592
+				'js'     => '',
593
+				'moment' => '',
594
+			),
595
+			// Year
596
+			//whether leap year or not 1/0
597
+			'L' => array(
598
+				'js'     => '',
599
+				'moment' => '',
600
+			),
601
+			//ISO-8601 year number
602
+			'o' => array(
603
+				'js'     => '',
604
+				'moment' => 'GGGG',
605
+			),
606
+			//1999...2003
607
+			'Y' => array(
608
+				'js'     => 'yy',
609
+				'moment' => 'YYYY',
610
+			),
611
+			//99...03
612
+			'y' => array(
613
+				'js'     => 'y',
614
+				'moment' => 'YY',
615
+			),
616
+			// Time
617
+			// am/pm
618
+			'a' => array(
619
+				'js'     => 'tt',
620
+				'moment' => 'a',
621
+			),
622
+			// AM/PM
623
+			'A' => array(
624
+				'js'     => 'TT',
625
+				'moment' => 'A',
626
+			),
627
+			// Swatch Internet Time?!?
628
+			'B' => array(
629
+				'js'     => '',
630
+				'moment' => '',
631
+			),
632
+			//1...12
633
+			'g' => array(
634
+				'js'     => 'h',
635
+				'moment' => 'h',
636
+			),
637
+			//0...23
638
+			'G' => array(
639
+				'js'     => 'H',
640
+				'moment' => 'H',
641
+			),
642
+			//01...12
643
+			'h' => array(
644
+				'js'     => 'hh',
645
+				'moment' => 'hh',
646
+			),
647
+			//00...23
648
+			'H' => array(
649
+				'js'     => 'HH',
650
+				'moment' => 'HH',
651
+			),
652
+			//00..59
653
+			'i' => array(
654
+				'js'     => 'mm',
655
+				'moment' => 'mm',
656
+			),
657
+			//seconds... 00...59
658
+			's' => array(
659
+				'js'     => 'ss',
660
+				'moment' => 'ss',
661
+			),
662
+			//microseconds
663
+			'u' => array(
664
+				'js'     => '',
665
+				'moment' => '',
666
+			),
667
+		);
668
+		$jquery_ui_format     = '';
669
+		$moment_format        = '';
670
+		$escaping             = false;
671
+		$format_string_length = strlen($format_string);
672
+		for ($i = 0; $i < $format_string_length; $i++) {
673
+			$char = $format_string[ $i ];
674
+			if ($char === '\\') { // PHP date format escaping character
675
+				$i++;
676
+				if ($escaping) {
677
+					$jquery_ui_format .= $format_string[ $i ];
678
+					$moment_format    .= $format_string[ $i ];
679
+				} else {
680
+					$jquery_ui_format .= '\'' . $format_string[ $i ];
681
+					$moment_format    .= $format_string[ $i ];
682
+				}
683
+				$escaping = true;
684
+			} else {
685
+				if ($escaping) {
686
+					$jquery_ui_format .= "'";
687
+					$moment_format    .= "'";
688
+					$escaping         = false;
689
+				}
690
+				if (isset($symbols_map[ $char ])) {
691
+					$jquery_ui_format .= $symbols_map[ $char ]['js'];
692
+					$moment_format    .= $symbols_map[ $char ]['moment'];
693
+				} else {
694
+					$jquery_ui_format .= $char;
695
+					$moment_format    .= $char;
696
+				}
697
+			}
698
+		}
699
+		return array('js' => $jquery_ui_format, 'moment' => $moment_format);
700
+	}
701
+
702
+
703
+	/**
704
+	 * This takes an incoming format string and validates it to ensure it will work fine with PHP.
705
+	 *
706
+	 * @param string $format_string   Incoming format string for php date().
707
+	 * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
708
+	 *                                errors is returned.  So for client code calling, check for is_array() to
709
+	 *                                indicate failed validations.
710
+	 */
711
+	public static function validate_format_string($format_string)
712
+	{
713
+		$error_msg = array();
714
+		//time format checks
715
+		switch (true) {
716
+			case   strpos($format_string, 'h') !== false  :
717
+			case   strpos($format_string, 'g') !== false :
718
+				/**
719
+				 * if the time string has a lowercase 'h' which == 12 hour time format and there
720
+				 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
721
+				 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
722
+				 */
723
+				if (stripos($format_string, 'A') === false) {
724
+					$error_msg[] = esc_html__(
725
+						'There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
726
+						'event_espresso'
727
+					);
728
+				}
729
+				break;
730
+		}
731
+		return empty($error_msg) ? true : $error_msg;
732
+	}
733
+
734
+
735
+	/**
736
+	 *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
737
+	 *     very next day then this method will return true.
738
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
739
+	 *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
740
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
741
+	 *
742
+	 * @param mixed $date_1
743
+	 * @param mixed $date_2
744
+	 * @return bool
745
+	 */
746
+	public static function dates_represent_one_24_hour_date($date_1, $date_2)
747
+	{
748
+
749
+		if (
750
+			(! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime)
751
+			|| ($date_1->format(EE_Datetime_Field::mysql_time_format) !== '00:00:00'
752
+				|| $date_2->format(
753
+					EE_Datetime_Field::mysql_time_format
754
+				) !== '00:00:00')
755
+		) {
756
+			return false;
757
+		}
758
+		return $date_2->format('U') - $date_1->format('U') === 86400;
759
+	}
760
+
761
+
762
+	/**
763
+	 * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
764
+	 * Functions.
765
+	 *
766
+	 * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
767
+	 * @param string $field_for_interval The Database field that is the interval is applied to in the query.
768
+	 * @return string
769
+	 */
770
+	public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
771
+	{
772
+		try {
773
+			/** need to account for timezone offset on the selects */
774
+			$DateTimeZone = new DateTimeZone($timezone_string);
775
+		} catch (Exception $e) {
776
+			$DateTimeZone = null;
777
+		}
778
+		/**
779
+		 * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
780
+		 * Hence we do the calc for DateTimeZone::getOffset.
781
+		 */
782
+		$offset         = $DateTimeZone instanceof DateTimeZone
783
+			? $DateTimeZone->getOffset(new DateTime('now')) / HOUR_IN_SECONDS
784
+			: (float) get_option('gmt_offset');
785
+		$query_interval = $offset < 0
786
+			? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
787
+			: 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
788
+		return $query_interval;
789
+	}
790
+
791
+
792
+	/**
793
+	 * Retrieves the site's default timezone and returns it formatted so it's ready for display
794
+	 * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
795
+	 * and 'gmt_offset' WordPress options directly; or use the filter
796
+	 * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
797
+	 * (although note that we remove any HTML that may be added)
798
+	 *
799
+	 * @return string
800
+	 */
801
+	public static function get_timezone_string_for_display()
802
+	{
803
+		$pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
804
+		if (! empty($pretty_timezone)) {
805
+			return esc_html($pretty_timezone);
806
+		}
807
+		$timezone_string = get_option('timezone_string');
808
+		if ($timezone_string) {
809
+			static $mo_loaded = false;
810
+			// Load translations for continents and cities just like wp_timezone_choice does
811
+			if (! $mo_loaded) {
812
+				$locale = get_locale();
813
+				$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
814
+				load_textdomain('continents-cities', $mofile);
815
+				$mo_loaded = true;
816
+			}
817
+			//well that was easy.
818
+			$parts = explode('/', $timezone_string);
819
+			//remove the continent
820
+			unset($parts[0]);
821
+			$t_parts = array();
822
+			foreach ($parts as $part) {
823
+				$t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
824
+			}
825
+			return implode(' - ', $t_parts);
826
+		}
827
+		//they haven't set the timezone string, so let's return a string like "UTC+1"
828
+		$gmt_offset = get_option('gmt_offset');
829
+		$prefix     = (int) $gmt_offset >= 0 ? '+' : '';
830
+		$parts      = explode('.', (string) $gmt_offset);
831
+		if (count($parts) === 1) {
832
+			$parts[1] = '00';
833
+		} else {
834
+			//convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
835
+			//to minutes, eg 30 or 15, respectively
836
+			$hour_fraction = (float) ('0.' . $parts[1]);
837
+			$parts[1]      = (string) $hour_fraction * 60;
838
+		}
839
+		return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
840
+	}
841
+
842
+
843
+
844
+	/**
845
+	 * So PHP does this awesome thing where if you are trying to get a timestamp
846
+	 * for a month using a string like "February" or "February 2017",
847
+	 * and you don't specify a day as part of your string,
848
+	 * then PHP will use whatever the current day of the month is.
849
+	 * IF the current day of the month happens to be the 30th or 31st,
850
+	 * then PHP gets really confused by a date like February 30,
851
+	 * so instead of saying
852
+	 *      "Hey February only has 28 days (this year)...
853
+	 *      ...you must have meant the last day of the month!"
854
+	 * PHP does the next most logical thing, and bumps the date up to March 2nd,
855
+	 * because someone requesting February 30th obviously meant March 1st!
856
+	 * The way around this is to always set the day to the first,
857
+	 * so that the month will stay on the month you wanted.
858
+	 * this method will add that "1" into your date regardless of the format.
859
+	 *
860
+	 * @param string $month
861
+	 * @return string
862
+	 */
863
+	public static function first_of_month_timestamp($month = '')
864
+	{
865
+		$month = (string) $month;
866
+		$year  = '';
867
+		// check if the incoming string has a year in it or not
868
+		if (preg_match('/\b\d{4}\b/', $month, $matches)) {
869
+			$year = $matches[0];
870
+			// ten remove that from the month string as well as any spaces
871
+			$month = trim(str_replace($year, '', $month));
872
+			// add a space before the year
873
+			$year = " {$year}";
874
+		}
875
+		// return timestamp for something like "February 1 2017"
876
+		return strtotime("{$month} 1{$year}");
877
+	}
878
+
879
+
880
+	/**
881
+	 * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
882
+	 * for this sites timezone, but the timestamp could be some other time GMT.
883
+	 */
884
+	public static function tomorrow()
885
+	{
886
+		//The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive
887
+		//before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
888
+		//not an offset from midnight in UTC.  So if we're starting with UTC 00:00:00, then we want to make sure the
889
+		//final timestamp is equivalent to midnight in this timezone as represented in GMT.
890
+		return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1);
891
+	}
892
+
893
+
894
+	/**
895
+	 * **
896
+	 * Gives a nicely-formatted list of timezone strings.
897
+	 * Copied from the core wp function by the same name so we could customize to remove UTC offsets.
898
+	 *
899
+	 * @since     4.9.40.rc.008
900
+	 * @staticvar bool $mo_loaded
901
+	 * @staticvar string $locale_loaded
902
+	 * @param string $selected_zone Selected timezone.
903
+	 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
904
+	 * @return string
905
+	 */
906
+	public static function wp_timezone_choice($selected_zone, $locale = null)
907
+	{
908
+		static $mo_loaded = false, $locale_loaded = null;
909
+		$continents = array(
910
+			'Africa',
911
+			'America',
912
+			'Antarctica',
913
+			'Arctic',
914
+			'Asia',
915
+			'Atlantic',
916
+			'Australia',
917
+			'Europe',
918
+			'Indian',
919
+			'Pacific',
920
+		);
921
+		// Load translations for continents and cities.
922
+		if (! $mo_loaded || $locale !== $locale_loaded) {
923
+			$locale_loaded = $locale ? $locale : get_locale();
924
+			$mofile        = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
925
+			unload_textdomain('continents-cities');
926
+			load_textdomain('continents-cities', $mofile);
927
+			$mo_loaded = true;
928
+		}
929
+		$zone_data = array();
930
+		foreach (timezone_identifiers_list() as $zone) {
931
+			$zone = explode('/', $zone);
932
+			if (! in_array($zone[0], $continents, true)) {
933
+				continue;
934
+			}
935
+			// This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
936
+			$exists      = array(
937
+				0 => isset($zone[0]) && $zone[0],
938
+				1 => isset($zone[1]) && $zone[1],
939
+				2 => isset($zone[2]) && $zone[2],
940
+			);
941
+			$exists[3]   = $exists[0] && $zone[0] !== 'Etc';
942
+			$exists[4]   = $exists[1] && $exists[3];
943
+			$exists[5]   = $exists[2] && $exists[3];
944
+			$zone_data[] = array(
945
+				'continent'   => $exists[0] ? $zone[0] : '',
946
+				'city'        => $exists[1] ? $zone[1] : '',
947
+				'subcity'     => $exists[2] ? $zone[2] : '',
948
+				't_continent' => $exists[3]
949
+					? translate(str_replace('_', ' ', $zone[0]), 'continents-cities')
950
+					: '',
951
+				't_city'      => $exists[4]
952
+					? translate(str_replace('_', ' ', $zone[1]), 'continents-cities')
953
+					: '',
954
+				't_subcity'   => $exists[5]
955
+					? translate(str_replace('_', ' ', $zone[2]), 'continents-cities')
956
+					: '',
957
+			);
958
+		}
959
+		usort($zone_data, '_wp_timezone_choice_usort_callback');
960
+		$structure = array();
961
+		if (empty($selected_zone)) {
962
+			$structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
963
+		}
964
+		foreach ($zone_data as $key => $zone) {
965
+			// Build value in an array to join later
966
+			$value = array($zone['continent']);
967
+			if (empty($zone['city'])) {
968
+				// It's at the continent level (generally won't happen)
969
+				$display = $zone['t_continent'];
970
+			} else {
971
+				// It's inside a continent group
972
+				// Continent optgroup
973
+				if (! isset($zone_data[ $key - 1 ]) || $zone_data[ $key - 1 ]['continent'] !== $zone['continent']) {
974
+					$label       = $zone['t_continent'];
975
+					$structure[] = '<optgroup label="' . esc_attr($label) . '">';
976
+				}
977
+				// Add the city to the value
978
+				$value[] = $zone['city'];
979
+				$display = $zone['t_city'];
980
+				if (! empty($zone['subcity'])) {
981
+					// Add the subcity to the value
982
+					$value[] = $zone['subcity'];
983
+					$display .= ' - ' . $zone['t_subcity'];
984
+				}
985
+			}
986
+			// Build the value
987
+			$value       = implode('/', $value);
988
+			$selected    = $value === $selected_zone ? ' selected="selected"' : '';
989
+			$structure[] = '<option value="' . esc_attr($value) . '"' . $selected . '>'
990
+						   . esc_html($display)
991
+						   . '</option>';
992
+			// Close continent optgroup
993
+			if (! empty($zone['city'])
994
+				&& (
995
+					! isset($zone_data[ $key + 1 ])
996
+					|| (isset($zone_data[ $key + 1 ]) && $zone_data[ $key + 1 ]['continent'] !== $zone['continent'])
997
+				)
998
+			) {
999
+				$structure[] = '</optgroup>';
1000
+			}
1001
+		}
1002
+		return implode("\n", $structure);
1003
+	}
1004
+
1005
+
1006
+	/**
1007
+	 * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0
1008
+	 *
1009
+	 * @param int|WP_User $user_id
1010
+	 * @return string
1011
+	 */
1012
+	public static function get_user_locale($user_id = 0)
1013
+	{
1014
+		if (function_exists('get_user_locale')) {
1015
+			return get_user_locale($user_id);
1016
+		}
1017
+		return get_locale();
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Return the appropriate helper adapter for DTT related things.
1023
+	 *
1024
+	 * @return HelperInterface
1025
+	 * @throws InvalidArgumentException
1026
+	 * @throws InvalidDataTypeException
1027
+	 * @throws InvalidInterfaceException
1028
+	 */
1029
+	private static function getHelperAdapter() {
1030
+		$dtt_helper_fqcn = PHP_VERSION_ID < 50600
1031
+			? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper'
1032
+			: 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper';
1033
+		return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn);
1034
+	}
1035
+
1036
+
1037
+	/**
1038
+	 * Helper function for setting the timezone on a DateTime object.
1039
+	 * This is implemented to standardize a workaround for a PHP bug outlined in
1040
+	 * https://events.codebasehq.com/projects/event-espresso/tickets/11407 and
1041
+	 * https://events.codebasehq.com/projects/event-espresso/tickets/11233
1042
+	 *
1043
+	 * @param DateTime     $datetime
1044
+	 * @param DateTimeZone $timezone
1045
+	 */
1046
+	public static function setTimezone(DateTime $datetime, DateTimeZone $timezone)
1047
+	{
1048
+		$datetime->setTimezone($timezone);
1049
+		$datetime->getTimestamp();
1050
+	}
1051 1051
 }
1052 1052
\ No newline at end of file
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Indentation   +3722 added lines, -3722 removed lines patch added patch discarded remove patch
@@ -30,2339 +30,2339 @@  discard block
 block discarded – undo
30 30
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
31 31
 {
32 32
 
33
-    /**
34
-     * @var EE_Registration
35
-     */
36
-    private $_registration;
37
-
38
-    /**
39
-     * @var EE_Event
40
-     */
41
-    private $_reg_event;
42
-
43
-    /**
44
-     * @var EE_Session
45
-     */
46
-    private $_session;
47
-
48
-    private static $_reg_status;
49
-
50
-    /**
51
-     * Form for displaying the custom questions for this registration.
52
-     * This gets used a few times throughout the request so its best to cache it
53
-     *
54
-     * @var EE_Registration_Custom_Questions_Form
55
-     */
56
-    protected $_reg_custom_questions_form = null;
57
-
58
-
59
-    /**
60
-     *        constructor
61
-     *
62
-     * @Constructor
63
-     * @access public
64
-     * @param bool $routing
65
-     * @return Registrations_Admin_Page
66
-     */
67
-    public function __construct($routing = true)
68
-    {
69
-        parent::__construct($routing);
70
-        add_action('wp_loaded', array($this, 'wp_loaded'));
71
-    }
72
-
73
-
74
-    public function wp_loaded()
75
-    {
76
-        // when adding a new registration...
77
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78
-            EE_System::do_not_cache();
79
-            if (! isset($this->_req_data['processing_registration'])
80
-                 || absint($this->_req_data['processing_registration']) !== 1
81
-            ) {
82
-                // and it's NOT the attendee information reg step
83
-                // force cookie expiration by setting time to last week
84
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
85
-                // and update the global
86
-                $_COOKIE['ee_registration_added'] = 0;
87
-            }
88
-        }
89
-    }
90
-
91
-
92
-    protected function _init_page_props()
93
-    {
94
-        $this->page_slug        = REG_PG_SLUG;
95
-        $this->_admin_base_url  = REG_ADMIN_URL;
96
-        $this->_admin_base_path = REG_ADMIN;
97
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
98
-        $this->_cpt_routes      = array(
99
-            'add_new_attendee' => 'espresso_attendees',
100
-            'edit_attendee'    => 'espresso_attendees',
101
-            'insert_attendee'  => 'espresso_attendees',
102
-            'update_attendee'  => 'espresso_attendees',
103
-        );
104
-        $this->_cpt_model_names = array(
105
-            'add_new_attendee' => 'EEM_Attendee',
106
-            'edit_attendee'    => 'EEM_Attendee',
107
-        );
108
-        $this->_cpt_edit_routes = array(
109
-            'espresso_attendees' => 'edit_attendee',
110
-        );
111
-        $this->_pagenow_map     = array(
112
-            'add_new_attendee' => 'post-new.php',
113
-            'edit_attendee'    => 'post.php',
114
-            'trash'            => 'post.php',
115
-        );
116
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
117
-        //add filters so that the comment urls don't take users to a confusing 404 page
118
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
119
-    }
120
-
121
-
122
-    public function clear_comment_link($link, $comment, $args)
123
-    {
124
-        //gotta make sure this only happens on this route
125
-        $post_type = get_post_type($comment->comment_post_ID);
126
-        if ($post_type === 'espresso_attendees') {
127
-            return '#commentsdiv';
128
-        }
129
-        return $link;
130
-    }
131
-
132
-
133
-    protected function _ajax_hooks()
134
-    {
135
-        //todo: all hooks for registrations ajax goes in here
136
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
137
-    }
138
-
139
-
140
-    protected function _define_page_props()
141
-    {
142
-        $this->_admin_page_title = $this->page_label;
143
-        $this->_labels           = array(
144
-            'buttons'                      => array(
145
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
146
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
147
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
148
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
149
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
150
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
151
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
152
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
153
-            ),
154
-            'publishbox'                   => array(
155
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
156
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
157
-            ),
158
-            'hide_add_button_on_cpt_route' => array(
159
-                'edit_attendee' => true,
160
-            ),
161
-        );
162
-    }
163
-
164
-
165
-    /**
166
-     *        grab url requests and route them
167
-     *
168
-     * @access private
169
-     * @return void
170
-     */
171
-    public function _set_page_routes()
172
-    {
173
-        $this->_get_registration_status_array();
174
-        $reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175
-            ? $this->_req_data['_REG_ID'] : 0;
176
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
178
-            : $reg_id;
179
-        $att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
180
-            ? $this->_req_data['ATT_ID'] : 0;
181
-        $att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
182
-            ? $this->_req_data['post']
183
-            : $att_id;
184
-        $this->_page_routes = array(
185
-            'default'                            => array(
186
-                'func'       => '_registrations_overview_list_table',
187
-                'capability' => 'ee_read_registrations',
188
-            ),
189
-            'view_registration'                  => array(
190
-                'func'       => '_registration_details',
191
-                'capability' => 'ee_read_registration',
192
-                'obj_id'     => $reg_id,
193
-            ),
194
-            'edit_registration'                  => array(
195
-                'func'               => '_update_attendee_registration_form',
196
-                'noheader'           => true,
197
-                'headers_sent_route' => 'view_registration',
198
-                'capability'         => 'ee_edit_registration',
199
-                'obj_id'             => $reg_id,
200
-                '_REG_ID'            => $reg_id,
201
-            ),
202
-            'trash_registrations'                => array(
203
-                'func'       => '_trash_or_restore_registrations',
204
-                'args'       => array('trash' => true),
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'restore_registrations'              => array(
209
-                'func'       => '_trash_or_restore_registrations',
210
-                'args'       => array('trash' => false),
211
-                'noheader'   => true,
212
-                'capability' => 'ee_delete_registrations',
213
-            ),
214
-            'delete_registrations'               => array(
215
-                'func'       => '_delete_registrations',
216
-                'noheader'   => true,
217
-                'capability' => 'ee_delete_registrations',
218
-            ),
219
-            'new_registration'                   => array(
220
-                'func'       => 'new_registration',
221
-                'capability' => 'ee_edit_registrations',
222
-            ),
223
-            'process_reg_step'                   => array(
224
-                'func'       => 'process_reg_step',
225
-                'noheader'   => true,
226
-                'capability' => 'ee_edit_registrations',
227
-            ),
228
-            'redirect_to_txn'                    => array(
229
-                'func'       => 'redirect_to_txn',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registrations',
232
-            ),
233
-            'change_reg_status'                  => array(
234
-                'func'       => '_change_reg_status',
235
-                'noheader'   => true,
236
-                'capability' => 'ee_edit_registration',
237
-                'obj_id'     => $reg_id,
238
-            ),
239
-            'approve_registration'               => array(
240
-                'func'       => 'approve_registration',
241
-                'noheader'   => true,
242
-                'capability' => 'ee_edit_registration',
243
-                'obj_id'     => $reg_id,
244
-            ),
245
-            'approve_and_notify_registration'    => array(
246
-                'func'       => 'approve_registration',
247
-                'noheader'   => true,
248
-                'args'       => array(true),
249
-                'capability' => 'ee_edit_registration',
250
-                'obj_id'     => $reg_id,
251
-            ),
252
-            'approve_registrations'               => array(
253
-                'func'       => 'bulk_action_on_registrations',
254
-                'noheader'   => true,
255
-                'capability' => 'ee_edit_registrations',
256
-                'args' => array('approve')
257
-            ),
258
-            'approve_and_notify_registrations'               => array(
259
-                'func'       => 'bulk_action_on_registrations',
260
-                'noheader'   => true,
261
-                'capability' => 'ee_edit_registrations',
262
-                'args' => array('approve', true)
263
-            ),
264
-            'decline_registration'               => array(
265
-                'func'       => 'decline_registration',
266
-                'noheader'   => true,
267
-                'capability' => 'ee_edit_registration',
268
-                'obj_id'     => $reg_id,
269
-            ),
270
-            'decline_and_notify_registration'    => array(
271
-                'func'       => 'decline_registration',
272
-                'noheader'   => true,
273
-                'args'       => array(true),
274
-                'capability' => 'ee_edit_registration',
275
-                'obj_id'     => $reg_id,
276
-            ),
277
-            'decline_registrations'               => array(
278
-                'func'       => 'bulk_action_on_registrations',
279
-                'noheader'   => true,
280
-                'capability' => 'ee_edit_registrations',
281
-                'args' => array('decline')
282
-            ),
283
-            'decline_and_notify_registrations'    => array(
284
-                'func'       => 'bulk_action_on_registrations',
285
-                'noheader'   => true,
286
-                'capability' => 'ee_edit_registrations',
287
-                'args' => array('decline', true)
288
-            ),
289
-            'pending_registration'               => array(
290
-                'func'       => 'pending_registration',
291
-                'noheader'   => true,
292
-                'capability' => 'ee_edit_registration',
293
-                'obj_id'     => $reg_id,
294
-            ),
295
-            'pending_and_notify_registration'    => array(
296
-                'func'       => 'pending_registration',
297
-                'noheader'   => true,
298
-                'args'       => array(true),
299
-                'capability' => 'ee_edit_registration',
300
-                'obj_id'     => $reg_id,
301
-            ),
302
-            'pending_registrations'               => array(
303
-                'func'       => 'bulk_action_on_registrations',
304
-                'noheader'   => true,
305
-                'capability' => 'ee_edit_registrations',
306
-                'args' => array('pending')
307
-            ),
308
-            'pending_and_notify_registrations'    => array(
309
-                'func'       => 'bulk_action_on_registrations',
310
-                'noheader'   => true,
311
-                'capability' => 'ee_edit_registrations',
312
-                'args' => array('pending', true)
313
-            ),
314
-            'no_approve_registration'            => array(
315
-                'func'       => 'not_approve_registration',
316
-                'noheader'   => true,
317
-                'capability' => 'ee_edit_registration',
318
-                'obj_id'     => $reg_id,
319
-            ),
320
-            'no_approve_and_notify_registration' => array(
321
-                'func'       => 'not_approve_registration',
322
-                'noheader'   => true,
323
-                'args'       => array(true),
324
-                'capability' => 'ee_edit_registration',
325
-                'obj_id'     => $reg_id,
326
-            ),
327
-            'no_approve_registrations'            => array(
328
-                'func'       => 'bulk_action_on_registrations',
329
-                'noheader'   => true,
330
-                'capability' => 'ee_edit_registrations',
331
-                'args' => array('not_approve')
332
-            ),
333
-            'no_approve_and_notify_registrations' => array(
334
-                'func'       => 'bulk_action_on_registrations',
335
-                'noheader'   => true,
336
-                'capability' => 'ee_edit_registrations',
337
-                'args' => array('not_approve', true)
338
-            ),
339
-            'cancel_registration'                => array(
340
-                'func'       => 'cancel_registration',
341
-                'noheader'   => true,
342
-                'capability' => 'ee_edit_registration',
343
-                'obj_id'     => $reg_id,
344
-            ),
345
-            'cancel_and_notify_registration'     => array(
346
-                'func'       => 'cancel_registration',
347
-                'noheader'   => true,
348
-                'args'       => array(true),
349
-                'capability' => 'ee_edit_registration',
350
-                'obj_id'     => $reg_id,
351
-            ),
352
-            'cancel_registrations'                => array(
353
-                'func'       => 'bulk_action_on_registrations',
354
-                'noheader'   => true,
355
-                'capability' => 'ee_edit_registrations',
356
-                'args' => array('cancel')
357
-            ),
358
-            'cancel_and_notify_registrations'     => array(
359
-                'func'       => 'bulk_action_on_registrations',
360
-                'noheader'   => true,
361
-                'capability' => 'ee_edit_registrations',
362
-                'args' => array('cancel', true)
363
-            ),
364
-            'wait_list_registration' => array(
365
-                'func'       => 'wait_list_registration',
366
-                'noheader'   => true,
367
-                'capability' => 'ee_edit_registration',
368
-                'obj_id'     => $reg_id,
369
-            ),
370
-            'wait_list_and_notify_registration' => array(
371
-                'func'       => 'wait_list_registration',
372
-                'noheader'   => true,
373
-                'args'       => array(true),
374
-                'capability' => 'ee_edit_registration',
375
-                'obj_id'     => $reg_id,
376
-            ),
377
-            'contact_list'                       => array(
378
-                'func'       => '_attendee_contact_list_table',
379
-                'capability' => 'ee_read_contacts',
380
-            ),
381
-            'add_new_attendee'                   => array(
382
-                'func' => '_create_new_cpt_item',
383
-                'args' => array(
384
-                    'new_attendee' => true,
385
-                    'capability'   => 'ee_edit_contacts',
386
-                ),
387
-            ),
388
-            'edit_attendee'                      => array(
389
-                'func'       => '_edit_cpt_item',
390
-                'capability' => 'ee_edit_contacts',
391
-                'obj_id'     => $att_id,
392
-            ),
393
-            'duplicate_attendee'                 => array(
394
-                'func'       => '_duplicate_attendee',
395
-                'noheader'   => true,
396
-                'capability' => 'ee_edit_contacts',
397
-                'obj_id'     => $att_id,
398
-            ),
399
-            'insert_attendee'                    => array(
400
-                'func'       => '_insert_or_update_attendee',
401
-                'args'       => array(
402
-                    'new_attendee' => true,
403
-                ),
404
-                'noheader'   => true,
405
-                'capability' => 'ee_edit_contacts',
406
-            ),
407
-            'update_attendee'                    => array(
408
-                'func'       => '_insert_or_update_attendee',
409
-                'args'       => array(
410
-                    'new_attendee' => false,
411
-                ),
412
-                'noheader'   => true,
413
-                'capability' => 'ee_edit_contacts',
414
-                'obj_id'     => $att_id,
415
-            ),
416
-            'trash_attendees' => array(
417
-                'func' => '_trash_or_restore_attendees',
418
-                'args' => array(
419
-                    'trash' => 'true'
420
-                ),
421
-                'noheader' => true,
422
-                'capability' => 'ee_delete_contacts'
423
-            ),
424
-            'trash_attendee'                    => array(
425
-                'func'       => '_trash_or_restore_attendees',
426
-                'args'       => array(
427
-                    'trash' => true,
428
-                ),
429
-                'noheader'   => true,
430
-                'capability' => 'ee_delete_contacts',
431
-                'obj_id'     => $att_id,
432
-            ),
433
-            'restore_attendees'                  => array(
434
-                'func'       => '_trash_or_restore_attendees',
435
-                'args'       => array(
436
-                    'trash' => false,
437
-                ),
438
-                'noheader'   => true,
439
-                'capability' => 'ee_delete_contacts',
440
-                'obj_id'     => $att_id,
441
-            ),
442
-            'resend_registration'                => array(
443
-                'func'       => '_resend_registration',
444
-                'noheader'   => true,
445
-                'capability' => 'ee_send_message',
446
-            ),
447
-            'registrations_report'               => array(
448
-                'func'       => '_registrations_report',
449
-                'noheader'   => true,
450
-                'capability' => 'ee_read_registrations',
451
-            ),
452
-            'contact_list_export'                => array(
453
-                'func'       => '_contact_list_export',
454
-                'noheader'   => true,
455
-                'capability' => 'export',
456
-            ),
457
-            'contact_list_report'                => array(
458
-                'func'       => '_contact_list_report',
459
-                'noheader'   => true,
460
-                'capability' => 'ee_read_contacts',
461
-            ),
462
-        );
463
-    }
464
-
465
-
466
-    protected function _set_page_config()
467
-    {
468
-        $this->_page_config = array(
469
-            'default'           => array(
470
-                'nav'           => array(
471
-                    'label' => esc_html__('Overview', 'event_espresso'),
472
-                    'order' => 5,
473
-                ),
474
-                'help_tabs'     => array(
475
-                    'registrations_overview_help_tab'                       => array(
476
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
477
-                        'filename' => 'registrations_overview',
478
-                    ),
479
-                    'registrations_overview_table_column_headings_help_tab' => array(
480
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
481
-                        'filename' => 'registrations_overview_table_column_headings',
482
-                    ),
483
-                    'registrations_overview_filters_help_tab'               => array(
484
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
485
-                        'filename' => 'registrations_overview_filters',
486
-                    ),
487
-                    'registrations_overview_views_help_tab'                 => array(
488
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
489
-                        'filename' => 'registrations_overview_views',
490
-                    ),
491
-                    'registrations_regoverview_other_help_tab'              => array(
492
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
493
-                        'filename' => 'registrations_overview_other',
494
-                    ),
495
-                ),
496
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
497
-                'qtips'         => array('Registration_List_Table_Tips'),
498
-                'list_table'    => 'EE_Registrations_List_Table',
499
-                'require_nonce' => false,
500
-            ),
501
-            'view_registration' => array(
502
-                'nav'           => array(
503
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
504
-                    'order'      => 15,
505
-                    'url'        => isset($this->_req_data['_REG_ID'])
506
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
507
-                        : $this->_admin_base_url,
508
-                    'persistent' => false,
509
-                ),
510
-                'help_tabs'     => array(
511
-                    'registrations_details_help_tab'                    => array(
512
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
513
-                        'filename' => 'registrations_details',
514
-                    ),
515
-                    'registrations_details_table_help_tab'              => array(
516
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
517
-                        'filename' => 'registrations_details_table',
518
-                    ),
519
-                    'registrations_details_form_answers_help_tab'       => array(
520
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
521
-                        'filename' => 'registrations_details_form_answers',
522
-                    ),
523
-                    'registrations_details_registrant_details_help_tab' => array(
524
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
525
-                        'filename' => 'registrations_details_registrant_details',
526
-                    ),
527
-                ),
528
-                'help_tour'     => array('Registration_Details_Help_Tour'),
529
-                'metaboxes'     => array_merge(
530
-                    $this->_default_espresso_metaboxes,
531
-                    array('_registration_details_metaboxes')
532
-                ),
533
-                'require_nonce' => false,
534
-            ),
535
-            'new_registration'  => array(
536
-                'nav'           => array(
537
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
538
-                    'url'        => '#',
539
-                    'order'      => 15,
540
-                    'persistent' => false,
541
-                ),
542
-                'metaboxes'     => $this->_default_espresso_metaboxes,
543
-                'labels'        => array(
544
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
545
-                ),
546
-                'require_nonce' => false,
547
-            ),
548
-            'add_new_attendee'  => array(
549
-                'nav'           => array(
550
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
551
-                    'order'      => 15,
552
-                    'persistent' => false,
553
-                ),
554
-                'metaboxes'     => array_merge(
555
-                    $this->_default_espresso_metaboxes,
556
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
557
-                ),
558
-                'require_nonce' => false,
559
-            ),
560
-            'edit_attendee'     => array(
561
-                'nav'           => array(
562
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
563
-                    'order'      => 15,
564
-                    'persistent' => false,
565
-                    'url'        => isset($this->_req_data['ATT_ID'])
566
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
567
-                        : $this->_admin_base_url,
568
-                ),
569
-                'metaboxes'     => array('attendee_editor_metaboxes'),
570
-                'require_nonce' => false,
571
-            ),
572
-            'contact_list'      => array(
573
-                'nav'           => array(
574
-                    'label' => esc_html__('Contact List', 'event_espresso'),
575
-                    'order' => 20,
576
-                ),
577
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
578
-                'help_tabs'     => array(
579
-                    'registrations_contact_list_help_tab'                       => array(
580
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
581
-                        'filename' => 'registrations_contact_list',
582
-                    ),
583
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
584
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
585
-                        'filename' => 'registrations_contact_list_table_column_headings',
586
-                    ),
587
-                    'registrations_contact_list_views_help_tab'                 => array(
588
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
589
-                        'filename' => 'registrations_contact_list_views',
590
-                    ),
591
-                    'registrations_contact_list_other_help_tab'                 => array(
592
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
593
-                        'filename' => 'registrations_contact_list_other',
594
-                    ),
595
-                ),
596
-                'help_tour'     => array('Contact_List_Help_Tour'),
597
-                'metaboxes'     => array(),
598
-                'require_nonce' => false,
599
-            ),
600
-            //override default cpt routes
601
-            'create_new'        => '',
602
-            'edit'              => '',
603
-        );
604
-    }
605
-
606
-
607
-    /**
608
-     * The below methods aren't used by this class currently
609
-     */
610
-    protected function _add_screen_options()
611
-    {
612
-    }
613
-
614
-
615
-    protected function _add_feature_pointers()
616
-    {
617
-    }
618
-
619
-
620
-    public function admin_init()
621
-    {
622
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
623
-            'click "Update Registration Questions" to save your changes',
624
-            'event_espresso'
625
-        );
626
-    }
627
-
628
-
629
-    public function admin_notices()
630
-    {
631
-    }
632
-
633
-
634
-    public function admin_footer_scripts()
635
-    {
636
-    }
637
-
638
-
639
-    /**
640
-     *        get list of registration statuses
641
-     *
642
-     * @access private
643
-     * @return void
644
-     * @throws EE_Error
645
-     */
646
-    private function _get_registration_status_array()
647
-    {
648
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
649
-    }
650
-
651
-
652
-    protected function _add_screen_options_default()
653
-    {
654
-        $this->_per_page_screen_option();
655
-    }
656
-
657
-
658
-    protected function _add_screen_options_contact_list()
659
-    {
660
-        $page_title              = $this->_admin_page_title;
661
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
662
-        $this->_per_page_screen_option();
663
-        $this->_admin_page_title = $page_title;
664
-    }
665
-
666
-
667
-    public function load_scripts_styles()
668
-    {
669
-        //style
670
-        wp_register_style(
671
-            'espresso_reg',
672
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
673
-            array('ee-admin-css'),
674
-            EVENT_ESPRESSO_VERSION
675
-        );
676
-        wp_enqueue_style('espresso_reg');
677
-        //script
678
-        wp_register_script(
679
-            'espresso_reg',
680
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
681
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682
-            EVENT_ESPRESSO_VERSION,
683
-            true
684
-        );
685
-        wp_enqueue_script('espresso_reg');
686
-    }
687
-
688
-
689
-    public function load_scripts_styles_edit_attendee()
690
-    {
691
-        //stuff to only show up on our attendee edit details page.
692
-        $attendee_details_translations = array(
693
-            'att_publish_text' => sprintf(
694
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
695
-                $this->_cpt_model_obj->get_datetime('ATT_created')
696
-            ),
697
-        );
698
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
699
-        wp_enqueue_script('jquery-validate');
700
-    }
701
-
702
-
703
-    public function load_scripts_styles_view_registration()
704
-    {
705
-        //styles
706
-        wp_enqueue_style('espresso-ui-theme');
707
-        //scripts
708
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
709
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
710
-    }
711
-
712
-
713
-    public function load_scripts_styles_contact_list()
714
-    {
715
-        wp_dequeue_style('espresso_reg');
716
-        wp_register_style(
717
-            'espresso_att',
718
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
719
-            array('ee-admin-css'),
720
-            EVENT_ESPRESSO_VERSION
721
-        );
722
-        wp_enqueue_style('espresso_att');
723
-    }
724
-
725
-
726
-    public function load_scripts_styles_new_registration()
727
-    {
728
-        wp_register_script(
729
-            'ee-spco-for-admin',
730
-            REG_ASSETS_URL . 'spco_for_admin.js',
731
-            array('underscore', 'jquery'),
732
-            EVENT_ESPRESSO_VERSION,
733
-            true
734
-        );
735
-        wp_enqueue_script('ee-spco-for-admin');
736
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
737
-        EE_Form_Section_Proper::wp_enqueue_scripts();
738
-        EED_Ticket_Selector::load_tckt_slctr_assets();
739
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
740
-    }
741
-
742
-
743
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
744
-    {
745
-        add_filter('FHEE_load_EE_messages', '__return_true');
746
-    }
747
-
748
-
749
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
750
-    {
751
-        add_filter('FHEE_load_EE_messages', '__return_true');
752
-    }
753
-
754
-
755
-    protected function _set_list_table_views_default()
756
-    {
757
-        //for notification related bulk actions we need to make sure only active messengers have an option.
758
-        EED_Messages::set_autoloaders();
759
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
760
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
761
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
762
-        //key= bulk_action_slug, value= message type.
763
-        $match_array = array(
764
-            'approve_registrations'    => 'registration',
765
-            'decline_registrations'    => 'declined_registration',
766
-            'pending_registrations'    => 'pending_approval',
767
-            'no_approve_registrations' => 'not_approved_registration',
768
-            'cancel_registrations'     => 'cancelled_registration',
769
-        );
770
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
771
-            'ee_send_message',
772
-            'batch_send_messages'
773
-        );
774
-        /** setup reg status bulk actions **/
775
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
776
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
777
-                $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
778
-                    'Approve and Notify Registrations',
779
-                    'event_espresso'
780
-                );
781
-        }
782
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
783
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
784
-                $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
785
-                    'Decline and Notify Registrations',
786
-                    'event_espresso'
787
-                );
788
-        }
789
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
790
-            'Set Registrations to Pending Payment',
791
-            'event_espresso'
792
-        );
793
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
794
-                $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
795
-                    'Set Registrations to Pending Payment and Notify',
796
-                    'event_espresso'
797
-                );
798
-        }
799
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
800
-            'Set Registrations to Not Approved',
801
-            'event_espresso'
802
-        );
803
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
804
-                $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
805
-                    'Set Registrations to Not Approved and Notify',
806
-                    'event_espresso'
807
-                );
808
-        }
809
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
810
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
811
-                $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
812
-                    'Cancel Registrations and Notify',
813
-                    'event_espresso'
814
-                );
815
-        }
816
-        $def_reg_status_actions = apply_filters(
817
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
818
-            $def_reg_status_actions,
819
-            $active_mts,
820
-            $can_send
821
-        );
822
-
823
-        $this->_views = array(
824
-            'all'   => array(
825
-                'slug'        => 'all',
826
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge($def_reg_status_actions, array(
829
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
830
-                )),
831
-            ),
832
-            'month' => array(
833
-                'slug'        => 'month',
834
-                'label'       => esc_html__('This Month', 'event_espresso'),
835
-                'count'       => 0,
836
-                'bulk_action' => array_merge($def_reg_status_actions, array(
837
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
838
-                )),
839
-            ),
840
-            'today' => array(
841
-                'slug'        => 'today',
842
-                'label'       => sprintf(
843
-                    esc_html__('Today - %s', 'event_espresso'),
844
-                    date('M d, Y', current_time('timestamp'))
845
-                ),
846
-                'count'       => 0,
847
-                'bulk_action' => array_merge($def_reg_status_actions, array(
848
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
849
-                )),
850
-            ),
851
-        );
852
-        if (EE_Registry::instance()->CAP->current_user_can(
853
-            'ee_delete_registrations',
854
-            'espresso_registrations_delete_registration'
855
-        )) {
856
-            $this->_views['incomplete'] = array(
857
-                'slug'        => 'incomplete',
858
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
859
-                'count'       => 0,
860
-                'bulk_action' => array(
861
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862
-                ),
863
-            );
864
-            $this->_views['trash']      = array(
865
-                'slug'        => 'trash',
866
-                'label'       => esc_html__('Trash', 'event_espresso'),
867
-                'count'       => 0,
868
-                'bulk_action' => array(
869
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
870
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
871
-                ),
872
-            );
873
-        }
874
-    }
875
-
876
-
877
-    protected function _set_list_table_views_contact_list()
878
-    {
879
-        $this->_views = array(
880
-            'in_use' => array(
881
-                'slug'        => 'in_use',
882
-                'label'       => esc_html__('In Use', 'event_espresso'),
883
-                'count'       => 0,
884
-                'bulk_action' => array(
885
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
886
-                ),
887
-            ),
888
-        );
889
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
890
-            'espresso_registrations_trash_attendees')
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = !empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post' => $ATT_ID
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                        . EE_Admin_Page::add_query_args_and_nonce(
1070
-                            array(
1071
-                                'action' => 'edit',
1072
-                                'post'   => $event->ID(),
1073
-                            ),
1074
-                            EVENTS_ADMIN_URL
1075
-                        )
1076
-                        . '">&nbsp;'
1077
-                        . $event->get('EVT_name')
1078
-                        . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        //get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG    = EEM_Registration::instance();
1119
-        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1166
-         * @see EEM_Base::get_all()
1167
-         */
1168
-        $query_params['group_by'] = '';
1169
-
1170
-        return $count
1171
-            ? EEM_Registration::instance()->count($query_params)
1172
-            /** @type EE_Registration[] */
1173
-            : EEM_Registration::instance()->get_all($query_params);
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1179
-     * Note: this listens to values on the request for some of the query parameters.
1180
-     *
1181
-     * @param array $request
1182
-     * @param int   $per_page
1183
-     * @param bool  $count
1184
-     * @return array
1185
-     * @throws EE_Error
1186
-     */
1187
-    protected function _get_registration_query_parameters(
1188
-        $request = array(),
1189
-        $per_page = 10,
1190
-        $count = false
1191
-    ) {
1192
-
1193
-        $query_params = array(
1194
-            0                          => $this->_get_where_conditions_for_registrations_query(
1195
-                $request
1196
-            ),
1197
-            'caps'                     => EEM_Registration::caps_read_admin,
1198
-            'default_where_conditions' => 'this_model_only',
1199
-        );
1200
-        if (! $count) {
1201
-            $query_params = array_merge(
1202
-                $query_params,
1203
-                $this->_get_orderby_for_registrations_query(),
1204
-                $this->_get_limit($per_page)
1205
-            );
1206
-        }
1207
-
1208
-        return $query_params;
1209
-    }
1210
-
1211
-
1212
-    /**
1213
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1214
-     *
1215
-     * @param array $request usually the same as $this->_req_data but not necessarily
1216
-     * @return array
1217
-     */
1218
-    protected function addAttendeeIdToWhereConditions(array $request)
1219
-    {
1220
-        $where = array();
1221
-        if (! empty($request['ATT_ID'])) {
1222
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1223
-        }
1224
-        return $where;
1225
-    }
1226
-
1227
-
1228
-    /**
1229
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1230
-     *
1231
-     * @param array $request usually the same as $this->_req_data but not necessarily
1232
-     * @return array
1233
-     */
1234
-    protected function _add_event_id_to_where_conditions(array $request)
1235
-    {
1236
-        $where = array();
1237
-        if (! empty($request['event_id'])) {
1238
-            $where['EVT_ID'] = absint($request['event_id']);
1239
-        }
1240
-        return $where;
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1246
-     *
1247
-     * @param array $request usually the same as $this->_req_data but not necessarily
1248
-     * @return array
1249
-     */
1250
-    protected function _add_category_id_to_where_conditions(array $request)
1251
-    {
1252
-        $where = array();
1253
-        if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1254
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255
-        }
1256
-        return $where;
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1262
-     *
1263
-     * @param array $request usually the same as $this->_req_data but not necessarily
1264
-     * @return array
1265
-     */
1266
-    protected function _add_datetime_id_to_where_conditions(array $request)
1267
-    {
1268
-        $where = array();
1269
-        if (! empty($request['datetime_id'])) {
1270
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271
-        }
1272
-        if (! empty($request['DTT_ID'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274
-        }
1275
-        return $where;
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * Adds the correct registration status to the where conditions for the registrations query.
1281
-     *
1282
-     * @param array $request usually the same as $this->_req_data but not necessarily
1283
-     * @return array
1284
-     */
1285
-    protected function _add_registration_status_to_where_conditions(array $request)
1286
-    {
1287
-        $where = array();
1288
-        $view = EEH_Array::is_set($request, 'status', '');
1289
-        $registration_status = ! empty($request['_reg_status'])
1290
-            ? sanitize_text_field($request['_reg_status'])
1291
-            : '';
1292
-
1293
-        /*
33
+	/**
34
+	 * @var EE_Registration
35
+	 */
36
+	private $_registration;
37
+
38
+	/**
39
+	 * @var EE_Event
40
+	 */
41
+	private $_reg_event;
42
+
43
+	/**
44
+	 * @var EE_Session
45
+	 */
46
+	private $_session;
47
+
48
+	private static $_reg_status;
49
+
50
+	/**
51
+	 * Form for displaying the custom questions for this registration.
52
+	 * This gets used a few times throughout the request so its best to cache it
53
+	 *
54
+	 * @var EE_Registration_Custom_Questions_Form
55
+	 */
56
+	protected $_reg_custom_questions_form = null;
57
+
58
+
59
+	/**
60
+	 *        constructor
61
+	 *
62
+	 * @Constructor
63
+	 * @access public
64
+	 * @param bool $routing
65
+	 * @return Registrations_Admin_Page
66
+	 */
67
+	public function __construct($routing = true)
68
+	{
69
+		parent::__construct($routing);
70
+		add_action('wp_loaded', array($this, 'wp_loaded'));
71
+	}
72
+
73
+
74
+	public function wp_loaded()
75
+	{
76
+		// when adding a new registration...
77
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78
+			EE_System::do_not_cache();
79
+			if (! isset($this->_req_data['processing_registration'])
80
+				 || absint($this->_req_data['processing_registration']) !== 1
81
+			) {
82
+				// and it's NOT the attendee information reg step
83
+				// force cookie expiration by setting time to last week
84
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
85
+				// and update the global
86
+				$_COOKIE['ee_registration_added'] = 0;
87
+			}
88
+		}
89
+	}
90
+
91
+
92
+	protected function _init_page_props()
93
+	{
94
+		$this->page_slug        = REG_PG_SLUG;
95
+		$this->_admin_base_url  = REG_ADMIN_URL;
96
+		$this->_admin_base_path = REG_ADMIN;
97
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
98
+		$this->_cpt_routes      = array(
99
+			'add_new_attendee' => 'espresso_attendees',
100
+			'edit_attendee'    => 'espresso_attendees',
101
+			'insert_attendee'  => 'espresso_attendees',
102
+			'update_attendee'  => 'espresso_attendees',
103
+		);
104
+		$this->_cpt_model_names = array(
105
+			'add_new_attendee' => 'EEM_Attendee',
106
+			'edit_attendee'    => 'EEM_Attendee',
107
+		);
108
+		$this->_cpt_edit_routes = array(
109
+			'espresso_attendees' => 'edit_attendee',
110
+		);
111
+		$this->_pagenow_map     = array(
112
+			'add_new_attendee' => 'post-new.php',
113
+			'edit_attendee'    => 'post.php',
114
+			'trash'            => 'post.php',
115
+		);
116
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
117
+		//add filters so that the comment urls don't take users to a confusing 404 page
118
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
119
+	}
120
+
121
+
122
+	public function clear_comment_link($link, $comment, $args)
123
+	{
124
+		//gotta make sure this only happens on this route
125
+		$post_type = get_post_type($comment->comment_post_ID);
126
+		if ($post_type === 'espresso_attendees') {
127
+			return '#commentsdiv';
128
+		}
129
+		return $link;
130
+	}
131
+
132
+
133
+	protected function _ajax_hooks()
134
+	{
135
+		//todo: all hooks for registrations ajax goes in here
136
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
137
+	}
138
+
139
+
140
+	protected function _define_page_props()
141
+	{
142
+		$this->_admin_page_title = $this->page_label;
143
+		$this->_labels           = array(
144
+			'buttons'                      => array(
145
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
146
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
147
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
148
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
149
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
150
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
151
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
152
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
153
+			),
154
+			'publishbox'                   => array(
155
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
156
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
157
+			),
158
+			'hide_add_button_on_cpt_route' => array(
159
+				'edit_attendee' => true,
160
+			),
161
+		);
162
+	}
163
+
164
+
165
+	/**
166
+	 *        grab url requests and route them
167
+	 *
168
+	 * @access private
169
+	 * @return void
170
+	 */
171
+	public function _set_page_routes()
172
+	{
173
+		$this->_get_registration_status_array();
174
+		$reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175
+			? $this->_req_data['_REG_ID'] : 0;
176
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177
+			? $this->_req_data['reg_status_change_form']['REG_ID']
178
+			: $reg_id;
179
+		$att_id             = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
180
+			? $this->_req_data['ATT_ID'] : 0;
181
+		$att_id             = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
182
+			? $this->_req_data['post']
183
+			: $att_id;
184
+		$this->_page_routes = array(
185
+			'default'                            => array(
186
+				'func'       => '_registrations_overview_list_table',
187
+				'capability' => 'ee_read_registrations',
188
+			),
189
+			'view_registration'                  => array(
190
+				'func'       => '_registration_details',
191
+				'capability' => 'ee_read_registration',
192
+				'obj_id'     => $reg_id,
193
+			),
194
+			'edit_registration'                  => array(
195
+				'func'               => '_update_attendee_registration_form',
196
+				'noheader'           => true,
197
+				'headers_sent_route' => 'view_registration',
198
+				'capability'         => 'ee_edit_registration',
199
+				'obj_id'             => $reg_id,
200
+				'_REG_ID'            => $reg_id,
201
+			),
202
+			'trash_registrations'                => array(
203
+				'func'       => '_trash_or_restore_registrations',
204
+				'args'       => array('trash' => true),
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'restore_registrations'              => array(
209
+				'func'       => '_trash_or_restore_registrations',
210
+				'args'       => array('trash' => false),
211
+				'noheader'   => true,
212
+				'capability' => 'ee_delete_registrations',
213
+			),
214
+			'delete_registrations'               => array(
215
+				'func'       => '_delete_registrations',
216
+				'noheader'   => true,
217
+				'capability' => 'ee_delete_registrations',
218
+			),
219
+			'new_registration'                   => array(
220
+				'func'       => 'new_registration',
221
+				'capability' => 'ee_edit_registrations',
222
+			),
223
+			'process_reg_step'                   => array(
224
+				'func'       => 'process_reg_step',
225
+				'noheader'   => true,
226
+				'capability' => 'ee_edit_registrations',
227
+			),
228
+			'redirect_to_txn'                    => array(
229
+				'func'       => 'redirect_to_txn',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registrations',
232
+			),
233
+			'change_reg_status'                  => array(
234
+				'func'       => '_change_reg_status',
235
+				'noheader'   => true,
236
+				'capability' => 'ee_edit_registration',
237
+				'obj_id'     => $reg_id,
238
+			),
239
+			'approve_registration'               => array(
240
+				'func'       => 'approve_registration',
241
+				'noheader'   => true,
242
+				'capability' => 'ee_edit_registration',
243
+				'obj_id'     => $reg_id,
244
+			),
245
+			'approve_and_notify_registration'    => array(
246
+				'func'       => 'approve_registration',
247
+				'noheader'   => true,
248
+				'args'       => array(true),
249
+				'capability' => 'ee_edit_registration',
250
+				'obj_id'     => $reg_id,
251
+			),
252
+			'approve_registrations'               => array(
253
+				'func'       => 'bulk_action_on_registrations',
254
+				'noheader'   => true,
255
+				'capability' => 'ee_edit_registrations',
256
+				'args' => array('approve')
257
+			),
258
+			'approve_and_notify_registrations'               => array(
259
+				'func'       => 'bulk_action_on_registrations',
260
+				'noheader'   => true,
261
+				'capability' => 'ee_edit_registrations',
262
+				'args' => array('approve', true)
263
+			),
264
+			'decline_registration'               => array(
265
+				'func'       => 'decline_registration',
266
+				'noheader'   => true,
267
+				'capability' => 'ee_edit_registration',
268
+				'obj_id'     => $reg_id,
269
+			),
270
+			'decline_and_notify_registration'    => array(
271
+				'func'       => 'decline_registration',
272
+				'noheader'   => true,
273
+				'args'       => array(true),
274
+				'capability' => 'ee_edit_registration',
275
+				'obj_id'     => $reg_id,
276
+			),
277
+			'decline_registrations'               => array(
278
+				'func'       => 'bulk_action_on_registrations',
279
+				'noheader'   => true,
280
+				'capability' => 'ee_edit_registrations',
281
+				'args' => array('decline')
282
+			),
283
+			'decline_and_notify_registrations'    => array(
284
+				'func'       => 'bulk_action_on_registrations',
285
+				'noheader'   => true,
286
+				'capability' => 'ee_edit_registrations',
287
+				'args' => array('decline', true)
288
+			),
289
+			'pending_registration'               => array(
290
+				'func'       => 'pending_registration',
291
+				'noheader'   => true,
292
+				'capability' => 'ee_edit_registration',
293
+				'obj_id'     => $reg_id,
294
+			),
295
+			'pending_and_notify_registration'    => array(
296
+				'func'       => 'pending_registration',
297
+				'noheader'   => true,
298
+				'args'       => array(true),
299
+				'capability' => 'ee_edit_registration',
300
+				'obj_id'     => $reg_id,
301
+			),
302
+			'pending_registrations'               => array(
303
+				'func'       => 'bulk_action_on_registrations',
304
+				'noheader'   => true,
305
+				'capability' => 'ee_edit_registrations',
306
+				'args' => array('pending')
307
+			),
308
+			'pending_and_notify_registrations'    => array(
309
+				'func'       => 'bulk_action_on_registrations',
310
+				'noheader'   => true,
311
+				'capability' => 'ee_edit_registrations',
312
+				'args' => array('pending', true)
313
+			),
314
+			'no_approve_registration'            => array(
315
+				'func'       => 'not_approve_registration',
316
+				'noheader'   => true,
317
+				'capability' => 'ee_edit_registration',
318
+				'obj_id'     => $reg_id,
319
+			),
320
+			'no_approve_and_notify_registration' => array(
321
+				'func'       => 'not_approve_registration',
322
+				'noheader'   => true,
323
+				'args'       => array(true),
324
+				'capability' => 'ee_edit_registration',
325
+				'obj_id'     => $reg_id,
326
+			),
327
+			'no_approve_registrations'            => array(
328
+				'func'       => 'bulk_action_on_registrations',
329
+				'noheader'   => true,
330
+				'capability' => 'ee_edit_registrations',
331
+				'args' => array('not_approve')
332
+			),
333
+			'no_approve_and_notify_registrations' => array(
334
+				'func'       => 'bulk_action_on_registrations',
335
+				'noheader'   => true,
336
+				'capability' => 'ee_edit_registrations',
337
+				'args' => array('not_approve', true)
338
+			),
339
+			'cancel_registration'                => array(
340
+				'func'       => 'cancel_registration',
341
+				'noheader'   => true,
342
+				'capability' => 'ee_edit_registration',
343
+				'obj_id'     => $reg_id,
344
+			),
345
+			'cancel_and_notify_registration'     => array(
346
+				'func'       => 'cancel_registration',
347
+				'noheader'   => true,
348
+				'args'       => array(true),
349
+				'capability' => 'ee_edit_registration',
350
+				'obj_id'     => $reg_id,
351
+			),
352
+			'cancel_registrations'                => array(
353
+				'func'       => 'bulk_action_on_registrations',
354
+				'noheader'   => true,
355
+				'capability' => 'ee_edit_registrations',
356
+				'args' => array('cancel')
357
+			),
358
+			'cancel_and_notify_registrations'     => array(
359
+				'func'       => 'bulk_action_on_registrations',
360
+				'noheader'   => true,
361
+				'capability' => 'ee_edit_registrations',
362
+				'args' => array('cancel', true)
363
+			),
364
+			'wait_list_registration' => array(
365
+				'func'       => 'wait_list_registration',
366
+				'noheader'   => true,
367
+				'capability' => 'ee_edit_registration',
368
+				'obj_id'     => $reg_id,
369
+			),
370
+			'wait_list_and_notify_registration' => array(
371
+				'func'       => 'wait_list_registration',
372
+				'noheader'   => true,
373
+				'args'       => array(true),
374
+				'capability' => 'ee_edit_registration',
375
+				'obj_id'     => $reg_id,
376
+			),
377
+			'contact_list'                       => array(
378
+				'func'       => '_attendee_contact_list_table',
379
+				'capability' => 'ee_read_contacts',
380
+			),
381
+			'add_new_attendee'                   => array(
382
+				'func' => '_create_new_cpt_item',
383
+				'args' => array(
384
+					'new_attendee' => true,
385
+					'capability'   => 'ee_edit_contacts',
386
+				),
387
+			),
388
+			'edit_attendee'                      => array(
389
+				'func'       => '_edit_cpt_item',
390
+				'capability' => 'ee_edit_contacts',
391
+				'obj_id'     => $att_id,
392
+			),
393
+			'duplicate_attendee'                 => array(
394
+				'func'       => '_duplicate_attendee',
395
+				'noheader'   => true,
396
+				'capability' => 'ee_edit_contacts',
397
+				'obj_id'     => $att_id,
398
+			),
399
+			'insert_attendee'                    => array(
400
+				'func'       => '_insert_or_update_attendee',
401
+				'args'       => array(
402
+					'new_attendee' => true,
403
+				),
404
+				'noheader'   => true,
405
+				'capability' => 'ee_edit_contacts',
406
+			),
407
+			'update_attendee'                    => array(
408
+				'func'       => '_insert_or_update_attendee',
409
+				'args'       => array(
410
+					'new_attendee' => false,
411
+				),
412
+				'noheader'   => true,
413
+				'capability' => 'ee_edit_contacts',
414
+				'obj_id'     => $att_id,
415
+			),
416
+			'trash_attendees' => array(
417
+				'func' => '_trash_or_restore_attendees',
418
+				'args' => array(
419
+					'trash' => 'true'
420
+				),
421
+				'noheader' => true,
422
+				'capability' => 'ee_delete_contacts'
423
+			),
424
+			'trash_attendee'                    => array(
425
+				'func'       => '_trash_or_restore_attendees',
426
+				'args'       => array(
427
+					'trash' => true,
428
+				),
429
+				'noheader'   => true,
430
+				'capability' => 'ee_delete_contacts',
431
+				'obj_id'     => $att_id,
432
+			),
433
+			'restore_attendees'                  => array(
434
+				'func'       => '_trash_or_restore_attendees',
435
+				'args'       => array(
436
+					'trash' => false,
437
+				),
438
+				'noheader'   => true,
439
+				'capability' => 'ee_delete_contacts',
440
+				'obj_id'     => $att_id,
441
+			),
442
+			'resend_registration'                => array(
443
+				'func'       => '_resend_registration',
444
+				'noheader'   => true,
445
+				'capability' => 'ee_send_message',
446
+			),
447
+			'registrations_report'               => array(
448
+				'func'       => '_registrations_report',
449
+				'noheader'   => true,
450
+				'capability' => 'ee_read_registrations',
451
+			),
452
+			'contact_list_export'                => array(
453
+				'func'       => '_contact_list_export',
454
+				'noheader'   => true,
455
+				'capability' => 'export',
456
+			),
457
+			'contact_list_report'                => array(
458
+				'func'       => '_contact_list_report',
459
+				'noheader'   => true,
460
+				'capability' => 'ee_read_contacts',
461
+			),
462
+		);
463
+	}
464
+
465
+
466
+	protected function _set_page_config()
467
+	{
468
+		$this->_page_config = array(
469
+			'default'           => array(
470
+				'nav'           => array(
471
+					'label' => esc_html__('Overview', 'event_espresso'),
472
+					'order' => 5,
473
+				),
474
+				'help_tabs'     => array(
475
+					'registrations_overview_help_tab'                       => array(
476
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
477
+						'filename' => 'registrations_overview',
478
+					),
479
+					'registrations_overview_table_column_headings_help_tab' => array(
480
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
481
+						'filename' => 'registrations_overview_table_column_headings',
482
+					),
483
+					'registrations_overview_filters_help_tab'               => array(
484
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
485
+						'filename' => 'registrations_overview_filters',
486
+					),
487
+					'registrations_overview_views_help_tab'                 => array(
488
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
489
+						'filename' => 'registrations_overview_views',
490
+					),
491
+					'registrations_regoverview_other_help_tab'              => array(
492
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
493
+						'filename' => 'registrations_overview_other',
494
+					),
495
+				),
496
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
497
+				'qtips'         => array('Registration_List_Table_Tips'),
498
+				'list_table'    => 'EE_Registrations_List_Table',
499
+				'require_nonce' => false,
500
+			),
501
+			'view_registration' => array(
502
+				'nav'           => array(
503
+					'label'      => esc_html__('REG Details', 'event_espresso'),
504
+					'order'      => 15,
505
+					'url'        => isset($this->_req_data['_REG_ID'])
506
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
507
+						: $this->_admin_base_url,
508
+					'persistent' => false,
509
+				),
510
+				'help_tabs'     => array(
511
+					'registrations_details_help_tab'                    => array(
512
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
513
+						'filename' => 'registrations_details',
514
+					),
515
+					'registrations_details_table_help_tab'              => array(
516
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
517
+						'filename' => 'registrations_details_table',
518
+					),
519
+					'registrations_details_form_answers_help_tab'       => array(
520
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
521
+						'filename' => 'registrations_details_form_answers',
522
+					),
523
+					'registrations_details_registrant_details_help_tab' => array(
524
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
525
+						'filename' => 'registrations_details_registrant_details',
526
+					),
527
+				),
528
+				'help_tour'     => array('Registration_Details_Help_Tour'),
529
+				'metaboxes'     => array_merge(
530
+					$this->_default_espresso_metaboxes,
531
+					array('_registration_details_metaboxes')
532
+				),
533
+				'require_nonce' => false,
534
+			),
535
+			'new_registration'  => array(
536
+				'nav'           => array(
537
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
538
+					'url'        => '#',
539
+					'order'      => 15,
540
+					'persistent' => false,
541
+				),
542
+				'metaboxes'     => $this->_default_espresso_metaboxes,
543
+				'labels'        => array(
544
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
545
+				),
546
+				'require_nonce' => false,
547
+			),
548
+			'add_new_attendee'  => array(
549
+				'nav'           => array(
550
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
551
+					'order'      => 15,
552
+					'persistent' => false,
553
+				),
554
+				'metaboxes'     => array_merge(
555
+					$this->_default_espresso_metaboxes,
556
+					array('_publish_post_box', 'attendee_editor_metaboxes')
557
+				),
558
+				'require_nonce' => false,
559
+			),
560
+			'edit_attendee'     => array(
561
+				'nav'           => array(
562
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
563
+					'order'      => 15,
564
+					'persistent' => false,
565
+					'url'        => isset($this->_req_data['ATT_ID'])
566
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
567
+						: $this->_admin_base_url,
568
+				),
569
+				'metaboxes'     => array('attendee_editor_metaboxes'),
570
+				'require_nonce' => false,
571
+			),
572
+			'contact_list'      => array(
573
+				'nav'           => array(
574
+					'label' => esc_html__('Contact List', 'event_espresso'),
575
+					'order' => 20,
576
+				),
577
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
578
+				'help_tabs'     => array(
579
+					'registrations_contact_list_help_tab'                       => array(
580
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
581
+						'filename' => 'registrations_contact_list',
582
+					),
583
+					'registrations_contact-list_table_column_headings_help_tab' => array(
584
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
585
+						'filename' => 'registrations_contact_list_table_column_headings',
586
+					),
587
+					'registrations_contact_list_views_help_tab'                 => array(
588
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
589
+						'filename' => 'registrations_contact_list_views',
590
+					),
591
+					'registrations_contact_list_other_help_tab'                 => array(
592
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
593
+						'filename' => 'registrations_contact_list_other',
594
+					),
595
+				),
596
+				'help_tour'     => array('Contact_List_Help_Tour'),
597
+				'metaboxes'     => array(),
598
+				'require_nonce' => false,
599
+			),
600
+			//override default cpt routes
601
+			'create_new'        => '',
602
+			'edit'              => '',
603
+		);
604
+	}
605
+
606
+
607
+	/**
608
+	 * The below methods aren't used by this class currently
609
+	 */
610
+	protected function _add_screen_options()
611
+	{
612
+	}
613
+
614
+
615
+	protected function _add_feature_pointers()
616
+	{
617
+	}
618
+
619
+
620
+	public function admin_init()
621
+	{
622
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
623
+			'click "Update Registration Questions" to save your changes',
624
+			'event_espresso'
625
+		);
626
+	}
627
+
628
+
629
+	public function admin_notices()
630
+	{
631
+	}
632
+
633
+
634
+	public function admin_footer_scripts()
635
+	{
636
+	}
637
+
638
+
639
+	/**
640
+	 *        get list of registration statuses
641
+	 *
642
+	 * @access private
643
+	 * @return void
644
+	 * @throws EE_Error
645
+	 */
646
+	private function _get_registration_status_array()
647
+	{
648
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
649
+	}
650
+
651
+
652
+	protected function _add_screen_options_default()
653
+	{
654
+		$this->_per_page_screen_option();
655
+	}
656
+
657
+
658
+	protected function _add_screen_options_contact_list()
659
+	{
660
+		$page_title              = $this->_admin_page_title;
661
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
662
+		$this->_per_page_screen_option();
663
+		$this->_admin_page_title = $page_title;
664
+	}
665
+
666
+
667
+	public function load_scripts_styles()
668
+	{
669
+		//style
670
+		wp_register_style(
671
+			'espresso_reg',
672
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
673
+			array('ee-admin-css'),
674
+			EVENT_ESPRESSO_VERSION
675
+		);
676
+		wp_enqueue_style('espresso_reg');
677
+		//script
678
+		wp_register_script(
679
+			'espresso_reg',
680
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
681
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682
+			EVENT_ESPRESSO_VERSION,
683
+			true
684
+		);
685
+		wp_enqueue_script('espresso_reg');
686
+	}
687
+
688
+
689
+	public function load_scripts_styles_edit_attendee()
690
+	{
691
+		//stuff to only show up on our attendee edit details page.
692
+		$attendee_details_translations = array(
693
+			'att_publish_text' => sprintf(
694
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
695
+				$this->_cpt_model_obj->get_datetime('ATT_created')
696
+			),
697
+		);
698
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
699
+		wp_enqueue_script('jquery-validate');
700
+	}
701
+
702
+
703
+	public function load_scripts_styles_view_registration()
704
+	{
705
+		//styles
706
+		wp_enqueue_style('espresso-ui-theme');
707
+		//scripts
708
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
709
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
710
+	}
711
+
712
+
713
+	public function load_scripts_styles_contact_list()
714
+	{
715
+		wp_dequeue_style('espresso_reg');
716
+		wp_register_style(
717
+			'espresso_att',
718
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
719
+			array('ee-admin-css'),
720
+			EVENT_ESPRESSO_VERSION
721
+		);
722
+		wp_enqueue_style('espresso_att');
723
+	}
724
+
725
+
726
+	public function load_scripts_styles_new_registration()
727
+	{
728
+		wp_register_script(
729
+			'ee-spco-for-admin',
730
+			REG_ASSETS_URL . 'spco_for_admin.js',
731
+			array('underscore', 'jquery'),
732
+			EVENT_ESPRESSO_VERSION,
733
+			true
734
+		);
735
+		wp_enqueue_script('ee-spco-for-admin');
736
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
737
+		EE_Form_Section_Proper::wp_enqueue_scripts();
738
+		EED_Ticket_Selector::load_tckt_slctr_assets();
739
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
740
+	}
741
+
742
+
743
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
744
+	{
745
+		add_filter('FHEE_load_EE_messages', '__return_true');
746
+	}
747
+
748
+
749
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
750
+	{
751
+		add_filter('FHEE_load_EE_messages', '__return_true');
752
+	}
753
+
754
+
755
+	protected function _set_list_table_views_default()
756
+	{
757
+		//for notification related bulk actions we need to make sure only active messengers have an option.
758
+		EED_Messages::set_autoloaders();
759
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
760
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
761
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
762
+		//key= bulk_action_slug, value= message type.
763
+		$match_array = array(
764
+			'approve_registrations'    => 'registration',
765
+			'decline_registrations'    => 'declined_registration',
766
+			'pending_registrations'    => 'pending_approval',
767
+			'no_approve_registrations' => 'not_approved_registration',
768
+			'cancel_registrations'     => 'cancelled_registration',
769
+		);
770
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
771
+			'ee_send_message',
772
+			'batch_send_messages'
773
+		);
774
+		/** setup reg status bulk actions **/
775
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
776
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
777
+				$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
778
+					'Approve and Notify Registrations',
779
+					'event_espresso'
780
+				);
781
+		}
782
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
783
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
784
+				$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
785
+					'Decline and Notify Registrations',
786
+					'event_espresso'
787
+				);
788
+		}
789
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
790
+			'Set Registrations to Pending Payment',
791
+			'event_espresso'
792
+		);
793
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
794
+				$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
795
+					'Set Registrations to Pending Payment and Notify',
796
+					'event_espresso'
797
+				);
798
+		}
799
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
800
+			'Set Registrations to Not Approved',
801
+			'event_espresso'
802
+		);
803
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
804
+				$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
805
+					'Set Registrations to Not Approved and Notify',
806
+					'event_espresso'
807
+				);
808
+		}
809
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
810
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
811
+				$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
812
+					'Cancel Registrations and Notify',
813
+					'event_espresso'
814
+				);
815
+		}
816
+		$def_reg_status_actions = apply_filters(
817
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
818
+			$def_reg_status_actions,
819
+			$active_mts,
820
+			$can_send
821
+		);
822
+
823
+		$this->_views = array(
824
+			'all'   => array(
825
+				'slug'        => 'all',
826
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge($def_reg_status_actions, array(
829
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
830
+				)),
831
+			),
832
+			'month' => array(
833
+				'slug'        => 'month',
834
+				'label'       => esc_html__('This Month', 'event_espresso'),
835
+				'count'       => 0,
836
+				'bulk_action' => array_merge($def_reg_status_actions, array(
837
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
838
+				)),
839
+			),
840
+			'today' => array(
841
+				'slug'        => 'today',
842
+				'label'       => sprintf(
843
+					esc_html__('Today - %s', 'event_espresso'),
844
+					date('M d, Y', current_time('timestamp'))
845
+				),
846
+				'count'       => 0,
847
+				'bulk_action' => array_merge($def_reg_status_actions, array(
848
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
849
+				)),
850
+			),
851
+		);
852
+		if (EE_Registry::instance()->CAP->current_user_can(
853
+			'ee_delete_registrations',
854
+			'espresso_registrations_delete_registration'
855
+		)) {
856
+			$this->_views['incomplete'] = array(
857
+				'slug'        => 'incomplete',
858
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
859
+				'count'       => 0,
860
+				'bulk_action' => array(
861
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862
+				),
863
+			);
864
+			$this->_views['trash']      = array(
865
+				'slug'        => 'trash',
866
+				'label'       => esc_html__('Trash', 'event_espresso'),
867
+				'count'       => 0,
868
+				'bulk_action' => array(
869
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
870
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
871
+				),
872
+			);
873
+		}
874
+	}
875
+
876
+
877
+	protected function _set_list_table_views_contact_list()
878
+	{
879
+		$this->_views = array(
880
+			'in_use' => array(
881
+				'slug'        => 'in_use',
882
+				'label'       => esc_html__('In Use', 'event_espresso'),
883
+				'count'       => 0,
884
+				'bulk_action' => array(
885
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
886
+				),
887
+			),
888
+		);
889
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_contacts',
890
+			'espresso_registrations_trash_attendees')
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = !empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post' => $ATT_ID
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+						. EE_Admin_Page::add_query_args_and_nonce(
1070
+							array(
1071
+								'action' => 'edit',
1072
+								'post'   => $event->ID(),
1073
+							),
1074
+							EVENTS_ADMIN_URL
1075
+						)
1076
+						. '">&nbsp;'
1077
+						. $event->get('EVT_name')
1078
+						. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID   = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		//get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG    = EEM_Registration::instance();
1119
+		$REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1166
+		 * @see EEM_Base::get_all()
1167
+		 */
1168
+		$query_params['group_by'] = '';
1169
+
1170
+		return $count
1171
+			? EEM_Registration::instance()->count($query_params)
1172
+			/** @type EE_Registration[] */
1173
+			: EEM_Registration::instance()->get_all($query_params);
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1179
+	 * Note: this listens to values on the request for some of the query parameters.
1180
+	 *
1181
+	 * @param array $request
1182
+	 * @param int   $per_page
1183
+	 * @param bool  $count
1184
+	 * @return array
1185
+	 * @throws EE_Error
1186
+	 */
1187
+	protected function _get_registration_query_parameters(
1188
+		$request = array(),
1189
+		$per_page = 10,
1190
+		$count = false
1191
+	) {
1192
+
1193
+		$query_params = array(
1194
+			0                          => $this->_get_where_conditions_for_registrations_query(
1195
+				$request
1196
+			),
1197
+			'caps'                     => EEM_Registration::caps_read_admin,
1198
+			'default_where_conditions' => 'this_model_only',
1199
+		);
1200
+		if (! $count) {
1201
+			$query_params = array_merge(
1202
+				$query_params,
1203
+				$this->_get_orderby_for_registrations_query(),
1204
+				$this->_get_limit($per_page)
1205
+			);
1206
+		}
1207
+
1208
+		return $query_params;
1209
+	}
1210
+
1211
+
1212
+	/**
1213
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1214
+	 *
1215
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1216
+	 * @return array
1217
+	 */
1218
+	protected function addAttendeeIdToWhereConditions(array $request)
1219
+	{
1220
+		$where = array();
1221
+		if (! empty($request['ATT_ID'])) {
1222
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1223
+		}
1224
+		return $where;
1225
+	}
1226
+
1227
+
1228
+	/**
1229
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1230
+	 *
1231
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1232
+	 * @return array
1233
+	 */
1234
+	protected function _add_event_id_to_where_conditions(array $request)
1235
+	{
1236
+		$where = array();
1237
+		if (! empty($request['event_id'])) {
1238
+			$where['EVT_ID'] = absint($request['event_id']);
1239
+		}
1240
+		return $where;
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1246
+	 *
1247
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1248
+	 * @return array
1249
+	 */
1250
+	protected function _add_category_id_to_where_conditions(array $request)
1251
+	{
1252
+		$where = array();
1253
+		if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1254
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255
+		}
1256
+		return $where;
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1262
+	 *
1263
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1264
+	 * @return array
1265
+	 */
1266
+	protected function _add_datetime_id_to_where_conditions(array $request)
1267
+	{
1268
+		$where = array();
1269
+		if (! empty($request['datetime_id'])) {
1270
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271
+		}
1272
+		if (! empty($request['DTT_ID'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274
+		}
1275
+		return $where;
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * Adds the correct registration status to the where conditions for the registrations query.
1281
+	 *
1282
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1283
+	 * @return array
1284
+	 */
1285
+	protected function _add_registration_status_to_where_conditions(array $request)
1286
+	{
1287
+		$where = array();
1288
+		$view = EEH_Array::is_set($request, 'status', '');
1289
+		$registration_status = ! empty($request['_reg_status'])
1290
+			? sanitize_text_field($request['_reg_status'])
1291
+			: '';
1292
+
1293
+		/*
1294 1294
          * If filtering by registration status, then we show registrations matching that status.
1295 1295
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1296 1296
          * UNLESS viewing trashed registrations.
1297 1297
          */
1298
-        if (! empty($registration_status)) {
1299
-            $where['STS_ID'] = $registration_status;
1300
-        } else {
1301
-            //make sure we exclude incomplete registrations, but only if not trashed.
1302
-            if ($view === 'trash') {
1303
-                $where['REG_deleted'] = true;
1304
-            } elseif ($view === 'incomplete') {
1305
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1306
-            } else {
1307
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1308
-            }
1309
-        }
1310
-        return $where;
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * Adds any provided date restraints to the where conditions for the registrations query.
1316
-     *
1317
-     * @param array $request usually the same as $this->_req_data but not necessarily
1318
-     * @return array
1319
-     * @throws EE_Error
1320
-     * @throws InvalidArgumentException
1321
-     * @throws InvalidDataTypeException
1322
-     * @throws InvalidInterfaceException
1323
-     */
1324
-    protected function _add_date_to_where_conditions(array $request)
1325
-    {
1326
-        $where = array();
1327
-        $view = EEH_Array::is_set($request, 'status', '');
1328
-        $month_range             = ! empty($request['month_range'])
1329
-            ? sanitize_text_field($request['month_range'])
1330
-            : '';
1331
-        $retrieve_for_today      = $view === 'today';
1332
-        $retrieve_for_this_month = $view === 'month';
1333
-
1334
-        if ($retrieve_for_today) {
1335
-            $now               = date('Y-m-d', current_time('timestamp'));
1336
-            $where['REG_date'] = array(
1337
-                'BETWEEN',
1338
-                array(
1339
-                    EEM_Registration::instance()->convert_datetime_for_query(
1340
-                        'REG_date',
1341
-                        $now . ' 00:00:00',
1342
-                        'Y-m-d H:i:s'
1343
-                    ),
1344
-                    EEM_Registration::instance()->convert_datetime_for_query(
1345
-                        'REG_date',
1346
-                        $now . ' 23:59:59',
1347
-                        'Y-m-d H:i:s'
1348
-                    ),
1349
-                ),
1350
-            );
1351
-        } elseif ($retrieve_for_this_month) {
1352
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1353
-            $days_this_month        = date('t', current_time('timestamp'));
1354
-            $where['REG_date']      = array(
1355
-                'BETWEEN',
1356
-                array(
1357
-                    EEM_Registration::instance()->convert_datetime_for_query(
1358
-                        'REG_date',
1359
-                        $current_year_and_month . '-01 00:00:00',
1360
-                        'Y-m-d H:i:s'
1361
-                    ),
1362
-                    EEM_Registration::instance()->convert_datetime_for_query(
1363
-                        'REG_date',
1364
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1365
-                        'Y-m-d H:i:s'
1366
-                    ),
1367
-                ),
1368
-            );
1369
-        } elseif ($month_range) {
1370
-            $pieces          = explode(' ', $month_range, 3);
1371
-            $month_requested = ! empty($pieces[0])
1372
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1373
-                : '';
1374
-            $year_requested  = ! empty($pieces[1])
1375
-                ? $pieces[1]
1376
-                : '';
1377
-            //if there is not a month or year then we can't go further
1378
-            if ($month_requested && $year_requested) {
1379
-                $days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1380
-                $where['REG_date'] = array(
1381
-                    'BETWEEN',
1382
-                    array(
1383
-                        EEM_Registration::instance()->convert_datetime_for_query(
1384
-                            'REG_date',
1385
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1386
-                            'Y-m-d H:i:s'
1387
-                        ),
1388
-                        EEM_Registration::instance()->convert_datetime_for_query(
1389
-                            'REG_date',
1390
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1391
-                            'Y-m-d H:i:s'
1392
-                        ),
1393
-                    ),
1394
-                );
1395
-            }
1396
-        }
1397
-        return $where;
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * Adds any provided search restraints to the where conditions for the registrations query
1403
-     *
1404
-     * @param array $request usually the same as $this->_req_data but not necessarily
1405
-     * @return array
1406
-     */
1407
-    protected function _add_search_to_where_conditions(array $request)
1408
-    {
1409
-        $where = array();
1410
-        if (! empty($request['s'])) {
1411
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1412
-            $where['OR*search_conditions'] = array(
1413
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1414
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1415
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1416
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1417
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1418
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1419
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1422
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1423
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1424
-                'REG_final_price'                         => array('LIKE', $search_string),
1425
-                'REG_code'                                => array('LIKE', $search_string),
1426
-                'REG_count'                               => array('LIKE', $search_string),
1427
-                'REG_group_size'                          => array('LIKE', $search_string),
1428
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1429
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1430
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1431
-            );
1432
-        }
1433
-        return $where;
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * Sets up the where conditions for the registrations query.
1439
-     *
1440
-     * @param array $request
1441
-     * @return array
1442
-     * @throws EE_Error
1443
-     */
1444
-    protected function _get_where_conditions_for_registrations_query($request)
1445
-    {
1446
-        return apply_filters(
1447
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1448
-            array_merge(
1449
-                $this->addAttendeeIdToWhereConditions($request),
1450
-                $this->_add_event_id_to_where_conditions($request),
1451
-                $this->_add_category_id_to_where_conditions($request),
1452
-                $this->_add_datetime_id_to_where_conditions($request),
1453
-                $this->_add_registration_status_to_where_conditions($request),
1454
-                $this->_add_date_to_where_conditions($request),
1455
-                $this->_add_search_to_where_conditions($request)
1456
-            ),
1457
-            $request
1458
-        );
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     * Sets up the orderby for the registrations query.
1464
-     *
1465
-     * @return array
1466
-     */
1467
-    protected function _get_orderby_for_registrations_query()
1468
-    {
1469
-        $orderby_field = ! empty($this->_req_data['orderby'])
1470
-            ? sanitize_text_field($this->_req_data['orderby'])
1471
-            : '';
1472
-        switch ($orderby_field) {
1473
-            case '_REG_ID':
1474
-                $orderby = array('REG_ID');
1475
-                break;
1476
-            case '_Reg_status':
1477
-                $orderby = array('STS_ID');
1478
-                break;
1479
-            case 'ATT_fname':
1480
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1481
-                break;
1482
-            case 'ATT_lname':
1483
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1484
-                break;
1485
-            case 'event_name':
1486
-                $orderby = array('Event.EVT_name');
1487
-                break;
1488
-            case 'DTT_EVT_start':
1489
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1490
-                break;
1491
-            default: //'REG_date'
1492
-                $orderby = array('REG_date');
1493
-        }
1494
-
1495
-        //order
1496
-        $order = ! empty($this->_req_data['order'])
1497
-            ? sanitize_text_field($this->_req_data['order'])
1498
-            : 'DESC';
1499
-        $orderby = array_combine(
1500
-            $orderby,
1501
-            array_fill(0, count($orderby), $order)
1502
-        );
1503
-        //because there are many registrations with the same date, define
1504
-        //a secondary way to order them, otherwise MySQL seems to be a bit random
1505
-        if (empty($orderby['REG_ID'])) {
1506
-            $orderby['REG_ID'] = $order;
1507
-        }
1508
-        return array('order_by' => $orderby);
1509
-    }
1510
-
1511
-
1512
-    /**
1513
-     * Sets up the limit for the registrations query.
1514
-     *
1515
-     * @param $per_page
1516
-     * @return array
1517
-     */
1518
-    protected function _get_limit($per_page)
1519
-    {
1520
-        $current_page = ! empty($this->_req_data['paged'])
1521
-            ? absint($this->_req_data['paged'])
1522
-            : 1;
1523
-        $per_page     = ! empty($this->_req_data['perpage'])
1524
-            ? $this->_req_data['perpage']
1525
-            : $per_page;
1526
-
1527
-        //-1 means return all results so get out if that's set.
1528
-        if ((int)$per_page === -1) {
1529
-            return array();
1530
-        }
1531
-        $per_page = absint($per_page);
1532
-        $offset   = ($current_page - 1) * $per_page;
1533
-        return array('limit' => array($offset, $per_page));
1534
-    }
1535
-
1536
-
1537
-    public function get_registration_status_array()
1538
-    {
1539
-        return self::$_reg_status;
1540
-    }
1541
-
1542
-
1543
-
1544
-
1545
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1546
-    /**
1547
-     *        generates HTML for the View Registration Details Admin page
1548
-     *
1549
-     * @access protected
1550
-     * @return void
1551
-     * @throws DomainException
1552
-     * @throws EE_Error
1553
-     * @throws InvalidArgumentException
1554
-     * @throws InvalidDataTypeException
1555
-     * @throws InvalidInterfaceException
1556
-     * @throws EntityNotFoundException
1557
-     */
1558
-    protected function _registration_details()
1559
-    {
1560
-        $this->_template_args = array();
1561
-        $this->_set_registration_object();
1562
-        if (is_object($this->_registration)) {
1563
-            $transaction                                   = $this->_registration->transaction()
1564
-                ? $this->_registration->transaction()
1565
-                : EE_Transaction::new_instance();
1566
-            $this->_session                                = $transaction->session_data();
1567
-            $event_id                                      = $this->_registration->event_ID();
1568
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1569
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1570
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1571
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1572
-            $this->_template_args['grand_total']           = $transaction->total();
1573
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1574
-            // link back to overview
1575
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1576
-            $this->_template_args['registration']                = $this->_registration;
1577
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1578
-                array(
1579
-                    'action'   => 'default',
1580
-                    'event_id' => $event_id,
1581
-                ),
1582
-                REG_ADMIN_URL
1583
-            );
1584
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1585
-                array(
1586
-                    'action' => 'default',
1587
-                    'EVT_ID' => $event_id,
1588
-                    'page'   => 'espresso_transactions',
1589
-                ),
1590
-                admin_url('admin.php')
1591
-            );
1592
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1593
-                array(
1594
-                    'page'   => 'espresso_events',
1595
-                    'action' => 'edit',
1596
-                    'post'   => $event_id,
1597
-                ),
1598
-                admin_url('admin.php')
1599
-            );
1600
-            //next and previous links
1601
-            $next_reg                                      = $this->_registration->next(
1602
-                null,
1603
-                array(),
1604
-                'REG_ID'
1605
-            );
1606
-            $this->_template_args['next_registration']     = $next_reg
1607
-                ? $this->_next_link(
1608
-                    EE_Admin_Page::add_query_args_and_nonce(
1609
-                        array(
1610
-                            'action'  => 'view_registration',
1611
-                            '_REG_ID' => $next_reg['REG_ID'],
1612
-                        ),
1613
-                        REG_ADMIN_URL
1614
-                    ),
1615
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1616
-                )
1617
-                : '';
1618
-            $previous_reg                                  = $this->_registration->previous(
1619
-                null,
1620
-                array(),
1621
-                'REG_ID'
1622
-            );
1623
-            $this->_template_args['previous_registration'] = $previous_reg
1624
-                ? $this->_previous_link(
1625
-                    EE_Admin_Page::add_query_args_and_nonce(
1626
-                        array(
1627
-                            'action'  => 'view_registration',
1628
-                            '_REG_ID' => $previous_reg['REG_ID'],
1629
-                        ),
1630
-                        REG_ADMIN_URL
1631
-                    ),
1632
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1633
-                )
1634
-                : '';
1635
-            // grab header
1636
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1637
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1638
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639
-                $template_path,
1640
-                $this->_template_args,
1641
-                true
1642
-            );
1643
-        } else {
1644
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1645
-        }
1646
-        // the details template wrapper
1647
-        $this->display_admin_page_with_sidebar();
1648
-    }
1649
-
1650
-
1651
-    protected function _registration_details_metaboxes()
1652
-    {
1653
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1654
-        $this->_set_registration_object();
1655
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1656
-        add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1657
-            array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1658
-        add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1659
-            array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1660
-        if ($attendee instanceof EE_Attendee
1661
-            && EE_Registry::instance()->CAP->current_user_can(
1662
-                'ee_edit_registration',
1663
-                'edit-reg-questions-mbox',
1664
-                $this->_registration->ID()
1665
-            )
1666
-        ) {
1667
-            add_meta_box(
1668
-                'edit-reg-questions-mbox',
1669
-                esc_html__('Registration Form Answers', 'event_espresso'),
1670
-                array($this, '_reg_questions_meta_box'),
1671
-                $this->wp_page_slug,
1672
-                'normal',
1673
-                'high'
1674
-            );
1675
-        }
1676
-        add_meta_box(
1677
-            'edit-reg-registrant-mbox',
1678
-            esc_html__('Contact Details', 'event_espresso'),
1679
-            array($this, '_reg_registrant_side_meta_box'),
1680
-            $this->wp_page_slug,
1681
-            'side',
1682
-            'high'
1683
-        );
1684
-        if ($this->_registration->group_size() > 1) {
1685
-            add_meta_box(
1686
-                'edit-reg-attendees-mbox',
1687
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1688
-                array($this, '_reg_attendees_meta_box'),
1689
-                $this->wp_page_slug,
1690
-                'normal',
1691
-                'high'
1692
-            );
1693
-        }
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * set_reg_status_buttons_metabox
1699
-     *
1700
-     * @access protected
1701
-     * @return string
1702
-     * @throws \EE_Error
1703
-     */
1704
-    public function set_reg_status_buttons_metabox()
1705
-    {
1706
-        $this->_set_registration_object();
1707
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1708
-        echo $change_reg_status_form->form_open(
1709
-            self::add_query_args_and_nonce(
1710
-                array(
1711
-                    'action' => 'change_reg_status',
1712
-                ),
1713
-                REG_ADMIN_URL
1714
-            )
1715
-        );
1716
-        echo $change_reg_status_form->get_html();
1717
-        echo $change_reg_status_form->form_close();
1718
-    }
1719
-
1720
-
1721
-    /**
1722
-     * @return EE_Form_Section_Proper
1723
-     * @throws EE_Error
1724
-     * @throws InvalidArgumentException
1725
-     * @throws InvalidDataTypeException
1726
-     * @throws InvalidInterfaceException
1727
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1728
-     */
1729
-    protected function _generate_reg_status_change_form()
1730
-    {
1731
-        return new EE_Form_Section_Proper(array(
1732
-            'name'            => 'reg_status_change_form',
1733
-            'html_id'         => 'reg-status-change-form',
1734
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1735
-            'subsections'     => array(
1736
-                'return'             => new EE_Hidden_Input(array(
1737
-                    'name'    => 'return',
1738
-                    'default' => 'view_registration',
1739
-                )),
1740
-                'REG_ID'             => new EE_Hidden_Input(array(
1741
-                    'name'    => 'REG_ID',
1742
-                    'default' => $this->_registration->ID(),
1743
-                )),
1744
-                'current_status'     => new EE_Form_Section_HTML(
1745
-                    EEH_HTML::tr(
1746
-                        EEH_HTML::th(
1747
-                            EEH_HTML::label(
1748
-                                EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1749
-                                )
1750
-                            )
1751
-                        )
1752
-                        . EEH_HTML::td(
1753
-                            EEH_HTML::strong(
1754
-                                $this->_registration->pretty_status(),
1755
-                                '',
1756
-                                'status-' . $this->_registration->status_ID(),
1757
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758
-                            )
1759
-                        )
1760
-                    )
1761
-                ),
1762
-                'reg_status'         => new EE_Select_Input(
1763
-                    $this->_get_reg_statuses(),
1764
-                    array(
1765
-                        'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1766
-                        'default'         => $this->_registration->status_ID(),
1767
-                    )
1768
-                ),
1769
-                'send_notifications' => new EE_Yes_No_Input(
1770
-                    array(
1771
-                        'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1772
-                        'default'         => false,
1773
-                        'html_help_text'  => esc_html__(
1774
-                            'If set to "Yes", then the related messages will be sent to the registrant.',
1775
-                            'event_espresso'
1776
-                        ),
1777
-                    )
1778
-                ),
1779
-                'submit'             => new EE_Submit_Input(
1780
-                    array(
1781
-                        'html_class'      => 'button-primary',
1782
-                        'html_label_text' => '&nbsp;',
1783
-                        'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1784
-                    )
1785
-                ),
1786
-            ),
1787
-        ));
1788
-    }
1789
-
1790
-
1791
-    /**
1792
-     * Returns an array of all the buttons for the various statuses and switch status actions
1793
-     *
1794
-     * @return array
1795
-     * @throws EE_Error
1796
-     * @throws InvalidArgumentException
1797
-     * @throws InvalidDataTypeException
1798
-     * @throws InvalidInterfaceException
1799
-     * @throws EntityNotFoundException
1800
-     */
1801
-    protected function _get_reg_statuses()
1802
-    {
1803
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1804
-        unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1805
-        // get current reg status
1806
-        $current_status = $this->_registration->status_ID();
1807
-        // is registration for free event? This will determine whether to display the pending payment option
1808
-        if (
1809
-            $current_status !== EEM_Registration::status_id_pending_payment
1810
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1811
-        ) {
1812
-            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1813
-        }
1814
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1815
-    }
1816
-
1817
-
1818
-    /**
1819
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1820
-     *
1821
-     * @param bool $status REG status given for changing registrations to.
1822
-     * @param bool $notify Whether to send messages notifications or not.
1823
-     * @return array (array with reg_id(s) updated and whether update was successful.
1824
-     * @throws EE_Error
1825
-     * @throws InvalidArgumentException
1826
-     * @throws InvalidDataTypeException
1827
-     * @throws InvalidInterfaceException
1828
-     * @throws ReflectionException
1829
-     * @throws RuntimeException
1830
-     * @throws EntityNotFoundException
1831
-     */
1832
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1833
-    {
1834
-        if (isset($this->_req_data['reg_status_change_form'])) {
1835
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
-                ? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1837
-                : array();
1838
-        } else {
1839
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1840
-                ? (array)$this->_req_data['_REG_ID']
1841
-                : array();
1842
-        }
1843
-        // sanitize $REG_IDs
1844
-        $REG_IDs = array_map('absint', $REG_IDs);
1845
-        // and remove empty entries
1846
-        $REG_IDs = array_filter($REG_IDs);
1847
-
1848
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1849
-
1850
-        /**
1851
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1852
-         * Currently this value is used downstream by the _process_resend_registration method.
1853
-         *
1854
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1855
-         * @param bool                     $status           The status registrations were changed to.
1856
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1857
-         * @param Registrations_Admin_Page $admin_page_object
1858
-         */
1859
-        $this->_req_data['_REG_ID'] = apply_filters(
1860
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1861
-            $result['REG_ID'],
1862
-            $status,
1863
-            $result['success'],
1864
-            $this
1865
-        );
1866
-
1867
-        //notify?
1868
-        if ($notify
1869
-            && $result['success']
1870
-            && ! empty($this->_req_data['_REG_ID'])
1871
-            && EE_Registry::instance()->CAP->current_user_can(
1872
-                'ee_send_message',
1873
-                'espresso_registrations_resend_registration'
1874
-            )
1875
-        ) {
1876
-            $this->_process_resend_registration();
1877
-        }
1878
-        return $result;
1879
-    }
1880
-
1881
-
1882
-    /**
1883
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1884
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1885
-     *
1886
-     * @param array  $REG_IDs
1887
-     * @param string $status
1888
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1889
-     *                        slug sent with setting the registration status.
1890
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1891
-     * @throws EE_Error
1892
-     * @throws InvalidArgumentException
1893
-     * @throws InvalidDataTypeException
1894
-     * @throws InvalidInterfaceException
1895
-     * @throws ReflectionException
1896
-     * @throws RuntimeException
1897
-     * @throws EntityNotFoundException
1898
-     */
1899
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1900
-    {
1901
-        $success = false;
1902
-        // typecast $REG_IDs
1903
-        $REG_IDs = (array)$REG_IDs;
1904
-        if ( ! empty($REG_IDs)) {
1905
-            $success = true;
1906
-            // set default status if none is passed
1907
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1908
-            $status_context = $notify
1909
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1910
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1911
-            //loop through REG_ID's and change status
1912
-            foreach ($REG_IDs as $REG_ID) {
1913
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1914
-                if ($registration instanceof EE_Registration) {
1915
-                    $registration->set_status(
1916
-                        $status,
1917
-                        false,
1918
-                        new Context(
1919
-                            $status_context,
1920
-                            esc_html__(
1921
-                                'Manually triggered status change on a Registration Admin Page route.',
1922
-                                'event_espresso'
1923
-                            )
1924
-                        )
1925
-                    );
1926
-                    $result = $registration->save();
1927
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1928
-                    $success = $result !== false ? $success : false;
1929
-                }
1930
-            }
1931
-        }
1932
-
1933
-        //return $success and processed registrations
1934
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1935
-    }
1936
-
1937
-
1938
-    /**
1939
-     * Common logic for setting up success message and redirecting to appropriate route
1940
-     *
1941
-     * @param  string $STS_ID status id for the registration changed to
1942
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1943
-     * @return void
1944
-     * @throws EE_Error
1945
-     */
1946
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1947
-    {
1948
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1949
-            : array('success' => false);
1950
-        $success = isset($result['success']) && $result['success'];
1951
-        //setup success message
1952
-        if ($success) {
1953
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1954
-                $msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1955
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1956
-            } else {
1957
-                $msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1958
-                    EEH_Template::pretty_status($STS_ID, false, 'lower'));
1959
-            }
1960
-            EE_Error::add_success($msg);
1961
-        } else {
1962
-            EE_Error::add_error(
1963
-                esc_html__(
1964
-                    'Something went wrong, and the status was not changed',
1965
-                    'event_espresso'
1966
-                ), __FILE__, __LINE__, __FUNCTION__
1967
-            );
1968
-        }
1969
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1970
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1971
-        } else {
1972
-            $route = array('action' => 'default');
1973
-        }
1974
-        //unset nonces
1975
-        foreach ($this->_req_data as $ref => $value) {
1976
-            if (strpos($ref, 'nonce') !== false) {
1977
-                unset($this->_req_data[$ref]);
1978
-                continue;
1979
-            }
1980
-            $value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1981
-            $this->_req_data[$ref] = $value;
1982
-        }
1983
-        //merge request vars so that the reloaded list table contains any existing filter query params
1984
-        $route = array_merge($this->_req_data, $route);
1985
-        $this->_redirect_after_action($success, '', '', $route, true);
1986
-    }
1987
-
1988
-
1989
-    /**
1990
-     * incoming reg status change from reg details page.
1991
-     *
1992
-     * @return void
1993
-     */
1994
-    protected function _change_reg_status()
1995
-    {
1996
-        $this->_req_data['return'] = 'view_registration';
1997
-        //set notify based on whether the send notifications toggle is set or not
1998
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1999
-        //$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2000
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2001
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2002
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2003
-            case EEM_Registration::status_id_approved :
2004
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
2005
-                $this->approve_registration($notify);
2006
-                break;
2007
-            case EEM_Registration::status_id_pending_payment :
2008
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
2009
-                $this->pending_registration($notify);
2010
-                break;
2011
-            case EEM_Registration::status_id_not_approved :
2012
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
2013
-                $this->not_approve_registration($notify);
2014
-                break;
2015
-            case EEM_Registration::status_id_declined :
2016
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
2017
-                $this->decline_registration($notify);
2018
-                break;
2019
-            case EEM_Registration::status_id_cancelled :
2020
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
2021
-                $this->cancel_registration($notify);
2022
-                break;
2023
-            case EEM_Registration::status_id_wait_list :
2024
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
2025
-                $this->wait_list_registration($notify);
2026
-                break;
2027
-            case EEM_Registration::status_id_incomplete :
2028
-            default :
2029
-                $result['success'] = false;
2030
-                unset($this->_req_data['return']);
2031
-                $this->_reg_status_change_return('', false);
2032
-                break;
2033
-        }
2034
-    }
2035
-
2036
-
2037
-    /**
2038
-     * Callback for bulk action routes.
2039
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2040
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2041
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2042
-     * when an action is happening on just a single registration).
2043
-     * @param      $action
2044
-     * @param bool $notify
2045
-     */
2046
-    protected function bulk_action_on_registrations($action, $notify = false) {
2047
-        do_action(
2048
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2049
-            $this,
2050
-            $action,
2051
-            $notify
2052
-        );
2053
-        $method = $action . '_registration';
2054
-        if (method_exists($this, $method)) {
2055
-            $this->$method($notify);
2056
-        }
2057
-    }
2058
-
2059
-
2060
-    /**
2061
-     * approve_registration
2062
-     *
2063
-     * @access protected
2064
-     * @param bool $notify whether or not to notify the registrant about their approval.
2065
-     * @return void
2066
-     */
2067
-    protected function approve_registration($notify = false)
2068
-    {
2069
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     *        decline_registration
2075
-     *
2076
-     * @access protected
2077
-     * @param bool $notify whether or not to notify the registrant about their status change.
2078
-     * @return void
2079
-     */
2080
-    protected function decline_registration($notify = false)
2081
-    {
2082
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2083
-    }
2084
-
2085
-
2086
-    /**
2087
-     *        cancel_registration
2088
-     *
2089
-     * @access protected
2090
-     * @param bool $notify whether or not to notify the registrant about their status change.
2091
-     * @return void
2092
-     */
2093
-    protected function cancel_registration($notify = false)
2094
-    {
2095
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2096
-    }
2097
-
2098
-
2099
-    /**
2100
-     *        not_approve_registration
2101
-     *
2102
-     * @access protected
2103
-     * @param bool $notify whether or not to notify the registrant about their status change.
2104
-     * @return void
2105
-     */
2106
-    protected function not_approve_registration($notify = false)
2107
-    {
2108
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2109
-    }
2110
-
2111
-
2112
-    /**
2113
-     *        decline_registration
2114
-     *
2115
-     * @access protected
2116
-     * @param bool $notify whether or not to notify the registrant about their status change.
2117
-     * @return void
2118
-     */
2119
-    protected function pending_registration($notify = false)
2120
-    {
2121
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2122
-    }
2123
-
2124
-
2125
-    /**
2126
-     * waitlist_registration
2127
-     *
2128
-     * @access protected
2129
-     * @param bool $notify whether or not to notify the registrant about their status change.
2130
-     * @return void
2131
-     */
2132
-    protected function wait_list_registration($notify = false)
2133
-    {
2134
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2135
-    }
2136
-
2137
-
2138
-    /**
2139
-     *        generates HTML for the Registration main meta box
2140
-     *
2141
-     * @access public
2142
-     * @return void
2143
-     * @throws DomainException
2144
-     * @throws EE_Error
2145
-     * @throws InvalidArgumentException
2146
-     * @throws InvalidDataTypeException
2147
-     * @throws InvalidInterfaceException
2148
-     * @throws ReflectionException
2149
-     * @throws EntityNotFoundException
2150
-     */
2151
-    public function _reg_details_meta_box()
2152
-    {
2153
-        EEH_Autoloader::register_line_item_display_autoloaders();
2154
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2155
-        EE_Registry::instance()->load_helper('Line_Item');
2156
-        $transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2157
-            : EE_Transaction::new_instance();
2158
-        $this->_session = $transaction->session_data();
2159
-        $filters        = new EE_Line_Item_Filter_Collection();
2160
-        //$filters->add( new EE_Non_Zero_Line_Item_Filter() );
2161
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2162
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
2163
-            $transaction->total_line_item());
2164
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
2165
-        $line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
2166
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
2167
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2168
-            $filtered_line_item_tree,
2169
-            array('EE_Registration' => $this->_registration)
2170
-        );
2171
-        $attendee                                = $this->_registration->attendee();
2172
-        if (EE_Registry::instance()->CAP->current_user_can(
2173
-            'ee_read_transaction',
2174
-            'espresso_transactions_view_transaction'
2175
-        )) {
2176
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2177
-                EE_Admin_Page::add_query_args_and_nonce(
2178
-                    array(
2179
-                        'action' => 'view_transaction',
2180
-                        'TXN_ID' => $transaction->ID(),
2181
-                    ),
2182
-                    TXN_ADMIN_URL
2183
-                ),
2184
-                esc_html__(' View Transaction', 'event_espresso'),
2185
-                'button secondary-button right',
2186
-                'dashicons dashicons-cart'
2187
-            );
2188
-        } else {
2189
-            $this->_template_args['view_transaction_button'] = '';
2190
-        }
2191
-        if ($attendee instanceof EE_Attendee
2192
-            && EE_Registry::instance()->CAP->current_user_can(
2193
-                'ee_send_message',
2194
-                'espresso_registrations_resend_registration'
2195
-            )
2196
-        ) {
2197
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2198
-                EE_Admin_Page::add_query_args_and_nonce(
2199
-                    array(
2200
-                        'action'      => 'resend_registration',
2201
-                        '_REG_ID'     => $this->_registration->ID(),
2202
-                        'redirect_to' => 'view_registration',
2203
-                    ),
2204
-                    REG_ADMIN_URL
2205
-                ),
2206
-                esc_html__(' Resend Registration', 'event_espresso'),
2207
-                'button secondary-button right',
2208
-                'dashicons dashicons-email-alt'
2209
-            );
2210
-        } else {
2211
-            $this->_template_args['resend_registration_button'] = '';
2212
-        }
2213
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2214
-        $payment                               = $transaction->get_first_related('Payment');
2215
-        $payment                               = ! $payment instanceof EE_Payment
2216
-            ? EE_Payment::new_instance()
2217
-            : $payment;
2218
-        $payment_method                        = $payment->get_first_related('Payment_Method');
2219
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
2220
-            ? EE_Payment_Method::new_instance()
2221
-            : $payment_method;
2222
-        $reg_details                           = array(
2223
-            'payment_method'       => $payment_method->name(),
2224
-            'response_msg'         => $payment->gateway_response(),
2225
-            'registration_id'      => $this->_registration->get('REG_code'),
2226
-            'registration_session' => $this->_registration->session_ID(),
2227
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2228
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2229
-        );
2230
-        if (isset($reg_details['registration_id'])) {
2231
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2232
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2233
-                'Registration ID',
2234
-                'event_espresso'
2235
-            );
2236
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2237
-        }
2238
-        if (isset($reg_details['payment_method'])) {
2239
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2240
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2241
-                'Most Recent Payment Method',
2242
-                'event_espresso'
2243
-            );
2244
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2245
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2246
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2247
-                'Payment method response',
2248
-                'event_espresso'
2249
-            );
2250
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2251
-        }
2252
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2254
-            'Registration Session',
2255
-            'event_espresso'
2256
-        );
2257
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2258
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2259
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2260
-            'Registration placed from IP',
2261
-            'event_espresso'
2262
-        );
2263
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2264
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2265
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2266
-            'event_espresso');
2267
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2268
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2269
-            array(
2270
-                'action'   => 'default',
2271
-                'event_id' => $this->_registration->event_ID(),
2272
-            ),
2273
-            REG_ADMIN_URL
2274
-        );
2275
-        $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276
-        $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277
-        $template_path                                                        =
2278
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2279
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280
-    }
2281
-
2282
-
2283
-    /**
2284
-     * generates HTML for the Registration Questions meta box.
2285
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2286
-     * otherwise uses new forms system
2287
-     *
2288
-     * @access public
2289
-     * @return void
2290
-     * @throws DomainException
2291
-     * @throws EE_Error
2292
-     */
2293
-    public function _reg_questions_meta_box()
2294
-    {
2295
-        //allow someone to override this method entirely
2296
-        if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2297
-            $this->_registration)) {
2298
-            $form                                              = $this->_get_reg_custom_questions_form(
2299
-                $this->_registration->ID()
2300
-            );
2301
-            $this->_template_args['att_questions']             = count($form->subforms()) > 0
2302
-                ? $form->get_html_and_js()
2303
-                : '';
2304
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305
-            $this->_template_args['REG_ID']                    = $this->_registration->ID();
2306
-            $template_path                                     =
2307
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2308
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309
-        }
2310
-    }
2311
-
2312
-
2313
-    /**
2314
-     * form_before_question_group
2315
-     *
2316
-     * @deprecated    as of 4.8.32.rc.000
2317
-     * @access        public
2318
-     * @param        string $output
2319
-     * @return        string
2320
-     */
2321
-    public function form_before_question_group($output)
2322
-    {
2323
-        EE_Error::doing_it_wrong(
2324
-            __CLASS__ . '::' . __FUNCTION__,
2325
-            esc_html__(
2326
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327
-                'event_espresso'
2328
-            ),
2329
-            '4.8.32.rc.000'
2330
-        );
2331
-        return '
1298
+		if (! empty($registration_status)) {
1299
+			$where['STS_ID'] = $registration_status;
1300
+		} else {
1301
+			//make sure we exclude incomplete registrations, but only if not trashed.
1302
+			if ($view === 'trash') {
1303
+				$where['REG_deleted'] = true;
1304
+			} elseif ($view === 'incomplete') {
1305
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1306
+			} else {
1307
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1308
+			}
1309
+		}
1310
+		return $where;
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1316
+	 *
1317
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1318
+	 * @return array
1319
+	 * @throws EE_Error
1320
+	 * @throws InvalidArgumentException
1321
+	 * @throws InvalidDataTypeException
1322
+	 * @throws InvalidInterfaceException
1323
+	 */
1324
+	protected function _add_date_to_where_conditions(array $request)
1325
+	{
1326
+		$where = array();
1327
+		$view = EEH_Array::is_set($request, 'status', '');
1328
+		$month_range             = ! empty($request['month_range'])
1329
+			? sanitize_text_field($request['month_range'])
1330
+			: '';
1331
+		$retrieve_for_today      = $view === 'today';
1332
+		$retrieve_for_this_month = $view === 'month';
1333
+
1334
+		if ($retrieve_for_today) {
1335
+			$now               = date('Y-m-d', current_time('timestamp'));
1336
+			$where['REG_date'] = array(
1337
+				'BETWEEN',
1338
+				array(
1339
+					EEM_Registration::instance()->convert_datetime_for_query(
1340
+						'REG_date',
1341
+						$now . ' 00:00:00',
1342
+						'Y-m-d H:i:s'
1343
+					),
1344
+					EEM_Registration::instance()->convert_datetime_for_query(
1345
+						'REG_date',
1346
+						$now . ' 23:59:59',
1347
+						'Y-m-d H:i:s'
1348
+					),
1349
+				),
1350
+			);
1351
+		} elseif ($retrieve_for_this_month) {
1352
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1353
+			$days_this_month        = date('t', current_time('timestamp'));
1354
+			$where['REG_date']      = array(
1355
+				'BETWEEN',
1356
+				array(
1357
+					EEM_Registration::instance()->convert_datetime_for_query(
1358
+						'REG_date',
1359
+						$current_year_and_month . '-01 00:00:00',
1360
+						'Y-m-d H:i:s'
1361
+					),
1362
+					EEM_Registration::instance()->convert_datetime_for_query(
1363
+						'REG_date',
1364
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1365
+						'Y-m-d H:i:s'
1366
+					),
1367
+				),
1368
+			);
1369
+		} elseif ($month_range) {
1370
+			$pieces          = explode(' ', $month_range, 3);
1371
+			$month_requested = ! empty($pieces[0])
1372
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1373
+				: '';
1374
+			$year_requested  = ! empty($pieces[1])
1375
+				? $pieces[1]
1376
+				: '';
1377
+			//if there is not a month or year then we can't go further
1378
+			if ($month_requested && $year_requested) {
1379
+				$days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1380
+				$where['REG_date'] = array(
1381
+					'BETWEEN',
1382
+					array(
1383
+						EEM_Registration::instance()->convert_datetime_for_query(
1384
+							'REG_date',
1385
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1386
+							'Y-m-d H:i:s'
1387
+						),
1388
+						EEM_Registration::instance()->convert_datetime_for_query(
1389
+							'REG_date',
1390
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1391
+							'Y-m-d H:i:s'
1392
+						),
1393
+					),
1394
+				);
1395
+			}
1396
+		}
1397
+		return $where;
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * Adds any provided search restraints to the where conditions for the registrations query
1403
+	 *
1404
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1405
+	 * @return array
1406
+	 */
1407
+	protected function _add_search_to_where_conditions(array $request)
1408
+	{
1409
+		$where = array();
1410
+		if (! empty($request['s'])) {
1411
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1412
+			$where['OR*search_conditions'] = array(
1413
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1414
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1415
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1416
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1417
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1418
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1419
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1422
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1423
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1424
+				'REG_final_price'                         => array('LIKE', $search_string),
1425
+				'REG_code'                                => array('LIKE', $search_string),
1426
+				'REG_count'                               => array('LIKE', $search_string),
1427
+				'REG_group_size'                          => array('LIKE', $search_string),
1428
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1429
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1430
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1431
+			);
1432
+		}
1433
+		return $where;
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * Sets up the where conditions for the registrations query.
1439
+	 *
1440
+	 * @param array $request
1441
+	 * @return array
1442
+	 * @throws EE_Error
1443
+	 */
1444
+	protected function _get_where_conditions_for_registrations_query($request)
1445
+	{
1446
+		return apply_filters(
1447
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1448
+			array_merge(
1449
+				$this->addAttendeeIdToWhereConditions($request),
1450
+				$this->_add_event_id_to_where_conditions($request),
1451
+				$this->_add_category_id_to_where_conditions($request),
1452
+				$this->_add_datetime_id_to_where_conditions($request),
1453
+				$this->_add_registration_status_to_where_conditions($request),
1454
+				$this->_add_date_to_where_conditions($request),
1455
+				$this->_add_search_to_where_conditions($request)
1456
+			),
1457
+			$request
1458
+		);
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 * Sets up the orderby for the registrations query.
1464
+	 *
1465
+	 * @return array
1466
+	 */
1467
+	protected function _get_orderby_for_registrations_query()
1468
+	{
1469
+		$orderby_field = ! empty($this->_req_data['orderby'])
1470
+			? sanitize_text_field($this->_req_data['orderby'])
1471
+			: '';
1472
+		switch ($orderby_field) {
1473
+			case '_REG_ID':
1474
+				$orderby = array('REG_ID');
1475
+				break;
1476
+			case '_Reg_status':
1477
+				$orderby = array('STS_ID');
1478
+				break;
1479
+			case 'ATT_fname':
1480
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1481
+				break;
1482
+			case 'ATT_lname':
1483
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1484
+				break;
1485
+			case 'event_name':
1486
+				$orderby = array('Event.EVT_name');
1487
+				break;
1488
+			case 'DTT_EVT_start':
1489
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1490
+				break;
1491
+			default: //'REG_date'
1492
+				$orderby = array('REG_date');
1493
+		}
1494
+
1495
+		//order
1496
+		$order = ! empty($this->_req_data['order'])
1497
+			? sanitize_text_field($this->_req_data['order'])
1498
+			: 'DESC';
1499
+		$orderby = array_combine(
1500
+			$orderby,
1501
+			array_fill(0, count($orderby), $order)
1502
+		);
1503
+		//because there are many registrations with the same date, define
1504
+		//a secondary way to order them, otherwise MySQL seems to be a bit random
1505
+		if (empty($orderby['REG_ID'])) {
1506
+			$orderby['REG_ID'] = $order;
1507
+		}
1508
+		return array('order_by' => $orderby);
1509
+	}
1510
+
1511
+
1512
+	/**
1513
+	 * Sets up the limit for the registrations query.
1514
+	 *
1515
+	 * @param $per_page
1516
+	 * @return array
1517
+	 */
1518
+	protected function _get_limit($per_page)
1519
+	{
1520
+		$current_page = ! empty($this->_req_data['paged'])
1521
+			? absint($this->_req_data['paged'])
1522
+			: 1;
1523
+		$per_page     = ! empty($this->_req_data['perpage'])
1524
+			? $this->_req_data['perpage']
1525
+			: $per_page;
1526
+
1527
+		//-1 means return all results so get out if that's set.
1528
+		if ((int)$per_page === -1) {
1529
+			return array();
1530
+		}
1531
+		$per_page = absint($per_page);
1532
+		$offset   = ($current_page - 1) * $per_page;
1533
+		return array('limit' => array($offset, $per_page));
1534
+	}
1535
+
1536
+
1537
+	public function get_registration_status_array()
1538
+	{
1539
+		return self::$_reg_status;
1540
+	}
1541
+
1542
+
1543
+
1544
+
1545
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1546
+	/**
1547
+	 *        generates HTML for the View Registration Details Admin page
1548
+	 *
1549
+	 * @access protected
1550
+	 * @return void
1551
+	 * @throws DomainException
1552
+	 * @throws EE_Error
1553
+	 * @throws InvalidArgumentException
1554
+	 * @throws InvalidDataTypeException
1555
+	 * @throws InvalidInterfaceException
1556
+	 * @throws EntityNotFoundException
1557
+	 */
1558
+	protected function _registration_details()
1559
+	{
1560
+		$this->_template_args = array();
1561
+		$this->_set_registration_object();
1562
+		if (is_object($this->_registration)) {
1563
+			$transaction                                   = $this->_registration->transaction()
1564
+				? $this->_registration->transaction()
1565
+				: EE_Transaction::new_instance();
1566
+			$this->_session                                = $transaction->session_data();
1567
+			$event_id                                      = $this->_registration->event_ID();
1568
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1569
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1570
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1571
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1572
+			$this->_template_args['grand_total']           = $transaction->total();
1573
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1574
+			// link back to overview
1575
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1576
+			$this->_template_args['registration']                = $this->_registration;
1577
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1578
+				array(
1579
+					'action'   => 'default',
1580
+					'event_id' => $event_id,
1581
+				),
1582
+				REG_ADMIN_URL
1583
+			);
1584
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1585
+				array(
1586
+					'action' => 'default',
1587
+					'EVT_ID' => $event_id,
1588
+					'page'   => 'espresso_transactions',
1589
+				),
1590
+				admin_url('admin.php')
1591
+			);
1592
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1593
+				array(
1594
+					'page'   => 'espresso_events',
1595
+					'action' => 'edit',
1596
+					'post'   => $event_id,
1597
+				),
1598
+				admin_url('admin.php')
1599
+			);
1600
+			//next and previous links
1601
+			$next_reg                                      = $this->_registration->next(
1602
+				null,
1603
+				array(),
1604
+				'REG_ID'
1605
+			);
1606
+			$this->_template_args['next_registration']     = $next_reg
1607
+				? $this->_next_link(
1608
+					EE_Admin_Page::add_query_args_and_nonce(
1609
+						array(
1610
+							'action'  => 'view_registration',
1611
+							'_REG_ID' => $next_reg['REG_ID'],
1612
+						),
1613
+						REG_ADMIN_URL
1614
+					),
1615
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1616
+				)
1617
+				: '';
1618
+			$previous_reg                                  = $this->_registration->previous(
1619
+				null,
1620
+				array(),
1621
+				'REG_ID'
1622
+			);
1623
+			$this->_template_args['previous_registration'] = $previous_reg
1624
+				? $this->_previous_link(
1625
+					EE_Admin_Page::add_query_args_and_nonce(
1626
+						array(
1627
+							'action'  => 'view_registration',
1628
+							'_REG_ID' => $previous_reg['REG_ID'],
1629
+						),
1630
+						REG_ADMIN_URL
1631
+					),
1632
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1633
+				)
1634
+				: '';
1635
+			// grab header
1636
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1637
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1638
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639
+				$template_path,
1640
+				$this->_template_args,
1641
+				true
1642
+			);
1643
+		} else {
1644
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1645
+		}
1646
+		// the details template wrapper
1647
+		$this->display_admin_page_with_sidebar();
1648
+	}
1649
+
1650
+
1651
+	protected function _registration_details_metaboxes()
1652
+	{
1653
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1654
+		$this->_set_registration_object();
1655
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1656
+		add_meta_box('edit-reg-status-mbox', esc_html__('Registration Status', 'event_espresso'),
1657
+			array($this, 'set_reg_status_buttons_metabox'), $this->wp_page_slug, 'normal', 'high');
1658
+		add_meta_box('edit-reg-details-mbox', esc_html__('Registration Details', 'event_espresso'),
1659
+			array($this, '_reg_details_meta_box'), $this->wp_page_slug, 'normal', 'high');
1660
+		if ($attendee instanceof EE_Attendee
1661
+			&& EE_Registry::instance()->CAP->current_user_can(
1662
+				'ee_edit_registration',
1663
+				'edit-reg-questions-mbox',
1664
+				$this->_registration->ID()
1665
+			)
1666
+		) {
1667
+			add_meta_box(
1668
+				'edit-reg-questions-mbox',
1669
+				esc_html__('Registration Form Answers', 'event_espresso'),
1670
+				array($this, '_reg_questions_meta_box'),
1671
+				$this->wp_page_slug,
1672
+				'normal',
1673
+				'high'
1674
+			);
1675
+		}
1676
+		add_meta_box(
1677
+			'edit-reg-registrant-mbox',
1678
+			esc_html__('Contact Details', 'event_espresso'),
1679
+			array($this, '_reg_registrant_side_meta_box'),
1680
+			$this->wp_page_slug,
1681
+			'side',
1682
+			'high'
1683
+		);
1684
+		if ($this->_registration->group_size() > 1) {
1685
+			add_meta_box(
1686
+				'edit-reg-attendees-mbox',
1687
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1688
+				array($this, '_reg_attendees_meta_box'),
1689
+				$this->wp_page_slug,
1690
+				'normal',
1691
+				'high'
1692
+			);
1693
+		}
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * set_reg_status_buttons_metabox
1699
+	 *
1700
+	 * @access protected
1701
+	 * @return string
1702
+	 * @throws \EE_Error
1703
+	 */
1704
+	public function set_reg_status_buttons_metabox()
1705
+	{
1706
+		$this->_set_registration_object();
1707
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1708
+		echo $change_reg_status_form->form_open(
1709
+			self::add_query_args_and_nonce(
1710
+				array(
1711
+					'action' => 'change_reg_status',
1712
+				),
1713
+				REG_ADMIN_URL
1714
+			)
1715
+		);
1716
+		echo $change_reg_status_form->get_html();
1717
+		echo $change_reg_status_form->form_close();
1718
+	}
1719
+
1720
+
1721
+	/**
1722
+	 * @return EE_Form_Section_Proper
1723
+	 * @throws EE_Error
1724
+	 * @throws InvalidArgumentException
1725
+	 * @throws InvalidDataTypeException
1726
+	 * @throws InvalidInterfaceException
1727
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1728
+	 */
1729
+	protected function _generate_reg_status_change_form()
1730
+	{
1731
+		return new EE_Form_Section_Proper(array(
1732
+			'name'            => 'reg_status_change_form',
1733
+			'html_id'         => 'reg-status-change-form',
1734
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1735
+			'subsections'     => array(
1736
+				'return'             => new EE_Hidden_Input(array(
1737
+					'name'    => 'return',
1738
+					'default' => 'view_registration',
1739
+				)),
1740
+				'REG_ID'             => new EE_Hidden_Input(array(
1741
+					'name'    => 'REG_ID',
1742
+					'default' => $this->_registration->ID(),
1743
+				)),
1744
+				'current_status'     => new EE_Form_Section_HTML(
1745
+					EEH_HTML::tr(
1746
+						EEH_HTML::th(
1747
+							EEH_HTML::label(
1748
+								EEH_HTML::strong(esc_html__('Current Registration Status', 'event_espresso')
1749
+								)
1750
+							)
1751
+						)
1752
+						. EEH_HTML::td(
1753
+							EEH_HTML::strong(
1754
+								$this->_registration->pretty_status(),
1755
+								'',
1756
+								'status-' . $this->_registration->status_ID(),
1757
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758
+							)
1759
+						)
1760
+					)
1761
+				),
1762
+				'reg_status'         => new EE_Select_Input(
1763
+					$this->_get_reg_statuses(),
1764
+					array(
1765
+						'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1766
+						'default'         => $this->_registration->status_ID(),
1767
+					)
1768
+				),
1769
+				'send_notifications' => new EE_Yes_No_Input(
1770
+					array(
1771
+						'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1772
+						'default'         => false,
1773
+						'html_help_text'  => esc_html__(
1774
+							'If set to "Yes", then the related messages will be sent to the registrant.',
1775
+							'event_espresso'
1776
+						),
1777
+					)
1778
+				),
1779
+				'submit'             => new EE_Submit_Input(
1780
+					array(
1781
+						'html_class'      => 'button-primary',
1782
+						'html_label_text' => '&nbsp;',
1783
+						'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1784
+					)
1785
+				),
1786
+			),
1787
+		));
1788
+	}
1789
+
1790
+
1791
+	/**
1792
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1793
+	 *
1794
+	 * @return array
1795
+	 * @throws EE_Error
1796
+	 * @throws InvalidArgumentException
1797
+	 * @throws InvalidDataTypeException
1798
+	 * @throws InvalidInterfaceException
1799
+	 * @throws EntityNotFoundException
1800
+	 */
1801
+	protected function _get_reg_statuses()
1802
+	{
1803
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1804
+		unset ($reg_status_array[EEM_Registration::status_id_incomplete]);
1805
+		// get current reg status
1806
+		$current_status = $this->_registration->status_ID();
1807
+		// is registration for free event? This will determine whether to display the pending payment option
1808
+		if (
1809
+			$current_status !== EEM_Registration::status_id_pending_payment
1810
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1811
+		) {
1812
+			unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1813
+		}
1814
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1815
+	}
1816
+
1817
+
1818
+	/**
1819
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1820
+	 *
1821
+	 * @param bool $status REG status given for changing registrations to.
1822
+	 * @param bool $notify Whether to send messages notifications or not.
1823
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1824
+	 * @throws EE_Error
1825
+	 * @throws InvalidArgumentException
1826
+	 * @throws InvalidDataTypeException
1827
+	 * @throws InvalidInterfaceException
1828
+	 * @throws ReflectionException
1829
+	 * @throws RuntimeException
1830
+	 * @throws EntityNotFoundException
1831
+	 */
1832
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1833
+	{
1834
+		if (isset($this->_req_data['reg_status_change_form'])) {
1835
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
+				? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1837
+				: array();
1838
+		} else {
1839
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1840
+				? (array)$this->_req_data['_REG_ID']
1841
+				: array();
1842
+		}
1843
+		// sanitize $REG_IDs
1844
+		$REG_IDs = array_map('absint', $REG_IDs);
1845
+		// and remove empty entries
1846
+		$REG_IDs = array_filter($REG_IDs);
1847
+
1848
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1849
+
1850
+		/**
1851
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1852
+		 * Currently this value is used downstream by the _process_resend_registration method.
1853
+		 *
1854
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1855
+		 * @param bool                     $status           The status registrations were changed to.
1856
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1857
+		 * @param Registrations_Admin_Page $admin_page_object
1858
+		 */
1859
+		$this->_req_data['_REG_ID'] = apply_filters(
1860
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1861
+			$result['REG_ID'],
1862
+			$status,
1863
+			$result['success'],
1864
+			$this
1865
+		);
1866
+
1867
+		//notify?
1868
+		if ($notify
1869
+			&& $result['success']
1870
+			&& ! empty($this->_req_data['_REG_ID'])
1871
+			&& EE_Registry::instance()->CAP->current_user_can(
1872
+				'ee_send_message',
1873
+				'espresso_registrations_resend_registration'
1874
+			)
1875
+		) {
1876
+			$this->_process_resend_registration();
1877
+		}
1878
+		return $result;
1879
+	}
1880
+
1881
+
1882
+	/**
1883
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1884
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1885
+	 *
1886
+	 * @param array  $REG_IDs
1887
+	 * @param string $status
1888
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1889
+	 *                        slug sent with setting the registration status.
1890
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1891
+	 * @throws EE_Error
1892
+	 * @throws InvalidArgumentException
1893
+	 * @throws InvalidDataTypeException
1894
+	 * @throws InvalidInterfaceException
1895
+	 * @throws ReflectionException
1896
+	 * @throws RuntimeException
1897
+	 * @throws EntityNotFoundException
1898
+	 */
1899
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1900
+	{
1901
+		$success = false;
1902
+		// typecast $REG_IDs
1903
+		$REG_IDs = (array)$REG_IDs;
1904
+		if ( ! empty($REG_IDs)) {
1905
+			$success = true;
1906
+			// set default status if none is passed
1907
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1908
+			$status_context = $notify
1909
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1910
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1911
+			//loop through REG_ID's and change status
1912
+			foreach ($REG_IDs as $REG_ID) {
1913
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1914
+				if ($registration instanceof EE_Registration) {
1915
+					$registration->set_status(
1916
+						$status,
1917
+						false,
1918
+						new Context(
1919
+							$status_context,
1920
+							esc_html__(
1921
+								'Manually triggered status change on a Registration Admin Page route.',
1922
+								'event_espresso'
1923
+							)
1924
+						)
1925
+					);
1926
+					$result = $registration->save();
1927
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1928
+					$success = $result !== false ? $success : false;
1929
+				}
1930
+			}
1931
+		}
1932
+
1933
+		//return $success and processed registrations
1934
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1935
+	}
1936
+
1937
+
1938
+	/**
1939
+	 * Common logic for setting up success message and redirecting to appropriate route
1940
+	 *
1941
+	 * @param  string $STS_ID status id for the registration changed to
1942
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1943
+	 * @return void
1944
+	 * @throws EE_Error
1945
+	 */
1946
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1947
+	{
1948
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1949
+			: array('success' => false);
1950
+		$success = isset($result['success']) && $result['success'];
1951
+		//setup success message
1952
+		if ($success) {
1953
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1954
+				$msg = sprintf(esc_html__('Registration status has been set to %s', 'event_espresso'),
1955
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1956
+			} else {
1957
+				$msg = sprintf(esc_html__('Registrations have been set to %s.', 'event_espresso'),
1958
+					EEH_Template::pretty_status($STS_ID, false, 'lower'));
1959
+			}
1960
+			EE_Error::add_success($msg);
1961
+		} else {
1962
+			EE_Error::add_error(
1963
+				esc_html__(
1964
+					'Something went wrong, and the status was not changed',
1965
+					'event_espresso'
1966
+				), __FILE__, __LINE__, __FUNCTION__
1967
+			);
1968
+		}
1969
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1970
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1971
+		} else {
1972
+			$route = array('action' => 'default');
1973
+		}
1974
+		//unset nonces
1975
+		foreach ($this->_req_data as $ref => $value) {
1976
+			if (strpos($ref, 'nonce') !== false) {
1977
+				unset($this->_req_data[$ref]);
1978
+				continue;
1979
+			}
1980
+			$value                 = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
1981
+			$this->_req_data[$ref] = $value;
1982
+		}
1983
+		//merge request vars so that the reloaded list table contains any existing filter query params
1984
+		$route = array_merge($this->_req_data, $route);
1985
+		$this->_redirect_after_action($success, '', '', $route, true);
1986
+	}
1987
+
1988
+
1989
+	/**
1990
+	 * incoming reg status change from reg details page.
1991
+	 *
1992
+	 * @return void
1993
+	 */
1994
+	protected function _change_reg_status()
1995
+	{
1996
+		$this->_req_data['return'] = 'view_registration';
1997
+		//set notify based on whether the send notifications toggle is set or not
1998
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1999
+		//$notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2000
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2001
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2002
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2003
+			case EEM_Registration::status_id_approved :
2004
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence') :
2005
+				$this->approve_registration($notify);
2006
+				break;
2007
+			case EEM_Registration::status_id_pending_payment :
2008
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence') :
2009
+				$this->pending_registration($notify);
2010
+				break;
2011
+			case EEM_Registration::status_id_not_approved :
2012
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence') :
2013
+				$this->not_approve_registration($notify);
2014
+				break;
2015
+			case EEM_Registration::status_id_declined :
2016
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence') :
2017
+				$this->decline_registration($notify);
2018
+				break;
2019
+			case EEM_Registration::status_id_cancelled :
2020
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence') :
2021
+				$this->cancel_registration($notify);
2022
+				break;
2023
+			case EEM_Registration::status_id_wait_list :
2024
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence') :
2025
+				$this->wait_list_registration($notify);
2026
+				break;
2027
+			case EEM_Registration::status_id_incomplete :
2028
+			default :
2029
+				$result['success'] = false;
2030
+				unset($this->_req_data['return']);
2031
+				$this->_reg_status_change_return('', false);
2032
+				break;
2033
+		}
2034
+	}
2035
+
2036
+
2037
+	/**
2038
+	 * Callback for bulk action routes.
2039
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2040
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2041
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2042
+	 * when an action is happening on just a single registration).
2043
+	 * @param      $action
2044
+	 * @param bool $notify
2045
+	 */
2046
+	protected function bulk_action_on_registrations($action, $notify = false) {
2047
+		do_action(
2048
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2049
+			$this,
2050
+			$action,
2051
+			$notify
2052
+		);
2053
+		$method = $action . '_registration';
2054
+		if (method_exists($this, $method)) {
2055
+			$this->$method($notify);
2056
+		}
2057
+	}
2058
+
2059
+
2060
+	/**
2061
+	 * approve_registration
2062
+	 *
2063
+	 * @access protected
2064
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2065
+	 * @return void
2066
+	 */
2067
+	protected function approve_registration($notify = false)
2068
+	{
2069
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 *        decline_registration
2075
+	 *
2076
+	 * @access protected
2077
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2078
+	 * @return void
2079
+	 */
2080
+	protected function decline_registration($notify = false)
2081
+	{
2082
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2083
+	}
2084
+
2085
+
2086
+	/**
2087
+	 *        cancel_registration
2088
+	 *
2089
+	 * @access protected
2090
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2091
+	 * @return void
2092
+	 */
2093
+	protected function cancel_registration($notify = false)
2094
+	{
2095
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2096
+	}
2097
+
2098
+
2099
+	/**
2100
+	 *        not_approve_registration
2101
+	 *
2102
+	 * @access protected
2103
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2104
+	 * @return void
2105
+	 */
2106
+	protected function not_approve_registration($notify = false)
2107
+	{
2108
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2109
+	}
2110
+
2111
+
2112
+	/**
2113
+	 *        decline_registration
2114
+	 *
2115
+	 * @access protected
2116
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2117
+	 * @return void
2118
+	 */
2119
+	protected function pending_registration($notify = false)
2120
+	{
2121
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2122
+	}
2123
+
2124
+
2125
+	/**
2126
+	 * waitlist_registration
2127
+	 *
2128
+	 * @access protected
2129
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2130
+	 * @return void
2131
+	 */
2132
+	protected function wait_list_registration($notify = false)
2133
+	{
2134
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2135
+	}
2136
+
2137
+
2138
+	/**
2139
+	 *        generates HTML for the Registration main meta box
2140
+	 *
2141
+	 * @access public
2142
+	 * @return void
2143
+	 * @throws DomainException
2144
+	 * @throws EE_Error
2145
+	 * @throws InvalidArgumentException
2146
+	 * @throws InvalidDataTypeException
2147
+	 * @throws InvalidInterfaceException
2148
+	 * @throws ReflectionException
2149
+	 * @throws EntityNotFoundException
2150
+	 */
2151
+	public function _reg_details_meta_box()
2152
+	{
2153
+		EEH_Autoloader::register_line_item_display_autoloaders();
2154
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2155
+		EE_Registry::instance()->load_helper('Line_Item');
2156
+		$transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2157
+			: EE_Transaction::new_instance();
2158
+		$this->_session = $transaction->session_data();
2159
+		$filters        = new EE_Line_Item_Filter_Collection();
2160
+		//$filters->add( new EE_Non_Zero_Line_Item_Filter() );
2161
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2162
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor($filters,
2163
+			$transaction->total_line_item());
2164
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
2165
+		$line_item_display                       = new EE_Line_Item_Display('reg_admin_table',
2166
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy');
2167
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2168
+			$filtered_line_item_tree,
2169
+			array('EE_Registration' => $this->_registration)
2170
+		);
2171
+		$attendee                                = $this->_registration->attendee();
2172
+		if (EE_Registry::instance()->CAP->current_user_can(
2173
+			'ee_read_transaction',
2174
+			'espresso_transactions_view_transaction'
2175
+		)) {
2176
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2177
+				EE_Admin_Page::add_query_args_and_nonce(
2178
+					array(
2179
+						'action' => 'view_transaction',
2180
+						'TXN_ID' => $transaction->ID(),
2181
+					),
2182
+					TXN_ADMIN_URL
2183
+				),
2184
+				esc_html__(' View Transaction', 'event_espresso'),
2185
+				'button secondary-button right',
2186
+				'dashicons dashicons-cart'
2187
+			);
2188
+		} else {
2189
+			$this->_template_args['view_transaction_button'] = '';
2190
+		}
2191
+		if ($attendee instanceof EE_Attendee
2192
+			&& EE_Registry::instance()->CAP->current_user_can(
2193
+				'ee_send_message',
2194
+				'espresso_registrations_resend_registration'
2195
+			)
2196
+		) {
2197
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2198
+				EE_Admin_Page::add_query_args_and_nonce(
2199
+					array(
2200
+						'action'      => 'resend_registration',
2201
+						'_REG_ID'     => $this->_registration->ID(),
2202
+						'redirect_to' => 'view_registration',
2203
+					),
2204
+					REG_ADMIN_URL
2205
+				),
2206
+				esc_html__(' Resend Registration', 'event_espresso'),
2207
+				'button secondary-button right',
2208
+				'dashicons dashicons-email-alt'
2209
+			);
2210
+		} else {
2211
+			$this->_template_args['resend_registration_button'] = '';
2212
+		}
2213
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2214
+		$payment                               = $transaction->get_first_related('Payment');
2215
+		$payment                               = ! $payment instanceof EE_Payment
2216
+			? EE_Payment::new_instance()
2217
+			: $payment;
2218
+		$payment_method                        = $payment->get_first_related('Payment_Method');
2219
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
2220
+			? EE_Payment_Method::new_instance()
2221
+			: $payment_method;
2222
+		$reg_details                           = array(
2223
+			'payment_method'       => $payment_method->name(),
2224
+			'response_msg'         => $payment->gateway_response(),
2225
+			'registration_id'      => $this->_registration->get('REG_code'),
2226
+			'registration_session' => $this->_registration->session_ID(),
2227
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2228
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2229
+		);
2230
+		if (isset($reg_details['registration_id'])) {
2231
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2232
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2233
+				'Registration ID',
2234
+				'event_espresso'
2235
+			);
2236
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2237
+		}
2238
+		if (isset($reg_details['payment_method'])) {
2239
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2240
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2241
+				'Most Recent Payment Method',
2242
+				'event_espresso'
2243
+			);
2244
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2245
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2246
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2247
+				'Payment method response',
2248
+				'event_espresso'
2249
+			);
2250
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2251
+		}
2252
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2254
+			'Registration Session',
2255
+			'event_espresso'
2256
+		);
2257
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2258
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2259
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2260
+			'Registration placed from IP',
2261
+			'event_espresso'
2262
+		);
2263
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2264
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2265
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__('Registrant User Agent',
2266
+			'event_espresso');
2267
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2268
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2269
+			array(
2270
+				'action'   => 'default',
2271
+				'event_id' => $this->_registration->event_ID(),
2272
+			),
2273
+			REG_ADMIN_URL
2274
+		);
2275
+		$this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276
+		$this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277
+		$template_path                                                        =
2278
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2279
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280
+	}
2281
+
2282
+
2283
+	/**
2284
+	 * generates HTML for the Registration Questions meta box.
2285
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2286
+	 * otherwise uses new forms system
2287
+	 *
2288
+	 * @access public
2289
+	 * @return void
2290
+	 * @throws DomainException
2291
+	 * @throws EE_Error
2292
+	 */
2293
+	public function _reg_questions_meta_box()
2294
+	{
2295
+		//allow someone to override this method entirely
2296
+		if (apply_filters('FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default', true, $this,
2297
+			$this->_registration)) {
2298
+			$form                                              = $this->_get_reg_custom_questions_form(
2299
+				$this->_registration->ID()
2300
+			);
2301
+			$this->_template_args['att_questions']             = count($form->subforms()) > 0
2302
+				? $form->get_html_and_js()
2303
+				: '';
2304
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305
+			$this->_template_args['REG_ID']                    = $this->_registration->ID();
2306
+			$template_path                                     =
2307
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2308
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309
+		}
2310
+	}
2311
+
2312
+
2313
+	/**
2314
+	 * form_before_question_group
2315
+	 *
2316
+	 * @deprecated    as of 4.8.32.rc.000
2317
+	 * @access        public
2318
+	 * @param        string $output
2319
+	 * @return        string
2320
+	 */
2321
+	public function form_before_question_group($output)
2322
+	{
2323
+		EE_Error::doing_it_wrong(
2324
+			__CLASS__ . '::' . __FUNCTION__,
2325
+			esc_html__(
2326
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327
+				'event_espresso'
2328
+			),
2329
+			'4.8.32.rc.000'
2330
+		);
2331
+		return '
2332 2332
 	<table class="form-table ee-width-100">
2333 2333
 		<tbody>
2334 2334
 			';
2335
-    }
2336
-
2337
-
2338
-    /**
2339
-     * form_after_question_group
2340
-     *
2341
-     * @deprecated    as of 4.8.32.rc.000
2342
-     * @access        public
2343
-     * @param        string $output
2344
-     * @return        string
2345
-     */
2346
-    public function form_after_question_group($output)
2347
-    {
2348
-        EE_Error::doing_it_wrong(
2349
-            __CLASS__ . '::' . __FUNCTION__,
2350
-            esc_html__(
2351
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352
-                'event_espresso'
2353
-            ),
2354
-            '4.8.32.rc.000'
2355
-        );
2356
-        return '
2335
+	}
2336
+
2337
+
2338
+	/**
2339
+	 * form_after_question_group
2340
+	 *
2341
+	 * @deprecated    as of 4.8.32.rc.000
2342
+	 * @access        public
2343
+	 * @param        string $output
2344
+	 * @return        string
2345
+	 */
2346
+	public function form_after_question_group($output)
2347
+	{
2348
+		EE_Error::doing_it_wrong(
2349
+			__CLASS__ . '::' . __FUNCTION__,
2350
+			esc_html__(
2351
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352
+				'event_espresso'
2353
+			),
2354
+			'4.8.32.rc.000'
2355
+		);
2356
+		return '
2357 2357
 			<tr class="hide-if-no-js">
2358 2358
 				<th> </th>
2359 2359
 				<td class="reg-admin-edit-attendee-question-td">
2360 2360
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2361
-               . esc_attr__('click to edit question', 'event_espresso')
2362
-               . '">
2361
+			   . esc_attr__('click to edit question', 'event_espresso')
2362
+			   . '">
2363 2363
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2364
-               . esc_html__('edit the above question group', 'event_espresso')
2365
-               . '</span>
2364
+			   . esc_html__('edit the above question group', 'event_espresso')
2365
+			   . '</span>
2366 2366
 						<div class="dashicons dashicons-edit"></div>
2367 2367
 					</a>
2368 2368
 				</td>
@@ -2370,579 +2370,579 @@  discard block
 block discarded – undo
2370 2370
 		</tbody>
2371 2371
 	</table>
2372 2372
 ';
2373
-    }
2374
-
2375
-
2376
-    /**
2377
-     * form_form_field_label_wrap
2378
-     *
2379
-     * @deprecated    as of 4.8.32.rc.000
2380
-     * @access        public
2381
-     * @param        string $label
2382
-     * @return        string
2383
-     */
2384
-    public function form_form_field_label_wrap($label)
2385
-    {
2386
-        EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2388
-            esc_html__(
2389
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
-                'event_espresso'
2391
-            ),
2392
-            '4.8.32.rc.000'
2393
-        );
2394
-        return '
2373
+	}
2374
+
2375
+
2376
+	/**
2377
+	 * form_form_field_label_wrap
2378
+	 *
2379
+	 * @deprecated    as of 4.8.32.rc.000
2380
+	 * @access        public
2381
+	 * @param        string $label
2382
+	 * @return        string
2383
+	 */
2384
+	public function form_form_field_label_wrap($label)
2385
+	{
2386
+		EE_Error::doing_it_wrong(
2387
+			__CLASS__ . '::' . __FUNCTION__,
2388
+			esc_html__(
2389
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
+				'event_espresso'
2391
+			),
2392
+			'4.8.32.rc.000'
2393
+		);
2394
+		return '
2395 2395
 			<tr>
2396 2396
 				<th>
2397 2397
 					' . $label . '
2398 2398
 				</th>';
2399
-    }
2400
-
2401
-
2402
-    /**
2403
-     * form_form_field_input__wrap
2404
-     *
2405
-     * @deprecated    as of 4.8.32.rc.000
2406
-     * @access        public
2407
-     * @param        string $input
2408
-     * @return        string
2409
-     */
2410
-    public function form_form_field_input__wrap($input)
2411
-    {
2412
-        EE_Error::doing_it_wrong(
2413
-            __CLASS__ . '::' . __FUNCTION__,
2414
-            esc_html__(
2415
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416
-                'event_espresso'
2417
-            ),
2418
-            '4.8.32.rc.000'
2419
-        );
2420
-        return '
2399
+	}
2400
+
2401
+
2402
+	/**
2403
+	 * form_form_field_input__wrap
2404
+	 *
2405
+	 * @deprecated    as of 4.8.32.rc.000
2406
+	 * @access        public
2407
+	 * @param        string $input
2408
+	 * @return        string
2409
+	 */
2410
+	public function form_form_field_input__wrap($input)
2411
+	{
2412
+		EE_Error::doing_it_wrong(
2413
+			__CLASS__ . '::' . __FUNCTION__,
2414
+			esc_html__(
2415
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416
+				'event_espresso'
2417
+			),
2418
+			'4.8.32.rc.000'
2419
+		);
2420
+		return '
2421 2421
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2422 2422
 					' . $input . '
2423 2423
 				</td>
2424 2424
 			</tr>';
2425
-    }
2426
-
2427
-
2428
-    /**
2429
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2430
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2431
-     * to display the page
2432
-     *
2433
-     * @access protected
2434
-     * @return void
2435
-     * @throws EE_Error
2436
-     */
2437
-    protected function _update_attendee_registration_form()
2438
-    {
2439
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2440
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2441
-            $REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2442
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2443
-            if ($success) {
2444
-                $what  = esc_html__('Registration Form', 'event_espresso');
2445
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2446
-                    : array('action' => 'default');
2447
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2448
-            }
2449
-        }
2450
-    }
2451
-
2452
-
2453
-    /**
2454
-     * Gets the form for saving registrations custom questions (if done
2455
-     * previously retrieves the cached form object, which may have validation errors in it)
2456
-     *
2457
-     * @param int $REG_ID
2458
-     * @return EE_Registration_Custom_Questions_Form
2459
-     * @throws EE_Error
2460
-     * @throws InvalidArgumentException
2461
-     * @throws InvalidDataTypeException
2462
-     * @throws InvalidInterfaceException
2463
-     */
2464
-    protected function _get_reg_custom_questions_form($REG_ID)
2465
-    {
2466
-        if ( ! $this->_reg_custom_questions_form) {
2467
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2468
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470
-            );
2471
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2472
-        }
2473
-        return $this->_reg_custom_questions_form;
2474
-    }
2475
-
2476
-
2477
-    /**
2478
-     * Saves
2479
-     *
2480
-     * @access private
2481
-     * @param bool $REG_ID
2482
-     * @return bool
2483
-     * @throws EE_Error
2484
-     * @throws InvalidArgumentException
2485
-     * @throws InvalidDataTypeException
2486
-     * @throws InvalidInterfaceException
2487
-     */
2488
-    private function _save_reg_custom_questions_form($REG_ID = false)
2489
-    {
2490
-        if ( ! $REG_ID) {
2491
-            EE_Error::add_error(
2492
-                esc_html__(
2493
-                    'An error occurred. No registration ID was received.', 'event_espresso'),
2494
-                __FILE__, __FUNCTION__, __LINE__
2495
-            );
2496
-        }
2497
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2498
-        $form->receive_form_submission($this->_req_data);
2499
-        $success = false;
2500
-        if ($form->is_valid()) {
2501
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2503
-                    $where_conditions    = array(
2504
-                        'QST_ID' => $question_id,
2505
-                        'REG_ID' => $REG_ID,
2506
-                    );
2507
-                    $possibly_new_values = array(
2508
-                        'ANS_value' => $input->normalized_value(),
2509
-                    );
2510
-                    $answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2511
-                    if ($answer instanceof EE_Answer) {
2512
-                        $success = $answer->save($possibly_new_values);
2513
-                    } else {
2514
-                        //insert it then
2515
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2516
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2517
-                        $success     = $answer->save();
2518
-                    }
2519
-                }
2520
-            }
2521
-        } else {
2522
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2523
-        }
2524
-        return $success;
2525
-    }
2526
-
2527
-
2528
-    /**
2529
-     *        generates HTML for the Registration main meta box
2530
-     *
2531
-     * @access public
2532
-     * @return void
2533
-     * @throws DomainException
2534
-     * @throws EE_Error
2535
-     * @throws InvalidArgumentException
2536
-     * @throws InvalidDataTypeException
2537
-     * @throws InvalidInterfaceException
2538
-     */
2539
-    public function _reg_attendees_meta_box()
2540
-    {
2541
-        $REG = EEM_Registration::instance();
2542
-        //get all other registrations on this transaction, and cache
2543
-        //the attendees for them so we don't have to run another query using force_join
2544
-        $registrations                           = $REG->get_all(array(
2545
-            array(
2546
-                'TXN_ID' => $this->_registration->transaction_ID(),
2547
-                'REG_ID' => array('!=', $this->_registration->ID()),
2548
-            ),
2549
-            'force_join' => array('Attendee'),
2550
-        ));
2551
-        $this->_template_args['attendees']       = array();
2552
-        $this->_template_args['attendee_notice'] = '';
2553
-        if (empty($registrations)
2554
-            || (is_array($registrations)
2555
-                && ! EEH_Array::get_one_item_from_array($registrations))
2556
-        ) {
2557
-            EE_Error::add_error(
2558
-                esc_html__(
2559
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2560
-                    'event_espresso'
2561
-                ), __FILE__, __FUNCTION__, __LINE__
2562
-            );
2563
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2564
-        } else {
2565
-            $att_nmbr = 1;
2566
-            foreach ($registrations as $registration) {
2567
-                /* @var $registration EE_Registration */
2568
-                $attendee                                                    = $registration->attendee()
2569
-                    ? $registration->attendee()
2570
-                    : EEM_Attendee::instance()
2571
-                                  ->create_default_object();
2572
-                $this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2573
-                $this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2574
-                $this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2575
-                $this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2576
-                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2577
-                $this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2578
-                    ', ',
2579
-                    $attendee->full_address_as_array()
2580
-                );
2581
-                $this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2582
-                    array(
2583
-                        'action' => 'edit_attendee',
2584
-                        'post'   => $attendee->ID(),
2585
-                    ),
2586
-                    REG_ADMIN_URL
2587
-                );
2588
-                $this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2589
-                $att_nmbr++;
2590
-            }
2591
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592
-        }
2593
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2594
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595
-    }
2596
-
2597
-
2598
-    /**
2599
-     *        generates HTML for the Edit Registration side meta box
2600
-     *
2601
-     * @access public
2602
-     * @return void
2603
-     * @throws DomainException
2604
-     * @throws EE_Error
2605
-     * @throws InvalidArgumentException
2606
-     * @throws InvalidDataTypeException
2607
-     * @throws InvalidInterfaceException
2608
-     */
2609
-    public function _reg_registrant_side_meta_box()
2610
-    {
2611
-        /*@var $attendee EE_Attendee */
2612
-        $att_check = $this->_registration->attendee();
2613
-        $attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2614
-        //now let's determine if this is not the primary registration.  If it isn't then we set the
2615
-        //primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2616
-        //primary registration object (that way we know if we need to show create button or not)
2617
-        if ( ! $this->_registration->is_primary_registrant()) {
2618
-            $primary_registration = $this->_registration->get_primary_registration();
2619
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2620
-                : null;
2621
-            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2622
-                //in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2623
-                //custom attendee object so let's not worry about the primary reg.
2624
-                $primary_registration = null;
2625
-            }
2626
-        } else {
2627
-            $primary_registration = null;
2628
-        }
2629
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2630
-        $this->_template_args['fname']             = $attendee->fname();
2631
-        $this->_template_args['lname']             = $attendee->lname();
2632
-        $this->_template_args['email']             = $attendee->email();
2633
-        $this->_template_args['phone']             = $attendee->phone();
2634
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635
-        //edit link
2636
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2637
-            'action' => 'edit_attendee',
2638
-            'post'   => $attendee->ID(),
2639
-        ), REG_ADMIN_URL);
2640
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641
-        //create link
2642
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2643
-            ? EE_Admin_Page::add_query_args_and_nonce(array(
2644
-                'action'  => 'duplicate_attendee',
2645
-                '_REG_ID' => $this->_registration->ID(),
2646
-            ), REG_ADMIN_URL) : '';
2647
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648
-        $this->_template_args['att_check']    = $att_check;
2649
-        $template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2650
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651
-    }
2652
-
2653
-
2654
-    /**
2655
-     * trash or restore registrations
2656
-     *
2657
-     * @param  boolean $trash whether to archive or restore
2658
-     * @return void
2659
-     * @throws EE_Error
2660
-     * @throws InvalidArgumentException
2661
-     * @throws InvalidDataTypeException
2662
-     * @throws InvalidInterfaceException
2663
-     * @throws RuntimeException
2664
-     * @access protected
2665
-     */
2666
-    protected function _trash_or_restore_registrations($trash = true)
2667
-    {
2668
-        //if empty _REG_ID then get out because there's nothing to do
2669
-        if (empty($this->_req_data['_REG_ID'])) {
2670
-            EE_Error::add_error(
2671
-                sprintf(
2672
-                    esc_html__(
2673
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2674
-                        'event_espresso'
2675
-                    ),
2676
-                    $trash ? 'trash' : 'restore'
2677
-                ),
2678
-                __FILE__, __LINE__, __FUNCTION__
2679
-            );
2680
-            $this->_redirect_after_action(false, '', '', array(), true);
2681
-        }
2682
-        $success = 0;
2683
-        $overwrite_msgs = false;
2684
-        //Checkboxes
2685
-        if ( ! is_array($this->_req_data['_REG_ID'])) {
2686
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2687
-        }
2688
-        $reg_count = count($this->_req_data['_REG_ID']);
2689
-        // cycle thru checkboxes
2690
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2691
-            /** @var EE_Registration $REG */
2692
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693
-            $payments = $REG->registration_payments();
2694
-            if (! empty($payments)) {
2695
-                $name = $REG->attendee() instanceof EE_Attendee
2696
-                    ? $REG->attendee()->full_name()
2697
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2698
-                $overwrite_msgs = true;
2699
-                EE_Error::add_error(
2700
-                    sprintf(
2701
-                        esc_html__(
2702
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2703
-                            'event_espresso'
2704
-                        ),
2705
-                        $name
2706
-                    ),
2707
-                    __FILE__, __FUNCTION__, __LINE__
2708
-                );
2709
-                //can't trash this registration because it has payments.
2710
-                continue;
2711
-            }
2712
-            $updated = $trash ? $REG->delete() : $REG->restore();
2713
-            if ($updated) {
2714
-                $success++;
2715
-            }
2716
-        }
2717
-        $this->_redirect_after_action(
2718
-            $success === $reg_count, // were ALL registrations affected?
2719
-            $success > 1
2720
-                ? esc_html__('Registrations', 'event_espresso')
2721
-                : esc_html__('Registration', 'event_espresso'),
2722
-            $trash
2723
-                ? esc_html__('moved to the trash', 'event_espresso')
2724
-                : esc_html__('restored', 'event_espresso'),
2725
-            array('action' => 'default'),
2726
-            $overwrite_msgs
2727
-        );
2728
-    }
2729
-
2730
-
2731
-    /**
2732
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2733
-     * registration but also.
2734
-     * 1. Removing relations to EE_Attendee
2735
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2736
-     * ALSO trashed.
2737
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2738
-     * 4. Removing relationships between all tickets and the related registrations
2739
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2740
-     * 6. Deleting permanently any related Checkins.
2741
-     *
2742
-     * @return void
2743
-     * @throws EE_Error
2744
-     * @throws InvalidArgumentException
2745
-     * @throws InvalidDataTypeException
2746
-     * @throws InvalidInterfaceException
2747
-     */
2748
-    protected function _delete_registrations()
2749
-    {
2750
-        $REG_MDL = EEM_Registration::instance();
2751
-        $success = 1;
2752
-        //Checkboxes
2753
-        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2754
-            // if array has more than one element than success message should be plural
2755
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2756
-            // cycle thru checkboxes
2757
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2758
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2759
-                if ( ! $REG instanceof EE_Registration) {
2760
-                    continue;
2761
-                }
2762
-                $deleted = $this->_delete_registration($REG);
2763
-                if ( ! $deleted) {
2764
-                    $success = 0;
2765
-                }
2766
-            }
2767
-        } else {
2768
-            // grab single id and delete
2769
-            $REG_ID  = $this->_req_data['_REG_ID'];
2770
-            $REG     = $REG_MDL->get_one_by_ID($REG_ID);
2771
-            $deleted = $this->_delete_registration($REG);
2772
-            if ( ! $deleted) {
2773
-                $success = 0;
2774
-            }
2775
-        }
2776
-        $what        = $success > 1
2777
-            ? esc_html__('Registrations', 'event_espresso')
2778
-            : esc_html__('Registration', 'event_espresso');
2779
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2780
-        $this->_redirect_after_action(
2781
-            $success,
2782
-            $what,
2783
-            $action_desc,
2784
-            array('action' => 'default'),
2785
-            true
2786
-        );
2787
-    }
2788
-
2789
-
2790
-    /**
2791
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2792
-     * models get affected.
2793
-     *
2794
-     * @param  EE_Registration $REG registration to be deleted permenantly
2795
-     * @return bool true = successful deletion, false = fail.
2796
-     * @throws EE_Error
2797
-     */
2798
-    protected function _delete_registration(EE_Registration $REG)
2799
-    {
2800
-        //first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2801
-        //registrations on the transaction that are NOT trashed.
2802
-        $TXN         = $REG->get_first_related('Transaction');
2803
-        $REGS        = $TXN->get_many_related('Registration');
2804
-        $all_trashed = true;
2805
-        foreach ($REGS as $registration) {
2806
-            if ( ! $registration->get('REG_deleted')) {
2807
-                $all_trashed = false;
2808
-            }
2809
-        }
2810
-        if ( ! $all_trashed) {
2811
-            EE_Error::add_error(
2812
-                esc_html__(
2813
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2814
-                    'event_espresso'
2815
-                ),
2816
-                __FILE__, __FUNCTION__, __LINE__
2817
-            );
2818
-            return false;
2819
-        }
2820
-        //k made it here so that means we can delete all the related transactions and their answers (but let's do them
2821
-        //separately from THIS one).
2822
-        foreach ($REGS as $registration) {
2823
-            //delete related answers
2824
-            $registration->delete_related_permanently('Answer');
2825
-            //remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2826
-            $attendee = $registration->get_first_related('Attendee');
2827
-            if ($attendee instanceof EE_Attendee) {
2828
-                $registration->_remove_relation_to($attendee, 'Attendee');
2829
-            }
2830
-            //now remove relationships to tickets on this registration.
2831
-            $registration->_remove_relations('Ticket');
2832
-            //now delete permanently the checkins related to this registration.
2833
-            $registration->delete_related_permanently('Checkin');
2834
-            if ($registration->ID() === $REG->ID()) {
2835
-                continue;
2836
-            } //we don't want to delete permanently the existing registration just yet.
2837
-            //remove relation to transaction for these registrations if NOT the existing registrations
2838
-            $registration->_remove_relations('Transaction');
2839
-            //delete permanently any related messages.
2840
-            $registration->delete_related_permanently('Message');
2841
-            //now delete this registration permanently
2842
-            $registration->delete_permanently();
2843
-        }
2844
-        //now all related registrations on the transaction are handled.  So let's just handle this registration itself
2845
-        // (the transaction and line items should be all that's left).
2846
-        // delete the line items related to the transaction for this registration.
2847
-        $TXN->delete_related_permanently('Line_Item');
2848
-        //we need to remove all the relationships on the transaction
2849
-        $TXN->delete_related_permanently('Payment');
2850
-        $TXN->delete_related_permanently('Extra_Meta');
2851
-        $TXN->delete_related_permanently('Message');
2852
-        //now we can delete this REG permanently (and the transaction of course)
2853
-        $REG->delete_related_permanently('Transaction');
2854
-        return $REG->delete_permanently();
2855
-    }
2856
-
2857
-
2858
-    /**
2859
-     *    generates HTML for the Register New Attendee Admin page
2860
-     *
2861
-     * @access private
2862
-     * @throws DomainException
2863
-     * @throws EE_Error
2864
-     */
2865
-    public function new_registration()
2866
-    {
2867
-        if ( ! $this->_set_reg_event()) {
2868
-            throw new EE_Error(
2869
-                esc_html__(
2870
-                    'Unable to continue with registering because there is no Event ID in the request',
2871
-                    'event_espresso'
2872
-                )
2873
-            );
2874
-        }
2875
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2876
-        // gotta start with a clean slate if we're not coming here via ajax
2877
-        if ( ! defined('DOING_AJAX')
2878
-             && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2879
-        ) {
2880
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2881
-        }
2882
-        $this->_template_args['event_name'] = '';
2883
-        // event name
2884
-        if ($this->_reg_event) {
2885
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2886
-            $edit_event_url                     = self::add_query_args_and_nonce(array(
2887
-                'action' => 'edit',
2888
-                'post'   => $this->_reg_event->ID(),
2889
-            ), EVENTS_ADMIN_URL);
2890
-            $edit_event_lnk                     = '<a href="'
2891
-                                                  . $edit_event_url
2892
-                                                  . '" title="'
2893
-                                                  . esc_attr__('Edit ', 'event_espresso')
2894
-                                                  . $this->_reg_event->name()
2895
-                                                  . '">'
2896
-                                                  . esc_html__('Edit Event', 'event_espresso')
2897
-                                                  . '</a>';
2898
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2899
-                                                   . $edit_event_lnk
2900
-                                                   . '</span>';
2901
-        }
2902
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2903
-        if (defined('DOING_AJAX')) {
2904
-            $this->_return_json();
2905
-        }
2906
-        // grab header
2907
-        $template_path                              =
2908
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2909
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910
-            $this->_template_args, true);
2911
-        //$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2912
-        // the details template wrapper
2913
-        $this->display_admin_page_with_sidebar();
2914
-    }
2915
-
2916
-
2917
-    /**
2918
-     * This returns the content for a registration step
2919
-     *
2920
-     * @access protected
2921
-     * @return string html
2922
-     * @throws DomainException
2923
-     * @throws EE_Error
2924
-     * @throws InvalidArgumentException
2925
-     * @throws InvalidDataTypeException
2926
-     * @throws InvalidInterfaceException
2927
-     */
2928
-    protected function _get_registration_step_content()
2929
-    {
2930
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2931
-            $warning_msg = sprintf(
2932
-                esc_html__(
2933
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2934
-                    'event_espresso'
2935
-                ),
2936
-                '<br />',
2937
-                '<h3 class="important-notice">',
2938
-                '</h3>',
2939
-                '<div class="float-right">',
2940
-                '<span id="redirect_timer" class="important-notice">30</span>',
2941
-                '</div>',
2942
-                '<b>',
2943
-                '</b>'
2944
-            );
2945
-            return '
2425
+	}
2426
+
2427
+
2428
+	/**
2429
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2430
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2431
+	 * to display the page
2432
+	 *
2433
+	 * @access protected
2434
+	 * @return void
2435
+	 * @throws EE_Error
2436
+	 */
2437
+	protected function _update_attendee_registration_form()
2438
+	{
2439
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2440
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2441
+			$REG_ID  = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2442
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2443
+			if ($success) {
2444
+				$what  = esc_html__('Registration Form', 'event_espresso');
2445
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2446
+					: array('action' => 'default');
2447
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2448
+			}
2449
+		}
2450
+	}
2451
+
2452
+
2453
+	/**
2454
+	 * Gets the form for saving registrations custom questions (if done
2455
+	 * previously retrieves the cached form object, which may have validation errors in it)
2456
+	 *
2457
+	 * @param int $REG_ID
2458
+	 * @return EE_Registration_Custom_Questions_Form
2459
+	 * @throws EE_Error
2460
+	 * @throws InvalidArgumentException
2461
+	 * @throws InvalidDataTypeException
2462
+	 * @throws InvalidInterfaceException
2463
+	 */
2464
+	protected function _get_reg_custom_questions_form($REG_ID)
2465
+	{
2466
+		if ( ! $this->_reg_custom_questions_form) {
2467
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2468
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470
+			);
2471
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2472
+		}
2473
+		return $this->_reg_custom_questions_form;
2474
+	}
2475
+
2476
+
2477
+	/**
2478
+	 * Saves
2479
+	 *
2480
+	 * @access private
2481
+	 * @param bool $REG_ID
2482
+	 * @return bool
2483
+	 * @throws EE_Error
2484
+	 * @throws InvalidArgumentException
2485
+	 * @throws InvalidDataTypeException
2486
+	 * @throws InvalidInterfaceException
2487
+	 */
2488
+	private function _save_reg_custom_questions_form($REG_ID = false)
2489
+	{
2490
+		if ( ! $REG_ID) {
2491
+			EE_Error::add_error(
2492
+				esc_html__(
2493
+					'An error occurred. No registration ID was received.', 'event_espresso'),
2494
+				__FILE__, __FUNCTION__, __LINE__
2495
+			);
2496
+		}
2497
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2498
+		$form->receive_form_submission($this->_req_data);
2499
+		$success = false;
2500
+		if ($form->is_valid()) {
2501
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2503
+					$where_conditions    = array(
2504
+						'QST_ID' => $question_id,
2505
+						'REG_ID' => $REG_ID,
2506
+					);
2507
+					$possibly_new_values = array(
2508
+						'ANS_value' => $input->normalized_value(),
2509
+					);
2510
+					$answer              = EEM_Answer::instance()->get_one(array($where_conditions));
2511
+					if ($answer instanceof EE_Answer) {
2512
+						$success = $answer->save($possibly_new_values);
2513
+					} else {
2514
+						//insert it then
2515
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2516
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2517
+						$success     = $answer->save();
2518
+					}
2519
+				}
2520
+			}
2521
+		} else {
2522
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2523
+		}
2524
+		return $success;
2525
+	}
2526
+
2527
+
2528
+	/**
2529
+	 *        generates HTML for the Registration main meta box
2530
+	 *
2531
+	 * @access public
2532
+	 * @return void
2533
+	 * @throws DomainException
2534
+	 * @throws EE_Error
2535
+	 * @throws InvalidArgumentException
2536
+	 * @throws InvalidDataTypeException
2537
+	 * @throws InvalidInterfaceException
2538
+	 */
2539
+	public function _reg_attendees_meta_box()
2540
+	{
2541
+		$REG = EEM_Registration::instance();
2542
+		//get all other registrations on this transaction, and cache
2543
+		//the attendees for them so we don't have to run another query using force_join
2544
+		$registrations                           = $REG->get_all(array(
2545
+			array(
2546
+				'TXN_ID' => $this->_registration->transaction_ID(),
2547
+				'REG_ID' => array('!=', $this->_registration->ID()),
2548
+			),
2549
+			'force_join' => array('Attendee'),
2550
+		));
2551
+		$this->_template_args['attendees']       = array();
2552
+		$this->_template_args['attendee_notice'] = '';
2553
+		if (empty($registrations)
2554
+			|| (is_array($registrations)
2555
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2556
+		) {
2557
+			EE_Error::add_error(
2558
+				esc_html__(
2559
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2560
+					'event_espresso'
2561
+				), __FILE__, __FUNCTION__, __LINE__
2562
+			);
2563
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2564
+		} else {
2565
+			$att_nmbr = 1;
2566
+			foreach ($registrations as $registration) {
2567
+				/* @var $registration EE_Registration */
2568
+				$attendee                                                    = $registration->attendee()
2569
+					? $registration->attendee()
2570
+					: EEM_Attendee::instance()
2571
+								  ->create_default_object();
2572
+				$this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2573
+				$this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2574
+				$this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2575
+				$this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2576
+				$this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2577
+				$this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2578
+					', ',
2579
+					$attendee->full_address_as_array()
2580
+				);
2581
+				$this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2582
+					array(
2583
+						'action' => 'edit_attendee',
2584
+						'post'   => $attendee->ID(),
2585
+					),
2586
+					REG_ADMIN_URL
2587
+				);
2588
+				$this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2589
+				$att_nmbr++;
2590
+			}
2591
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592
+		}
2593
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2594
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595
+	}
2596
+
2597
+
2598
+	/**
2599
+	 *        generates HTML for the Edit Registration side meta box
2600
+	 *
2601
+	 * @access public
2602
+	 * @return void
2603
+	 * @throws DomainException
2604
+	 * @throws EE_Error
2605
+	 * @throws InvalidArgumentException
2606
+	 * @throws InvalidDataTypeException
2607
+	 * @throws InvalidInterfaceException
2608
+	 */
2609
+	public function _reg_registrant_side_meta_box()
2610
+	{
2611
+		/*@var $attendee EE_Attendee */
2612
+		$att_check = $this->_registration->attendee();
2613
+		$attendee  = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2614
+		//now let's determine if this is not the primary registration.  If it isn't then we set the
2615
+		//primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2616
+		//primary registration object (that way we know if we need to show create button or not)
2617
+		if ( ! $this->_registration->is_primary_registrant()) {
2618
+			$primary_registration = $this->_registration->get_primary_registration();
2619
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2620
+				: null;
2621
+			if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2622
+				//in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2623
+				//custom attendee object so let's not worry about the primary reg.
2624
+				$primary_registration = null;
2625
+			}
2626
+		} else {
2627
+			$primary_registration = null;
2628
+		}
2629
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2630
+		$this->_template_args['fname']             = $attendee->fname();
2631
+		$this->_template_args['lname']             = $attendee->lname();
2632
+		$this->_template_args['email']             = $attendee->email();
2633
+		$this->_template_args['phone']             = $attendee->phone();
2634
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635
+		//edit link
2636
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2637
+			'action' => 'edit_attendee',
2638
+			'post'   => $attendee->ID(),
2639
+		), REG_ADMIN_URL);
2640
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641
+		//create link
2642
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2643
+			? EE_Admin_Page::add_query_args_and_nonce(array(
2644
+				'action'  => 'duplicate_attendee',
2645
+				'_REG_ID' => $this->_registration->ID(),
2646
+			), REG_ADMIN_URL) : '';
2647
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648
+		$this->_template_args['att_check']    = $att_check;
2649
+		$template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2650
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651
+	}
2652
+
2653
+
2654
+	/**
2655
+	 * trash or restore registrations
2656
+	 *
2657
+	 * @param  boolean $trash whether to archive or restore
2658
+	 * @return void
2659
+	 * @throws EE_Error
2660
+	 * @throws InvalidArgumentException
2661
+	 * @throws InvalidDataTypeException
2662
+	 * @throws InvalidInterfaceException
2663
+	 * @throws RuntimeException
2664
+	 * @access protected
2665
+	 */
2666
+	protected function _trash_or_restore_registrations($trash = true)
2667
+	{
2668
+		//if empty _REG_ID then get out because there's nothing to do
2669
+		if (empty($this->_req_data['_REG_ID'])) {
2670
+			EE_Error::add_error(
2671
+				sprintf(
2672
+					esc_html__(
2673
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2674
+						'event_espresso'
2675
+					),
2676
+					$trash ? 'trash' : 'restore'
2677
+				),
2678
+				__FILE__, __LINE__, __FUNCTION__
2679
+			);
2680
+			$this->_redirect_after_action(false, '', '', array(), true);
2681
+		}
2682
+		$success = 0;
2683
+		$overwrite_msgs = false;
2684
+		//Checkboxes
2685
+		if ( ! is_array($this->_req_data['_REG_ID'])) {
2686
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2687
+		}
2688
+		$reg_count = count($this->_req_data['_REG_ID']);
2689
+		// cycle thru checkboxes
2690
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2691
+			/** @var EE_Registration $REG */
2692
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693
+			$payments = $REG->registration_payments();
2694
+			if (! empty($payments)) {
2695
+				$name = $REG->attendee() instanceof EE_Attendee
2696
+					? $REG->attendee()->full_name()
2697
+					: esc_html__('Unknown Attendee', 'event_espresso');
2698
+				$overwrite_msgs = true;
2699
+				EE_Error::add_error(
2700
+					sprintf(
2701
+						esc_html__(
2702
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2703
+							'event_espresso'
2704
+						),
2705
+						$name
2706
+					),
2707
+					__FILE__, __FUNCTION__, __LINE__
2708
+				);
2709
+				//can't trash this registration because it has payments.
2710
+				continue;
2711
+			}
2712
+			$updated = $trash ? $REG->delete() : $REG->restore();
2713
+			if ($updated) {
2714
+				$success++;
2715
+			}
2716
+		}
2717
+		$this->_redirect_after_action(
2718
+			$success === $reg_count, // were ALL registrations affected?
2719
+			$success > 1
2720
+				? esc_html__('Registrations', 'event_espresso')
2721
+				: esc_html__('Registration', 'event_espresso'),
2722
+			$trash
2723
+				? esc_html__('moved to the trash', 'event_espresso')
2724
+				: esc_html__('restored', 'event_espresso'),
2725
+			array('action' => 'default'),
2726
+			$overwrite_msgs
2727
+		);
2728
+	}
2729
+
2730
+
2731
+	/**
2732
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2733
+	 * registration but also.
2734
+	 * 1. Removing relations to EE_Attendee
2735
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2736
+	 * ALSO trashed.
2737
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2738
+	 * 4. Removing relationships between all tickets and the related registrations
2739
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2740
+	 * 6. Deleting permanently any related Checkins.
2741
+	 *
2742
+	 * @return void
2743
+	 * @throws EE_Error
2744
+	 * @throws InvalidArgumentException
2745
+	 * @throws InvalidDataTypeException
2746
+	 * @throws InvalidInterfaceException
2747
+	 */
2748
+	protected function _delete_registrations()
2749
+	{
2750
+		$REG_MDL = EEM_Registration::instance();
2751
+		$success = 1;
2752
+		//Checkboxes
2753
+		if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2754
+			// if array has more than one element than success message should be plural
2755
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2756
+			// cycle thru checkboxes
2757
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2758
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2759
+				if ( ! $REG instanceof EE_Registration) {
2760
+					continue;
2761
+				}
2762
+				$deleted = $this->_delete_registration($REG);
2763
+				if ( ! $deleted) {
2764
+					$success = 0;
2765
+				}
2766
+			}
2767
+		} else {
2768
+			// grab single id and delete
2769
+			$REG_ID  = $this->_req_data['_REG_ID'];
2770
+			$REG     = $REG_MDL->get_one_by_ID($REG_ID);
2771
+			$deleted = $this->_delete_registration($REG);
2772
+			if ( ! $deleted) {
2773
+				$success = 0;
2774
+			}
2775
+		}
2776
+		$what        = $success > 1
2777
+			? esc_html__('Registrations', 'event_espresso')
2778
+			: esc_html__('Registration', 'event_espresso');
2779
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2780
+		$this->_redirect_after_action(
2781
+			$success,
2782
+			$what,
2783
+			$action_desc,
2784
+			array('action' => 'default'),
2785
+			true
2786
+		);
2787
+	}
2788
+
2789
+
2790
+	/**
2791
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2792
+	 * models get affected.
2793
+	 *
2794
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2795
+	 * @return bool true = successful deletion, false = fail.
2796
+	 * @throws EE_Error
2797
+	 */
2798
+	protected function _delete_registration(EE_Registration $REG)
2799
+	{
2800
+		//first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2801
+		//registrations on the transaction that are NOT trashed.
2802
+		$TXN         = $REG->get_first_related('Transaction');
2803
+		$REGS        = $TXN->get_many_related('Registration');
2804
+		$all_trashed = true;
2805
+		foreach ($REGS as $registration) {
2806
+			if ( ! $registration->get('REG_deleted')) {
2807
+				$all_trashed = false;
2808
+			}
2809
+		}
2810
+		if ( ! $all_trashed) {
2811
+			EE_Error::add_error(
2812
+				esc_html__(
2813
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2814
+					'event_espresso'
2815
+				),
2816
+				__FILE__, __FUNCTION__, __LINE__
2817
+			);
2818
+			return false;
2819
+		}
2820
+		//k made it here so that means we can delete all the related transactions and their answers (but let's do them
2821
+		//separately from THIS one).
2822
+		foreach ($REGS as $registration) {
2823
+			//delete related answers
2824
+			$registration->delete_related_permanently('Answer');
2825
+			//remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2826
+			$attendee = $registration->get_first_related('Attendee');
2827
+			if ($attendee instanceof EE_Attendee) {
2828
+				$registration->_remove_relation_to($attendee, 'Attendee');
2829
+			}
2830
+			//now remove relationships to tickets on this registration.
2831
+			$registration->_remove_relations('Ticket');
2832
+			//now delete permanently the checkins related to this registration.
2833
+			$registration->delete_related_permanently('Checkin');
2834
+			if ($registration->ID() === $REG->ID()) {
2835
+				continue;
2836
+			} //we don't want to delete permanently the existing registration just yet.
2837
+			//remove relation to transaction for these registrations if NOT the existing registrations
2838
+			$registration->_remove_relations('Transaction');
2839
+			//delete permanently any related messages.
2840
+			$registration->delete_related_permanently('Message');
2841
+			//now delete this registration permanently
2842
+			$registration->delete_permanently();
2843
+		}
2844
+		//now all related registrations on the transaction are handled.  So let's just handle this registration itself
2845
+		// (the transaction and line items should be all that's left).
2846
+		// delete the line items related to the transaction for this registration.
2847
+		$TXN->delete_related_permanently('Line_Item');
2848
+		//we need to remove all the relationships on the transaction
2849
+		$TXN->delete_related_permanently('Payment');
2850
+		$TXN->delete_related_permanently('Extra_Meta');
2851
+		$TXN->delete_related_permanently('Message');
2852
+		//now we can delete this REG permanently (and the transaction of course)
2853
+		$REG->delete_related_permanently('Transaction');
2854
+		return $REG->delete_permanently();
2855
+	}
2856
+
2857
+
2858
+	/**
2859
+	 *    generates HTML for the Register New Attendee Admin page
2860
+	 *
2861
+	 * @access private
2862
+	 * @throws DomainException
2863
+	 * @throws EE_Error
2864
+	 */
2865
+	public function new_registration()
2866
+	{
2867
+		if ( ! $this->_set_reg_event()) {
2868
+			throw new EE_Error(
2869
+				esc_html__(
2870
+					'Unable to continue with registering because there is no Event ID in the request',
2871
+					'event_espresso'
2872
+				)
2873
+			);
2874
+		}
2875
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2876
+		// gotta start with a clean slate if we're not coming here via ajax
2877
+		if ( ! defined('DOING_AJAX')
2878
+			 && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2879
+		) {
2880
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2881
+		}
2882
+		$this->_template_args['event_name'] = '';
2883
+		// event name
2884
+		if ($this->_reg_event) {
2885
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2886
+			$edit_event_url                     = self::add_query_args_and_nonce(array(
2887
+				'action' => 'edit',
2888
+				'post'   => $this->_reg_event->ID(),
2889
+			), EVENTS_ADMIN_URL);
2890
+			$edit_event_lnk                     = '<a href="'
2891
+												  . $edit_event_url
2892
+												  . '" title="'
2893
+												  . esc_attr__('Edit ', 'event_espresso')
2894
+												  . $this->_reg_event->name()
2895
+												  . '">'
2896
+												  . esc_html__('Edit Event', 'event_espresso')
2897
+												  . '</a>';
2898
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2899
+												   . $edit_event_lnk
2900
+												   . '</span>';
2901
+		}
2902
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2903
+		if (defined('DOING_AJAX')) {
2904
+			$this->_return_json();
2905
+		}
2906
+		// grab header
2907
+		$template_path                              =
2908
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2909
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910
+			$this->_template_args, true);
2911
+		//$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2912
+		// the details template wrapper
2913
+		$this->display_admin_page_with_sidebar();
2914
+	}
2915
+
2916
+
2917
+	/**
2918
+	 * This returns the content for a registration step
2919
+	 *
2920
+	 * @access protected
2921
+	 * @return string html
2922
+	 * @throws DomainException
2923
+	 * @throws EE_Error
2924
+	 * @throws InvalidArgumentException
2925
+	 * @throws InvalidDataTypeException
2926
+	 * @throws InvalidInterfaceException
2927
+	 */
2928
+	protected function _get_registration_step_content()
2929
+	{
2930
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2931
+			$warning_msg = sprintf(
2932
+				esc_html__(
2933
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2934
+					'event_espresso'
2935
+				),
2936
+				'<br />',
2937
+				'<h3 class="important-notice">',
2938
+				'</h3>',
2939
+				'<div class="float-right">',
2940
+				'<span id="redirect_timer" class="important-notice">30</span>',
2941
+				'</div>',
2942
+				'<b>',
2943
+				'</b>'
2944
+			);
2945
+			return '
2946 2946
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2947 2947
 	<script >
2948 2948
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2955,841 +2955,841 @@  discard block
 block discarded – undo
2955 2955
 	        }
2956 2956
 	    }, 800 );
2957 2957
 	</script >';
2958
-        }
2959
-        $template_args = array(
2960
-            'title'                    => '',
2961
-            'content'                  => '',
2962
-            'step_button_text'         => '',
2963
-            'show_notification_toggle' => false,
2964
-        );
2965
-        //to indicate we're processing a new registration
2966
-        $hidden_fields = array(
2967
-            'processing_registration' => array(
2968
-                'type'  => 'hidden',
2969
-                'value' => 0,
2970
-            ),
2971
-            'event_id'                => array(
2972
-                'type'  => 'hidden',
2973
-                'value' => $this->_reg_event->ID(),
2974
-            ),
2975
-        );
2976
-        //if the cart is empty then we know we're at step one so we'll display ticket selector
2977
-        $cart = EE_Registry::instance()->SSN->cart();
2978
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2979
-        switch ($step) {
2980
-            case 'ticket' :
2981
-                $hidden_fields['processing_registration']['value'] = 1;
2982
-                $template_args['title']                            = esc_html__(
2983
-                    'Step One: Select the Ticket for this registration',
2984
-                    'event_espresso'
2985
-                );
2986
-                $template_args['content']                          =
2987
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2988
-                $template_args['step_button_text']                 = esc_html__(
2989
-                    'Add Tickets and Continue to Registrant Details',
2990
-                    'event_espresso'
2991
-                );
2992
-                $template_args['show_notification_toggle']         = false;
2993
-                break;
2994
-            case 'questions' :
2995
-                $hidden_fields['processing_registration']['value'] = 2;
2996
-                $template_args['title']                            = esc_html__(
2997
-                    'Step Two: Add Registrant Details for this Registration',
2998
-                    'event_espresso'
2999
-                );
3000
-                //in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3001
-                // properly by the first process_reg_step run.
3002
-                $template_args['content']                  =
3003
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3004
-                $template_args['step_button_text']         = esc_html__(
3005
-                    'Save Registration and Continue to Details',
3006
-                    'event_espresso'
3007
-                );
3008
-                $template_args['show_notification_toggle'] = true;
3009
-                break;
3010
-        }
3011
-        //we come back to the process_registration_step route.
3012
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013
-        return EEH_Template::display_template(
3014
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3015
-            $template_args,
3016
-            true
3017
-        );
3018
-    }
3019
-
3020
-
3021
-    /**
3022
-     *        set_reg_event
3023
-     *
3024
-     * @access private
3025
-     * @return bool
3026
-     * @throws EE_Error
3027
-     * @throws InvalidArgumentException
3028
-     * @throws InvalidDataTypeException
3029
-     * @throws InvalidInterfaceException
3030
-     */
3031
-    private function _set_reg_event()
3032
-    {
3033
-        if (is_object($this->_reg_event)) {
3034
-            return true;
3035
-        }
3036
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037
-        if ( ! $EVT_ID) {
3038
-            return false;
3039
-        }
3040
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3041
-        return true;
3042
-    }
3043
-
3044
-
3045
-    /**
3046
-     * process_reg_step
3047
-     *
3048
-     * @access        public
3049
-     * @return string
3050
-     * @throws DomainException
3051
-     * @throws EE_Error
3052
-     * @throws InvalidArgumentException
3053
-     * @throws InvalidDataTypeException
3054
-     * @throws InvalidInterfaceException
3055
-     * @throws ReflectionException
3056
-     * @throws RuntimeException
3057
-     */
3058
-    public function process_reg_step()
3059
-    {
3060
-        EE_System::do_not_cache();
3061
-        $this->_set_reg_event();
3062
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3063
-        EE_Registry::instance()->REQ->set('uts', time());
3064
-        //what step are we on?
3065
-        $cart = EE_Registry::instance()->SSN->cart();
3066
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3067
-        //if doing ajax then we need to verify the nonce
3068
-        if (defined('DOING_AJAX')) {
3069
-            $nonce = isset($this->_req_data[$this->_req_nonce])
3070
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3071
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3072
-        }
3073
-        switch ($step) {
3074
-            case 'ticket' :
3075
-                //process ticket selection
3076
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3077
-                if ($success) {
3078
-                    EE_Error::add_success(
3079
-                        esc_html__(
3080
-                            'Tickets Selected. Now complete the registration.',
3081
-                            'event_espresso'
3082
-                        )
3083
-                    );
3084
-                } else {
3085
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3086
-                }
3087
-                if (defined('DOING_AJAX')) {
3088
-                    $this->new_registration(); //display next step
3089
-                } else {
3090
-                    $query_args = array(
3091
-                        'action'                  => 'new_registration',
3092
-                        'processing_registration' => 1,
3093
-                        'event_id'                => $this->_reg_event->ID(),
3094
-                        'uts'                     => time(),
3095
-                    );
3096
-                    $this->_redirect_after_action(
3097
-                        false,
3098
-                        '',
3099
-                        '',
3100
-                        $query_args,
3101
-                        true
3102
-                    );
3103
-                }
3104
-                break;
3105
-            case 'questions' :
3106
-                if (! isset(
3107
-                    $this->_req_data['txn_reg_status_change'],
3108
-                    $this->_req_data['txn_reg_status_change']['send_notifications'])
3109
-                ) {
3110
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3111
-                }
3112
-                //process registration
3113
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3114
-                if ($cart instanceof EE_Cart) {
3115
-                    $grand_total = $cart->get_cart_grand_total();
3116
-                    if ($grand_total instanceof EE_Line_Item) {
3117
-                        $grand_total->save_this_and_descendants_to_txn();
3118
-                    }
3119
-                }
3120
-                if ( ! $transaction instanceof EE_Transaction) {
3121
-                    $query_args = array(
3122
-                        'action'                  => 'new_registration',
3123
-                        'processing_registration' => 2,
3124
-                        'event_id'                => $this->_reg_event->ID(),
3125
-                        'uts'                     => time(),
3126
-                    );
3127
-                    if (defined('DOING_AJAX')) {
3128
-                        //display registration form again because there are errors (maybe validation?)
3129
-                        $this->new_registration();
3130
-                        return;
3131
-                    } else {
3132
-                        $this->_redirect_after_action(
3133
-                            false,
3134
-                            '',
3135
-                            '',
3136
-                            $query_args,
3137
-                            true
3138
-                        );
3139
-                        return;
3140
-                    }
3141
-                }
3142
-                // maybe update status, and make sure to save transaction if not done already
3143
-                if ( ! $transaction->update_status_based_on_total_paid()) {
3144
-                    $transaction->save();
3145
-                }
3146
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3147
-                $this->_req_data = array();
3148
-                $query_args      = array(
3149
-                    'action'        => 'redirect_to_txn',
3150
-                    'TXN_ID'        => $transaction->ID(),
3151
-                    'EVT_ID'        => $this->_reg_event->ID(),
3152
-                    'event_name'    => urlencode($this->_reg_event->name()),
3153
-                    'redirect_from' => 'new_registration',
3154
-                );
3155
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3156
-                break;
3157
-        }
3158
-        //what are you looking here for?  Should be nothing to do at this point.
3159
-    }
3160
-
3161
-
3162
-    /**
3163
-     * redirect_to_txn
3164
-     *
3165
-     * @access public
3166
-     * @return void
3167
-     * @throws EE_Error
3168
-     * @throws InvalidArgumentException
3169
-     * @throws InvalidDataTypeException
3170
-     * @throws InvalidInterfaceException
3171
-     */
3172
-    public function redirect_to_txn()
3173
-    {
3174
-        EE_System::do_not_cache();
3175
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3176
-        $query_args = array(
3177
-            'action' => 'view_transaction',
3178
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3179
-            'page'   => 'espresso_transactions',
3180
-        );
3181
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3182
-            $query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
3183
-            $query_args['event_name']    = urlencode($this->_req_data['event_name']);
3184
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3185
-        }
3186
-        EE_Error::add_success(
3187
-            esc_html__(
3188
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3189
-                'event_espresso'
3190
-            )
3191
-        );
3192
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3193
-    }
3194
-
3195
-
3196
-    /**
3197
-     *        generates HTML for the Attendee Contact List
3198
-     *
3199
-     * @access protected
3200
-     * @return void
3201
-     */
3202
-    protected function _attendee_contact_list_table()
3203
-    {
3204
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3205
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3206
-        $this->display_admin_list_table_page_with_no_sidebar();
3207
-    }
3208
-
3209
-
3210
-    /**
3211
-     *        get_attendees
3212
-     *
3213
-     * @param      $per_page
3214
-     * @param bool $count whether to return count or data.
3215
-     * @param bool $trash
3216
-     * @return array
3217
-     * @throws EE_Error
3218
-     * @throws InvalidArgumentException
3219
-     * @throws InvalidDataTypeException
3220
-     * @throws InvalidInterfaceException
3221
-     * @access public
3222
-     */
3223
-    public function get_attendees($per_page, $count = false, $trash = false)
3224
-    {
3225
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3227
-        $ATT_MDL                    = EEM_Attendee::instance();
3228
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229
-        switch ($this->_req_data['orderby']) {
3230
-            case 'ATT_ID':
3231
-                $orderby = 'ATT_ID';
3232
-                break;
3233
-            case 'ATT_fname':
3234
-                $orderby = 'ATT_fname';
3235
-                break;
3236
-            case 'ATT_email':
3237
-                $orderby = 'ATT_email';
3238
-                break;
3239
-            case 'ATT_city':
3240
-                $orderby = 'ATT_city';
3241
-                break;
3242
-            case 'STA_ID':
3243
-                $orderby = 'STA_ID';
3244
-                break;
3245
-            case 'CNT_ID':
3246
-                $orderby = 'CNT_ID';
3247
-                break;
3248
-            case 'Registration_Count':
3249
-                $orderby = 'Registration_Count';
3250
-                break;
3251
-            default:
3252
-                $orderby = 'ATT_lname';
3253
-        }
3254
-        $sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3255
-            ? $this->_req_data['order']
3256
-            : 'ASC';
3257
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3258
-            ? $this->_req_data['paged']
3259
-            : 1;
3260
-        $per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3261
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3262
-            ? $this->_req_data['perpage']
3263
-            : $per_page;
3264
-        $_where       = array();
3265
-        if ( ! empty($this->_req_data['s'])) {
3266
-            $sstr         = '%' . $this->_req_data['s'] . '%';
3267
-            $_where['OR'] = array(
3268
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3270
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3271
-                'ATT_fname'                         => array('LIKE', $sstr),
3272
-                'ATT_lname'                         => array('LIKE', $sstr),
3273
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3274
-                'ATT_email'                         => array('LIKE', $sstr),
3275
-                'ATT_address'                       => array('LIKE', $sstr),
3276
-                'ATT_address2'                      => array('LIKE', $sstr),
3277
-                'ATT_city'                          => array('LIKE', $sstr),
3278
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3279
-                'State.STA_name'                    => array('LIKE', $sstr),
3280
-                'ATT_phone'                         => array('LIKE', $sstr),
3281
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3282
-                'Registration.REG_code'             => array('LIKE', $sstr),
3283
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3284
-            );
3285
-        }
3286
-        $offset = ($current_page - 1) * $per_page;
3287
-        $limit  = $count ? null : array($offset, $per_page);
3288
-        $query_args = array(
3289
-            $_where,
3290
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291
-            'limit' => $limit
3292
-        );
3293
-        if (! $count) {
3294
-            $query_args['order_by'] = array($orderby => $sort);
3295
-        }
3296
-        if ($trash) {
3297
-            $query_args[0]['status'] = array('!=', 'publish');
3298
-            $all_attendees    = $count
3299
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300
-                : $ATT_MDL->get_all($query_args);
3301
-        } else {
3302
-            $query_args[0]['status'] = array('IN', array('publish'));
3303
-            $all_attendees    = $count
3304
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305
-                : $ATT_MDL->get_all($query_args);
3306
-        }
3307
-        return $all_attendees;
3308
-    }
3309
-
3310
-
3311
-    /**
3312
-     * This is just taking care of resending the registration confirmation
3313
-     *
3314
-     * @access protected
3315
-     * @return void
3316
-     */
3317
-    protected function _resend_registration()
3318
-    {
3319
-        $this->_process_resend_registration();
3320
-        $query_args = isset($this->_req_data['redirect_to'])
3321
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3322
-            : array('action' => 'default');
3323
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3324
-    }
3325
-
3326
-    /**
3327
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3328
-     * to use when selecting registrations
3329
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3330
-     *                                                     the query parameters from the request
3331
-     * @return void ends the request with a redirect or download
3332
-     */
3333
-    public function _registrations_report_base( $method_name_for_getting_query_params )
3334
-    {
3335
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337
-                array(
3338
-                    'page'        => 'espresso_batch',
3339
-                    'batch'       => 'file',
3340
-                    'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3341
-                    'filters'     => urlencode(
3342
-                        serialize(
3343
-                            call_user_func(
3344
-                                array( $this, $method_name_for_getting_query_params ),
3345
-                                EEH_Array::is_set(
3346
-                                    $this->_req_data,
3347
-                                    'filters',
3348
-                                    array()
3349
-                                )
3350
-                            )
3351
-                        )
3352
-                ),
3353
-                'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3354
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3355
-                'return_url'  => urlencode($this->_req_data['return_url']),
3356
-            )));
3357
-        } else {
3358
-            $new_request_args = array(
3359
-                'export' => 'report',
3360
-                'action' => 'registrations_report_for_event',
3361
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362
-            );
3363
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3366
-                $EE_Export = EE_Export::instance($this->_req_data);
3367
-                $EE_Export->export();
3368
-            }
3369
-        }
3370
-    }
3371
-
3372
-
3373
-
3374
-    /**
3375
-     * Creates a registration report using only query parameters in the request
3376
-     * @return void
3377
-     */
3378
-    public function _registrations_report()
3379
-    {
3380
-        $this->_registrations_report_base('_get_registration_query_parameters');
3381
-    }
3382
-
3383
-
3384
-    public function _contact_list_export()
3385
-    {
3386
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3388
-            $EE_Export = EE_Export::instance($this->_req_data);
3389
-            $EE_Export->export_attendees();
3390
-        }
3391
-    }
3392
-
3393
-
3394
-    public function _contact_list_report()
3395
-    {
3396
-        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3397
-            wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3398
-                'page'        => 'espresso_batch',
3399
-                'batch'       => 'file',
3400
-                'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3401
-                'return_url'  => urlencode($this->_req_data['return_url']),
3402
-            )));
3403
-        } else {
3404
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3406
-                $EE_Export = EE_Export::instance($this->_req_data);
3407
-                $EE_Export->report_attendees();
3408
-            }
3409
-        }
3410
-    }
3411
-
3412
-
3413
-
3414
-
3415
-
3416
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3417
-    /**
3418
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3419
-     *
3420
-     * @return void
3421
-     * @throws EE_Error
3422
-     * @throws InvalidArgumentException
3423
-     * @throws InvalidDataTypeException
3424
-     * @throws InvalidInterfaceException
3425
-     */
3426
-    protected function _duplicate_attendee()
3427
-    {
3428
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3429
-        //verify we have necessary info
3430
-        if (empty($this->_req_data['_REG_ID'])) {
3431
-            EE_Error::add_error(
3432
-                esc_html__(
3433
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3434
-                    'event_espresso'
3435
-                ), __FILE__, __LINE__, __FUNCTION__
3436
-            );
3437
-            $query_args = array('action' => $action);
3438
-            $this->_redirect_after_action('', '', '', $query_args, true);
3439
-        }
3440
-        //okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3441
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3442
-        $attendee     = $registration->attendee();
3443
-        //remove relation of existing attendee on registration
3444
-        $registration->_remove_relation_to($attendee, 'Attendee');
3445
-        //new attendee
3446
-        $new_attendee = clone $attendee;
3447
-        $new_attendee->set('ATT_ID', 0);
3448
-        $new_attendee->save();
3449
-        //add new attendee to reg
3450
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3451
-        EE_Error::add_success(
3452
-            esc_html__(
3453
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3454
-                'event_espresso'
3455
-            )
3456
-        );
3457
-        //redirect to edit page for attendee
3458
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3459
-        $this->_redirect_after_action('', '', '', $query_args, true);
3460
-    }
3461
-
3462
-
3463
-    /**
3464
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3465
-     * @param int      $post_id
3466
-     * @param WP_POST $post
3467
-     * @throws DomainException
3468
-     * @throws EE_Error
3469
-     * @throws InvalidArgumentException
3470
-     * @throws InvalidDataTypeException
3471
-     * @throws InvalidInterfaceException
3472
-     * @throws LogicException
3473
-     * @throws InvalidFormSubmissionException
3474
-     */
3475
-    protected function _insert_update_cpt_item($post_id, $post)
3476
-    {
3477
-        $success  = true;
3478
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3479
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3480
-            : null;
3481
-        //for attendee updates
3482
-        if ($attendee instanceof EE_Attendee) {
3483
-            //note we should only be UPDATING attendees at this point.
3484
-            $updated_fields = array(
3485
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3486
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3488
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3491
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3492
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3493
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3494
-            );
3495
-            foreach ($updated_fields as $field => $value) {
3496
-                $attendee->set($field, $value);
3497
-            }
3498
-
3499
-            //process contact details metabox form handler (which will also save the attendee)
3500
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3501
-            $success = $contact_details_form->process($this->_req_data);
3502
-
3503
-            $attendee_update_callbacks = apply_filters(
3504
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3505
-                array()
3506
-            );
3507
-            foreach ($attendee_update_callbacks as $a_callback) {
3508
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3509
-                    throw new EE_Error(
3510
-                        sprintf(
3511
-                            esc_html__(
3512
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3513
-                                'event_espresso'
3514
-                            ),
3515
-                            $a_callback
3516
-                        )
3517
-                    );
3518
-                }
3519
-            }
3520
-        }
3521
-
3522
-        if ($success === false) {
3523
-            EE_Error::add_error(
3524
-                esc_html__(
3525
-                    'Something went wrong with updating the meta table data for the registration.',
3526
-                    'event_espresso'
3527
-                ),
3528
-                __FILE__, __FUNCTION__, __LINE__
3529
-            );
3530
-        }
3531
-    }
3532
-
3533
-
3534
-    public function trash_cpt_item($post_id)
3535
-    {
3536
-    }
3537
-
3538
-
3539
-    public function delete_cpt_item($post_id)
3540
-    {
3541
-    }
3542
-
3543
-
3544
-    public function restore_cpt_item($post_id)
3545
-    {
3546
-    }
3547
-
3548
-
3549
-    protected function _restore_cpt_item($post_id, $revision_id)
3550
-    {
3551
-    }
3552
-
3553
-
3554
-    public function attendee_editor_metaboxes()
3555
-    {
3556
-        $this->verify_cpt_object();
3557
-        remove_meta_box(
3558
-            'postexcerpt',
3559
-            esc_html__('Excerpt', 'event_espresso'),
3560
-            'post_excerpt_meta_box',
3561
-            $this->_cpt_routes[$this->_req_action],
3562
-            'normal',
3563
-            'core'
3564
-        );
3565
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3566
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3567
-            add_meta_box(
3568
-                'postexcerpt',
3569
-                esc_html__('Short Biography', 'event_espresso'),
3570
-                'post_excerpt_meta_box',
3571
-                $this->_cpt_routes[$this->_req_action],
3572
-                'normal'
3573
-            );
3574
-        }
3575
-        if (post_type_supports('espresso_attendees', 'comments')) {
3576
-            add_meta_box(
3577
-                'commentsdiv',
3578
-                esc_html__('Notes on the Contact', 'event_espresso'),
3579
-                'post_comment_meta_box',
3580
-                $this->_cpt_routes[$this->_req_action],
3581
-                'normal',
3582
-                'core'
3583
-            );
3584
-        }
3585
-        add_meta_box(
3586
-            'attendee_contact_info',
3587
-            esc_html__('Contact Info', 'event_espresso'),
3588
-            array($this, 'attendee_contact_info'),
3589
-            $this->_cpt_routes[$this->_req_action],
3590
-            'side',
3591
-            'core'
3592
-        );
3593
-        add_meta_box(
3594
-            'attendee_details_address',
3595
-            esc_html__('Address Details', 'event_espresso'),
3596
-            array($this, 'attendee_address_details'),
3597
-            $this->_cpt_routes[$this->_req_action],
3598
-            'normal',
3599
-            'core'
3600
-        );
3601
-        add_meta_box(
3602
-            'attendee_registrations',
3603
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3604
-            array($this, 'attendee_registrations_meta_box'),
3605
-            $this->_cpt_routes[$this->_req_action],
3606
-            'normal',
3607
-            'high'
3608
-        );
3609
-    }
3610
-
3611
-
3612
-    /**
3613
-     * Metabox for attendee contact info
3614
-     *
3615
-     * @param  WP_Post $post wp post object
3616
-     * @return string attendee contact info ( and form )
3617
-     * @throws EE_Error
3618
-     * @throws InvalidArgumentException
3619
-     * @throws InvalidDataTypeException
3620
-     * @throws InvalidInterfaceException
3621
-     * @throws LogicException
3622
-     * @throws DomainException
3623
-     */
3624
-    public function attendee_contact_info($post)
3625
-    {
3626
-        //get attendee object ( should already have it )
3627
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3628
-        $form->enqueueStylesAndScripts();
3629
-        echo $form->display();
3630
-    }
3631
-
3632
-
3633
-    /**
3634
-     * Return form handler for the contact details metabox
3635
-     *
3636
-     * @param EE_Attendee $attendee
3637
-     * @return AttendeeContactDetailsMetaboxFormHandler
3638
-     * @throws DomainException
3639
-     * @throws InvalidArgumentException
3640
-     * @throws InvalidDataTypeException
3641
-     * @throws InvalidInterfaceException
3642
-     */
3643
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3644
-    {
3645
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3646
-    }
3647
-
3648
-
3649
-    /**
3650
-     * Metabox for attendee details
3651
-     *
3652
-     * @param  WP_Post $post wp post object
3653
-     * @throws DomainException
3654
-     */
3655
-    public function attendee_address_details($post)
3656
-    {
3657
-        //get attendee object (should already have it)
3658
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3659
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3660
-            new EE_Question_Form_Input(
3661
-                EE_Question::new_instance(
3662
-                    array(
3663
-                        'QST_ID'           => 0,
3664
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3665
-                        'QST_system'       => 'admin-state',
3666
-                    )
3667
-                ),
3668
-                EE_Answer::new_instance(
3669
-                    array(
3670
-                        'ANS_ID'    => 0,
3671
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3672
-                    )
3673
-                ),
3674
-                array(
3675
-                    'input_id'       => 'STA_ID',
3676
-                    'input_name'     => 'STA_ID',
3677
-                    'input_prefix'   => '',
3678
-                    'append_qstn_id' => false,
3679
-                )
3680
-            )
3681
-        );
3682
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3683
-            new EE_Question_Form_Input(
3684
-                EE_Question::new_instance(
3685
-                    array(
3686
-                        'QST_ID'           => 0,
3687
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3688
-                        'QST_system'       => 'admin-country',
3689
-                    )
3690
-                ),
3691
-                EE_Answer::new_instance(
3692
-                    array(
3693
-                        'ANS_ID'    => 0,
3694
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3695
-                    )
3696
-                ),
3697
-                array(
3698
-                    'input_id'       => 'CNT_ISO',
3699
-                    'input_name'     => 'CNT_ISO',
3700
-                    'input_prefix'   => '',
3701
-                    'append_qstn_id' => false,
3702
-                )
3703
-            )
3704
-        );
3705
-        $template                             =
3706
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3707
-        EEH_Template::display_template($template, $this->_template_args);
3708
-    }
3709
-
3710
-
3711
-    /**
3712
-     *        _attendee_details
3713
-     *
3714
-     * @access protected
3715
-     * @param $post
3716
-     * @return void
3717
-     * @throws DomainException
3718
-     * @throws EE_Error
3719
-     */
3720
-    public function attendee_registrations_meta_box($post)
3721
-    {
3722
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3723
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724
-        $template                              =
3725
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3726
-        EEH_Template::display_template($template, $this->_template_args);
3727
-    }
3728
-
3729
-
3730
-    /**
3731
-     * add in the form fields for the attendee edit
3732
-     *
3733
-     * @param  WP_Post $post wp post object
3734
-     * @return string html for new form.
3735
-     * @throws DomainException
3736
-     */
3737
-    public function after_title_form_fields($post)
3738
-    {
3739
-        if ($post->post_type == 'espresso_attendees') {
3740
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3741
-            $template_args['attendee'] = $this->_cpt_model_obj;
3742
-            EEH_Template::display_template($template, $template_args);
3743
-        }
3744
-    }
3745
-
3746
-
3747
-    /**
3748
-     *        _trash_or_restore_attendee
3749
-     *
3750
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3751
-     * @return void
3752
-     * @throws EE_Error
3753
-     * @throws InvalidArgumentException
3754
-     * @throws InvalidDataTypeException
3755
-     * @throws InvalidInterfaceException
3756
-     * @access protected
3757
-     */
3758
-    protected function _trash_or_restore_attendees($trash = true)
3759
-    {
3760
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3761
-        $ATT_MDL = EEM_Attendee::instance();
3762
-        $success = 1;
3763
-        //Checkboxes
3764
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3765
-            // if array has more than one element than success message should be plural
3766
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3767
-            // cycle thru checkboxes
3768
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3769
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3770
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3771
-                if ( ! $updated) {
3772
-                    $success = 0;
3773
-                }
3774
-            }
3775
-        } else {
3776
-            // grab single id and delete
3777
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3778
-            //get attendee
3779
-            $att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3780
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3781
-            $updated = $att->save();
3782
-            if ( ! $updated) {
3783
-                $success = 0;
3784
-            }
3785
-        }
3786
-        $what        = $success > 1
3787
-            ? esc_html__('Contacts', 'event_espresso')
3788
-            : esc_html__('Contact', 'event_espresso');
3789
-        $action_desc = $trash
3790
-            ? esc_html__('moved to the trash', 'event_espresso')
3791
-            : esc_html__('restored', 'event_espresso');
3792
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3793
-    }
2958
+		}
2959
+		$template_args = array(
2960
+			'title'                    => '',
2961
+			'content'                  => '',
2962
+			'step_button_text'         => '',
2963
+			'show_notification_toggle' => false,
2964
+		);
2965
+		//to indicate we're processing a new registration
2966
+		$hidden_fields = array(
2967
+			'processing_registration' => array(
2968
+				'type'  => 'hidden',
2969
+				'value' => 0,
2970
+			),
2971
+			'event_id'                => array(
2972
+				'type'  => 'hidden',
2973
+				'value' => $this->_reg_event->ID(),
2974
+			),
2975
+		);
2976
+		//if the cart is empty then we know we're at step one so we'll display ticket selector
2977
+		$cart = EE_Registry::instance()->SSN->cart();
2978
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2979
+		switch ($step) {
2980
+			case 'ticket' :
2981
+				$hidden_fields['processing_registration']['value'] = 1;
2982
+				$template_args['title']                            = esc_html__(
2983
+					'Step One: Select the Ticket for this registration',
2984
+					'event_espresso'
2985
+				);
2986
+				$template_args['content']                          =
2987
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2988
+				$template_args['step_button_text']                 = esc_html__(
2989
+					'Add Tickets and Continue to Registrant Details',
2990
+					'event_espresso'
2991
+				);
2992
+				$template_args['show_notification_toggle']         = false;
2993
+				break;
2994
+			case 'questions' :
2995
+				$hidden_fields['processing_registration']['value'] = 2;
2996
+				$template_args['title']                            = esc_html__(
2997
+					'Step Two: Add Registrant Details for this Registration',
2998
+					'event_espresso'
2999
+				);
3000
+				//in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3001
+				// properly by the first process_reg_step run.
3002
+				$template_args['content']                  =
3003
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3004
+				$template_args['step_button_text']         = esc_html__(
3005
+					'Save Registration and Continue to Details',
3006
+					'event_espresso'
3007
+				);
3008
+				$template_args['show_notification_toggle'] = true;
3009
+				break;
3010
+		}
3011
+		//we come back to the process_registration_step route.
3012
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013
+		return EEH_Template::display_template(
3014
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3015
+			$template_args,
3016
+			true
3017
+		);
3018
+	}
3019
+
3020
+
3021
+	/**
3022
+	 *        set_reg_event
3023
+	 *
3024
+	 * @access private
3025
+	 * @return bool
3026
+	 * @throws EE_Error
3027
+	 * @throws InvalidArgumentException
3028
+	 * @throws InvalidDataTypeException
3029
+	 * @throws InvalidInterfaceException
3030
+	 */
3031
+	private function _set_reg_event()
3032
+	{
3033
+		if (is_object($this->_reg_event)) {
3034
+			return true;
3035
+		}
3036
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037
+		if ( ! $EVT_ID) {
3038
+			return false;
3039
+		}
3040
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3041
+		return true;
3042
+	}
3043
+
3044
+
3045
+	/**
3046
+	 * process_reg_step
3047
+	 *
3048
+	 * @access        public
3049
+	 * @return string
3050
+	 * @throws DomainException
3051
+	 * @throws EE_Error
3052
+	 * @throws InvalidArgumentException
3053
+	 * @throws InvalidDataTypeException
3054
+	 * @throws InvalidInterfaceException
3055
+	 * @throws ReflectionException
3056
+	 * @throws RuntimeException
3057
+	 */
3058
+	public function process_reg_step()
3059
+	{
3060
+		EE_System::do_not_cache();
3061
+		$this->_set_reg_event();
3062
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3063
+		EE_Registry::instance()->REQ->set('uts', time());
3064
+		//what step are we on?
3065
+		$cart = EE_Registry::instance()->SSN->cart();
3066
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3067
+		//if doing ajax then we need to verify the nonce
3068
+		if (defined('DOING_AJAX')) {
3069
+			$nonce = isset($this->_req_data[$this->_req_nonce])
3070
+				? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3071
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3072
+		}
3073
+		switch ($step) {
3074
+			case 'ticket' :
3075
+				//process ticket selection
3076
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3077
+				if ($success) {
3078
+					EE_Error::add_success(
3079
+						esc_html__(
3080
+							'Tickets Selected. Now complete the registration.',
3081
+							'event_espresso'
3082
+						)
3083
+					);
3084
+				} else {
3085
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3086
+				}
3087
+				if (defined('DOING_AJAX')) {
3088
+					$this->new_registration(); //display next step
3089
+				} else {
3090
+					$query_args = array(
3091
+						'action'                  => 'new_registration',
3092
+						'processing_registration' => 1,
3093
+						'event_id'                => $this->_reg_event->ID(),
3094
+						'uts'                     => time(),
3095
+					);
3096
+					$this->_redirect_after_action(
3097
+						false,
3098
+						'',
3099
+						'',
3100
+						$query_args,
3101
+						true
3102
+					);
3103
+				}
3104
+				break;
3105
+			case 'questions' :
3106
+				if (! isset(
3107
+					$this->_req_data['txn_reg_status_change'],
3108
+					$this->_req_data['txn_reg_status_change']['send_notifications'])
3109
+				) {
3110
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3111
+				}
3112
+				//process registration
3113
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3114
+				if ($cart instanceof EE_Cart) {
3115
+					$grand_total = $cart->get_cart_grand_total();
3116
+					if ($grand_total instanceof EE_Line_Item) {
3117
+						$grand_total->save_this_and_descendants_to_txn();
3118
+					}
3119
+				}
3120
+				if ( ! $transaction instanceof EE_Transaction) {
3121
+					$query_args = array(
3122
+						'action'                  => 'new_registration',
3123
+						'processing_registration' => 2,
3124
+						'event_id'                => $this->_reg_event->ID(),
3125
+						'uts'                     => time(),
3126
+					);
3127
+					if (defined('DOING_AJAX')) {
3128
+						//display registration form again because there are errors (maybe validation?)
3129
+						$this->new_registration();
3130
+						return;
3131
+					} else {
3132
+						$this->_redirect_after_action(
3133
+							false,
3134
+							'',
3135
+							'',
3136
+							$query_args,
3137
+							true
3138
+						);
3139
+						return;
3140
+					}
3141
+				}
3142
+				// maybe update status, and make sure to save transaction if not done already
3143
+				if ( ! $transaction->update_status_based_on_total_paid()) {
3144
+					$transaction->save();
3145
+				}
3146
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3147
+				$this->_req_data = array();
3148
+				$query_args      = array(
3149
+					'action'        => 'redirect_to_txn',
3150
+					'TXN_ID'        => $transaction->ID(),
3151
+					'EVT_ID'        => $this->_reg_event->ID(),
3152
+					'event_name'    => urlencode($this->_reg_event->name()),
3153
+					'redirect_from' => 'new_registration',
3154
+				);
3155
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3156
+				break;
3157
+		}
3158
+		//what are you looking here for?  Should be nothing to do at this point.
3159
+	}
3160
+
3161
+
3162
+	/**
3163
+	 * redirect_to_txn
3164
+	 *
3165
+	 * @access public
3166
+	 * @return void
3167
+	 * @throws EE_Error
3168
+	 * @throws InvalidArgumentException
3169
+	 * @throws InvalidDataTypeException
3170
+	 * @throws InvalidInterfaceException
3171
+	 */
3172
+	public function redirect_to_txn()
3173
+	{
3174
+		EE_System::do_not_cache();
3175
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3176
+		$query_args = array(
3177
+			'action' => 'view_transaction',
3178
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3179
+			'page'   => 'espresso_transactions',
3180
+		);
3181
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3182
+			$query_args['EVT_ID']        = $this->_req_data['EVT_ID'];
3183
+			$query_args['event_name']    = urlencode($this->_req_data['event_name']);
3184
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3185
+		}
3186
+		EE_Error::add_success(
3187
+			esc_html__(
3188
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3189
+				'event_espresso'
3190
+			)
3191
+		);
3192
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3193
+	}
3194
+
3195
+
3196
+	/**
3197
+	 *        generates HTML for the Attendee Contact List
3198
+	 *
3199
+	 * @access protected
3200
+	 * @return void
3201
+	 */
3202
+	protected function _attendee_contact_list_table()
3203
+	{
3204
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3205
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3206
+		$this->display_admin_list_table_page_with_no_sidebar();
3207
+	}
3208
+
3209
+
3210
+	/**
3211
+	 *        get_attendees
3212
+	 *
3213
+	 * @param      $per_page
3214
+	 * @param bool $count whether to return count or data.
3215
+	 * @param bool $trash
3216
+	 * @return array
3217
+	 * @throws EE_Error
3218
+	 * @throws InvalidArgumentException
3219
+	 * @throws InvalidDataTypeException
3220
+	 * @throws InvalidInterfaceException
3221
+	 * @access public
3222
+	 */
3223
+	public function get_attendees($per_page, $count = false, $trash = false)
3224
+	{
3225
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3227
+		$ATT_MDL                    = EEM_Attendee::instance();
3228
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229
+		switch ($this->_req_data['orderby']) {
3230
+			case 'ATT_ID':
3231
+				$orderby = 'ATT_ID';
3232
+				break;
3233
+			case 'ATT_fname':
3234
+				$orderby = 'ATT_fname';
3235
+				break;
3236
+			case 'ATT_email':
3237
+				$orderby = 'ATT_email';
3238
+				break;
3239
+			case 'ATT_city':
3240
+				$orderby = 'ATT_city';
3241
+				break;
3242
+			case 'STA_ID':
3243
+				$orderby = 'STA_ID';
3244
+				break;
3245
+			case 'CNT_ID':
3246
+				$orderby = 'CNT_ID';
3247
+				break;
3248
+			case 'Registration_Count':
3249
+				$orderby = 'Registration_Count';
3250
+				break;
3251
+			default:
3252
+				$orderby = 'ATT_lname';
3253
+		}
3254
+		$sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3255
+			? $this->_req_data['order']
3256
+			: 'ASC';
3257
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3258
+			? $this->_req_data['paged']
3259
+			: 1;
3260
+		$per_page     = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3261
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3262
+			? $this->_req_data['perpage']
3263
+			: $per_page;
3264
+		$_where       = array();
3265
+		if ( ! empty($this->_req_data['s'])) {
3266
+			$sstr         = '%' . $this->_req_data['s'] . '%';
3267
+			$_where['OR'] = array(
3268
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3270
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3271
+				'ATT_fname'                         => array('LIKE', $sstr),
3272
+				'ATT_lname'                         => array('LIKE', $sstr),
3273
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3274
+				'ATT_email'                         => array('LIKE', $sstr),
3275
+				'ATT_address'                       => array('LIKE', $sstr),
3276
+				'ATT_address2'                      => array('LIKE', $sstr),
3277
+				'ATT_city'                          => array('LIKE', $sstr),
3278
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3279
+				'State.STA_name'                    => array('LIKE', $sstr),
3280
+				'ATT_phone'                         => array('LIKE', $sstr),
3281
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3282
+				'Registration.REG_code'             => array('LIKE', $sstr),
3283
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3284
+			);
3285
+		}
3286
+		$offset = ($current_page - 1) * $per_page;
3287
+		$limit  = $count ? null : array($offset, $per_page);
3288
+		$query_args = array(
3289
+			$_where,
3290
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291
+			'limit' => $limit
3292
+		);
3293
+		if (! $count) {
3294
+			$query_args['order_by'] = array($orderby => $sort);
3295
+		}
3296
+		if ($trash) {
3297
+			$query_args[0]['status'] = array('!=', 'publish');
3298
+			$all_attendees    = $count
3299
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300
+				: $ATT_MDL->get_all($query_args);
3301
+		} else {
3302
+			$query_args[0]['status'] = array('IN', array('publish'));
3303
+			$all_attendees    = $count
3304
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305
+				: $ATT_MDL->get_all($query_args);
3306
+		}
3307
+		return $all_attendees;
3308
+	}
3309
+
3310
+
3311
+	/**
3312
+	 * This is just taking care of resending the registration confirmation
3313
+	 *
3314
+	 * @access protected
3315
+	 * @return void
3316
+	 */
3317
+	protected function _resend_registration()
3318
+	{
3319
+		$this->_process_resend_registration();
3320
+		$query_args = isset($this->_req_data['redirect_to'])
3321
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3322
+			: array('action' => 'default');
3323
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3324
+	}
3325
+
3326
+	/**
3327
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3328
+	 * to use when selecting registrations
3329
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3330
+	 *                                                     the query parameters from the request
3331
+	 * @return void ends the request with a redirect or download
3332
+	 */
3333
+	public function _registrations_report_base( $method_name_for_getting_query_params )
3334
+	{
3335
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337
+				array(
3338
+					'page'        => 'espresso_batch',
3339
+					'batch'       => 'file',
3340
+					'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3341
+					'filters'     => urlencode(
3342
+						serialize(
3343
+							call_user_func(
3344
+								array( $this, $method_name_for_getting_query_params ),
3345
+								EEH_Array::is_set(
3346
+									$this->_req_data,
3347
+									'filters',
3348
+									array()
3349
+								)
3350
+							)
3351
+						)
3352
+				),
3353
+				'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3354
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3355
+				'return_url'  => urlencode($this->_req_data['return_url']),
3356
+			)));
3357
+		} else {
3358
+			$new_request_args = array(
3359
+				'export' => 'report',
3360
+				'action' => 'registrations_report_for_event',
3361
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362
+			);
3363
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3366
+				$EE_Export = EE_Export::instance($this->_req_data);
3367
+				$EE_Export->export();
3368
+			}
3369
+		}
3370
+	}
3371
+
3372
+
3373
+
3374
+	/**
3375
+	 * Creates a registration report using only query parameters in the request
3376
+	 * @return void
3377
+	 */
3378
+	public function _registrations_report()
3379
+	{
3380
+		$this->_registrations_report_base('_get_registration_query_parameters');
3381
+	}
3382
+
3383
+
3384
+	public function _contact_list_export()
3385
+	{
3386
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3388
+			$EE_Export = EE_Export::instance($this->_req_data);
3389
+			$EE_Export->export_attendees();
3390
+		}
3391
+	}
3392
+
3393
+
3394
+	public function _contact_list_report()
3395
+	{
3396
+		if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3397
+			wp_redirect(EE_Admin_Page::add_query_args_and_nonce(array(
3398
+				'page'        => 'espresso_batch',
3399
+				'batch'       => 'file',
3400
+				'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3401
+				'return_url'  => urlencode($this->_req_data['return_url']),
3402
+			)));
3403
+		} else {
3404
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3406
+				$EE_Export = EE_Export::instance($this->_req_data);
3407
+				$EE_Export->report_attendees();
3408
+			}
3409
+		}
3410
+	}
3411
+
3412
+
3413
+
3414
+
3415
+
3416
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3417
+	/**
3418
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3419
+	 *
3420
+	 * @return void
3421
+	 * @throws EE_Error
3422
+	 * @throws InvalidArgumentException
3423
+	 * @throws InvalidDataTypeException
3424
+	 * @throws InvalidInterfaceException
3425
+	 */
3426
+	protected function _duplicate_attendee()
3427
+	{
3428
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3429
+		//verify we have necessary info
3430
+		if (empty($this->_req_data['_REG_ID'])) {
3431
+			EE_Error::add_error(
3432
+				esc_html__(
3433
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3434
+					'event_espresso'
3435
+				), __FILE__, __LINE__, __FUNCTION__
3436
+			);
3437
+			$query_args = array('action' => $action);
3438
+			$this->_redirect_after_action('', '', '', $query_args, true);
3439
+		}
3440
+		//okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3441
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3442
+		$attendee     = $registration->attendee();
3443
+		//remove relation of existing attendee on registration
3444
+		$registration->_remove_relation_to($attendee, 'Attendee');
3445
+		//new attendee
3446
+		$new_attendee = clone $attendee;
3447
+		$new_attendee->set('ATT_ID', 0);
3448
+		$new_attendee->save();
3449
+		//add new attendee to reg
3450
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3451
+		EE_Error::add_success(
3452
+			esc_html__(
3453
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3454
+				'event_espresso'
3455
+			)
3456
+		);
3457
+		//redirect to edit page for attendee
3458
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3459
+		$this->_redirect_after_action('', '', '', $query_args, true);
3460
+	}
3461
+
3462
+
3463
+	/**
3464
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3465
+	 * @param int      $post_id
3466
+	 * @param WP_POST $post
3467
+	 * @throws DomainException
3468
+	 * @throws EE_Error
3469
+	 * @throws InvalidArgumentException
3470
+	 * @throws InvalidDataTypeException
3471
+	 * @throws InvalidInterfaceException
3472
+	 * @throws LogicException
3473
+	 * @throws InvalidFormSubmissionException
3474
+	 */
3475
+	protected function _insert_update_cpt_item($post_id, $post)
3476
+	{
3477
+		$success  = true;
3478
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3479
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3480
+			: null;
3481
+		//for attendee updates
3482
+		if ($attendee instanceof EE_Attendee) {
3483
+			//note we should only be UPDATING attendees at this point.
3484
+			$updated_fields = array(
3485
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3486
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3488
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3491
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3492
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3493
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3494
+			);
3495
+			foreach ($updated_fields as $field => $value) {
3496
+				$attendee->set($field, $value);
3497
+			}
3498
+
3499
+			//process contact details metabox form handler (which will also save the attendee)
3500
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3501
+			$success = $contact_details_form->process($this->_req_data);
3502
+
3503
+			$attendee_update_callbacks = apply_filters(
3504
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3505
+				array()
3506
+			);
3507
+			foreach ($attendee_update_callbacks as $a_callback) {
3508
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3509
+					throw new EE_Error(
3510
+						sprintf(
3511
+							esc_html__(
3512
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3513
+								'event_espresso'
3514
+							),
3515
+							$a_callback
3516
+						)
3517
+					);
3518
+				}
3519
+			}
3520
+		}
3521
+
3522
+		if ($success === false) {
3523
+			EE_Error::add_error(
3524
+				esc_html__(
3525
+					'Something went wrong with updating the meta table data for the registration.',
3526
+					'event_espresso'
3527
+				),
3528
+				__FILE__, __FUNCTION__, __LINE__
3529
+			);
3530
+		}
3531
+	}
3532
+
3533
+
3534
+	public function trash_cpt_item($post_id)
3535
+	{
3536
+	}
3537
+
3538
+
3539
+	public function delete_cpt_item($post_id)
3540
+	{
3541
+	}
3542
+
3543
+
3544
+	public function restore_cpt_item($post_id)
3545
+	{
3546
+	}
3547
+
3548
+
3549
+	protected function _restore_cpt_item($post_id, $revision_id)
3550
+	{
3551
+	}
3552
+
3553
+
3554
+	public function attendee_editor_metaboxes()
3555
+	{
3556
+		$this->verify_cpt_object();
3557
+		remove_meta_box(
3558
+			'postexcerpt',
3559
+			esc_html__('Excerpt', 'event_espresso'),
3560
+			'post_excerpt_meta_box',
3561
+			$this->_cpt_routes[$this->_req_action],
3562
+			'normal',
3563
+			'core'
3564
+		);
3565
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3566
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3567
+			add_meta_box(
3568
+				'postexcerpt',
3569
+				esc_html__('Short Biography', 'event_espresso'),
3570
+				'post_excerpt_meta_box',
3571
+				$this->_cpt_routes[$this->_req_action],
3572
+				'normal'
3573
+			);
3574
+		}
3575
+		if (post_type_supports('espresso_attendees', 'comments')) {
3576
+			add_meta_box(
3577
+				'commentsdiv',
3578
+				esc_html__('Notes on the Contact', 'event_espresso'),
3579
+				'post_comment_meta_box',
3580
+				$this->_cpt_routes[$this->_req_action],
3581
+				'normal',
3582
+				'core'
3583
+			);
3584
+		}
3585
+		add_meta_box(
3586
+			'attendee_contact_info',
3587
+			esc_html__('Contact Info', 'event_espresso'),
3588
+			array($this, 'attendee_contact_info'),
3589
+			$this->_cpt_routes[$this->_req_action],
3590
+			'side',
3591
+			'core'
3592
+		);
3593
+		add_meta_box(
3594
+			'attendee_details_address',
3595
+			esc_html__('Address Details', 'event_espresso'),
3596
+			array($this, 'attendee_address_details'),
3597
+			$this->_cpt_routes[$this->_req_action],
3598
+			'normal',
3599
+			'core'
3600
+		);
3601
+		add_meta_box(
3602
+			'attendee_registrations',
3603
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3604
+			array($this, 'attendee_registrations_meta_box'),
3605
+			$this->_cpt_routes[$this->_req_action],
3606
+			'normal',
3607
+			'high'
3608
+		);
3609
+	}
3610
+
3611
+
3612
+	/**
3613
+	 * Metabox for attendee contact info
3614
+	 *
3615
+	 * @param  WP_Post $post wp post object
3616
+	 * @return string attendee contact info ( and form )
3617
+	 * @throws EE_Error
3618
+	 * @throws InvalidArgumentException
3619
+	 * @throws InvalidDataTypeException
3620
+	 * @throws InvalidInterfaceException
3621
+	 * @throws LogicException
3622
+	 * @throws DomainException
3623
+	 */
3624
+	public function attendee_contact_info($post)
3625
+	{
3626
+		//get attendee object ( should already have it )
3627
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3628
+		$form->enqueueStylesAndScripts();
3629
+		echo $form->display();
3630
+	}
3631
+
3632
+
3633
+	/**
3634
+	 * Return form handler for the contact details metabox
3635
+	 *
3636
+	 * @param EE_Attendee $attendee
3637
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3638
+	 * @throws DomainException
3639
+	 * @throws InvalidArgumentException
3640
+	 * @throws InvalidDataTypeException
3641
+	 * @throws InvalidInterfaceException
3642
+	 */
3643
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3644
+	{
3645
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3646
+	}
3647
+
3648
+
3649
+	/**
3650
+	 * Metabox for attendee details
3651
+	 *
3652
+	 * @param  WP_Post $post wp post object
3653
+	 * @throws DomainException
3654
+	 */
3655
+	public function attendee_address_details($post)
3656
+	{
3657
+		//get attendee object (should already have it)
3658
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3659
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3660
+			new EE_Question_Form_Input(
3661
+				EE_Question::new_instance(
3662
+					array(
3663
+						'QST_ID'           => 0,
3664
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3665
+						'QST_system'       => 'admin-state',
3666
+					)
3667
+				),
3668
+				EE_Answer::new_instance(
3669
+					array(
3670
+						'ANS_ID'    => 0,
3671
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3672
+					)
3673
+				),
3674
+				array(
3675
+					'input_id'       => 'STA_ID',
3676
+					'input_name'     => 'STA_ID',
3677
+					'input_prefix'   => '',
3678
+					'append_qstn_id' => false,
3679
+				)
3680
+			)
3681
+		);
3682
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3683
+			new EE_Question_Form_Input(
3684
+				EE_Question::new_instance(
3685
+					array(
3686
+						'QST_ID'           => 0,
3687
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3688
+						'QST_system'       => 'admin-country',
3689
+					)
3690
+				),
3691
+				EE_Answer::new_instance(
3692
+					array(
3693
+						'ANS_ID'    => 0,
3694
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3695
+					)
3696
+				),
3697
+				array(
3698
+					'input_id'       => 'CNT_ISO',
3699
+					'input_name'     => 'CNT_ISO',
3700
+					'input_prefix'   => '',
3701
+					'append_qstn_id' => false,
3702
+				)
3703
+			)
3704
+		);
3705
+		$template                             =
3706
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3707
+		EEH_Template::display_template($template, $this->_template_args);
3708
+	}
3709
+
3710
+
3711
+	/**
3712
+	 *        _attendee_details
3713
+	 *
3714
+	 * @access protected
3715
+	 * @param $post
3716
+	 * @return void
3717
+	 * @throws DomainException
3718
+	 * @throws EE_Error
3719
+	 */
3720
+	public function attendee_registrations_meta_box($post)
3721
+	{
3722
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3723
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724
+		$template                              =
3725
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3726
+		EEH_Template::display_template($template, $this->_template_args);
3727
+	}
3728
+
3729
+
3730
+	/**
3731
+	 * add in the form fields for the attendee edit
3732
+	 *
3733
+	 * @param  WP_Post $post wp post object
3734
+	 * @return string html for new form.
3735
+	 * @throws DomainException
3736
+	 */
3737
+	public function after_title_form_fields($post)
3738
+	{
3739
+		if ($post->post_type == 'espresso_attendees') {
3740
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3741
+			$template_args['attendee'] = $this->_cpt_model_obj;
3742
+			EEH_Template::display_template($template, $template_args);
3743
+		}
3744
+	}
3745
+
3746
+
3747
+	/**
3748
+	 *        _trash_or_restore_attendee
3749
+	 *
3750
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3751
+	 * @return void
3752
+	 * @throws EE_Error
3753
+	 * @throws InvalidArgumentException
3754
+	 * @throws InvalidDataTypeException
3755
+	 * @throws InvalidInterfaceException
3756
+	 * @access protected
3757
+	 */
3758
+	protected function _trash_or_restore_attendees($trash = true)
3759
+	{
3760
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3761
+		$ATT_MDL = EEM_Attendee::instance();
3762
+		$success = 1;
3763
+		//Checkboxes
3764
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3765
+			// if array has more than one element than success message should be plural
3766
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3767
+			// cycle thru checkboxes
3768
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3769
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3770
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3771
+				if ( ! $updated) {
3772
+					$success = 0;
3773
+				}
3774
+			}
3775
+		} else {
3776
+			// grab single id and delete
3777
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3778
+			//get attendee
3779
+			$att     = $ATT_MDL->get_one_by_ID($ATT_ID);
3780
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3781
+			$updated = $att->save();
3782
+			if ( ! $updated) {
3783
+				$success = 0;
3784
+			}
3785
+		}
3786
+		$what        = $success > 1
3787
+			? esc_html__('Contacts', 'event_espresso')
3788
+			: esc_html__('Contact', 'event_espresso');
3789
+		$action_desc = $trash
3790
+			? esc_html__('moved to the trash', 'event_espresso')
3791
+			: esc_html__('restored', 'event_espresso');
3792
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3793
+	}
3794 3794
 
3795 3795
 }
Please login to merge, or discard this patch.
Spacing   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
         // when adding a new registration...
77 77
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
78 78
             EE_System::do_not_cache();
79
-            if (! isset($this->_req_data['processing_registration'])
79
+            if ( ! isset($this->_req_data['processing_registration'])
80 80
                  || absint($this->_req_data['processing_registration']) !== 1
81 81
             ) {
82 82
                 // and it's NOT the attendee information reg step
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
     public function _set_page_routes()
172 172
     {
173 173
         $this->_get_registration_status_array();
174
-        $reg_id             = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
174
+        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
175 175
             ? $this->_req_data['_REG_ID'] : 0;
176 176
         $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
177 177
             ? $this->_req_data['reg_status_change_form']['REG_ID']
@@ -669,7 +669,7 @@  discard block
 block discarded – undo
669 669
         //style
670 670
         wp_register_style(
671 671
             'espresso_reg',
672
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
672
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
673 673
             array('ee-admin-css'),
674 674
             EVENT_ESPRESSO_VERSION
675 675
         );
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
         //script
678 678
         wp_register_script(
679 679
             'espresso_reg',
680
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
680
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
681 681
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
682 682
             EVENT_ESPRESSO_VERSION,
683 683
             true
@@ -715,7 +715,7 @@  discard block
 block discarded – undo
715 715
         wp_dequeue_style('espresso_reg');
716 716
         wp_register_style(
717 717
             'espresso_att',
718
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
718
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
719 719
             array('ee-admin-css'),
720 720
             EVENT_ESPRESSO_VERSION
721 721
         );
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
     {
728 728
         wp_register_script(
729 729
             'ee-spco-for-admin',
730
-            REG_ASSETS_URL . 'spco_for_admin.js',
730
+            REG_ASSETS_URL.'spco_for_admin.js',
731 731
             array('underscore', 'jquery'),
732 732
             EVENT_ESPRESSO_VERSION,
733 733
             true
@@ -861,7 +861,7 @@  discard block
 block discarded – undo
861 861
                     'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
862 862
                 ),
863 863
             );
864
-            $this->_views['trash']      = array(
864
+            $this->_views['trash'] = array(
865 865
                 'slug'        => 'trash',
866 866
                 'label'       => esc_html__('Trash', 'event_espresso'),
867 867
                 'count'       => 0,
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
         $EVT_ID                                    = ! empty($this->_req_data['event_id'])
1022 1022
             ? absint($this->_req_data['event_id'])
1023 1023
             : 0;
1024
-        $ATT_ID = !empty($this->_req_data['ATT_ID'])
1024
+        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025 1025
             ? absint($this->_req_data['ATT_ID'])
1026 1026
             : 0;
1027 1027
         if ($ATT_ID) {
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post' => $ATT_ID
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
             'caps'                     => EEM_Registration::caps_read_admin,
1198 1198
             'default_where_conditions' => 'this_model_only',
1199 1199
         );
1200
-        if (! $count) {
1200
+        if ( ! $count) {
1201 1201
             $query_params = array_merge(
1202 1202
                 $query_params,
1203 1203
                 $this->_get_orderby_for_registrations_query(),
@@ -1218,7 +1218,7 @@  discard block
 block discarded – undo
1218 1218
     protected function addAttendeeIdToWhereConditions(array $request)
1219 1219
     {
1220 1220
         $where = array();
1221
-        if (! empty($request['ATT_ID'])) {
1221
+        if ( ! empty($request['ATT_ID'])) {
1222 1222
             $where['ATT_ID'] = absint($request['ATT_ID']);
1223 1223
         }
1224 1224
         return $where;
@@ -1234,7 +1234,7 @@  discard block
 block discarded – undo
1234 1234
     protected function _add_event_id_to_where_conditions(array $request)
1235 1235
     {
1236 1236
         $where = array();
1237
-        if (! empty($request['event_id'])) {
1237
+        if ( ! empty($request['event_id'])) {
1238 1238
             $where['EVT_ID'] = absint($request['event_id']);
1239 1239
         }
1240 1240
         return $where;
@@ -1250,7 +1250,7 @@  discard block
 block discarded – undo
1250 1250
     protected function _add_category_id_to_where_conditions(array $request)
1251 1251
     {
1252 1252
         $where = array();
1253
-        if (! empty($request['EVT_CAT']) && (int)$request['EVT_CAT'] !== -1) {
1253
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1254 1254
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1255 1255
         }
1256 1256
         return $where;
@@ -1266,10 +1266,10 @@  discard block
 block discarded – undo
1266 1266
     protected function _add_datetime_id_to_where_conditions(array $request)
1267 1267
     {
1268 1268
         $where = array();
1269
-        if (! empty($request['datetime_id'])) {
1269
+        if ( ! empty($request['datetime_id'])) {
1270 1270
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1271 1271
         }
1272
-        if (! empty($request['DTT_ID'])) {
1272
+        if ( ! empty($request['DTT_ID'])) {
1273 1273
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1274 1274
         }
1275 1275
         return $where;
@@ -1295,7 +1295,7 @@  discard block
 block discarded – undo
1295 1295
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1296 1296
          * UNLESS viewing trashed registrations.
1297 1297
          */
1298
-        if (! empty($registration_status)) {
1298
+        if ( ! empty($registration_status)) {
1299 1299
             $where['STS_ID'] = $registration_status;
1300 1300
         } else {
1301 1301
             //make sure we exclude incomplete registrations, but only if not trashed.
@@ -1338,12 +1338,12 @@  discard block
 block discarded – undo
1338 1338
                 array(
1339 1339
                     EEM_Registration::instance()->convert_datetime_for_query(
1340 1340
                         'REG_date',
1341
-                        $now . ' 00:00:00',
1341
+                        $now.' 00:00:00',
1342 1342
                         'Y-m-d H:i:s'
1343 1343
                     ),
1344 1344
                     EEM_Registration::instance()->convert_datetime_for_query(
1345 1345
                         'REG_date',
1346
-                        $now . ' 23:59:59',
1346
+                        $now.' 23:59:59',
1347 1347
                         'Y-m-d H:i:s'
1348 1348
                     ),
1349 1349
                 ),
@@ -1356,12 +1356,12 @@  discard block
 block discarded – undo
1356 1356
                 array(
1357 1357
                     EEM_Registration::instance()->convert_datetime_for_query(
1358 1358
                         'REG_date',
1359
-                        $current_year_and_month . '-01 00:00:00',
1359
+                        $current_year_and_month.'-01 00:00:00',
1360 1360
                         'Y-m-d H:i:s'
1361 1361
                     ),
1362 1362
                     EEM_Registration::instance()->convert_datetime_for_query(
1363 1363
                         'REG_date',
1364
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1364
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1365 1365
                         'Y-m-d H:i:s'
1366 1366
                     ),
1367 1367
                 ),
@@ -1376,18 +1376,18 @@  discard block
 block discarded – undo
1376 1376
                 : '';
1377 1377
             //if there is not a month or year then we can't go further
1378 1378
             if ($month_requested && $year_requested) {
1379
-                $days_in_month     = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1379
+                $days_in_month     = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1380 1380
                 $where['REG_date'] = array(
1381 1381
                     'BETWEEN',
1382 1382
                     array(
1383 1383
                         EEM_Registration::instance()->convert_datetime_for_query(
1384 1384
                             'REG_date',
1385
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1385
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1386 1386
                             'Y-m-d H:i:s'
1387 1387
                         ),
1388 1388
                         EEM_Registration::instance()->convert_datetime_for_query(
1389 1389
                             'REG_date',
1390
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1390
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1391 1391
                             'Y-m-d H:i:s'
1392 1392
                         ),
1393 1393
                     ),
@@ -1407,8 +1407,8 @@  discard block
 block discarded – undo
1407 1407
     protected function _add_search_to_where_conditions(array $request)
1408 1408
     {
1409 1409
         $where = array();
1410
-        if (! empty($request['s'])) {
1411
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1410
+        if ( ! empty($request['s'])) {
1411
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1412 1412
             $where['OR*search_conditions'] = array(
1413 1413
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1414 1414
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1525,7 +1525,7 @@  discard block
 block discarded – undo
1525 1525
             : $per_page;
1526 1526
 
1527 1527
         //-1 means return all results so get out if that's set.
1528
-        if ((int)$per_page === -1) {
1528
+        if ((int) $per_page === -1) {
1529 1529
             return array();
1530 1530
         }
1531 1531
         $per_page = absint($per_page);
@@ -1581,7 +1581,7 @@  discard block
 block discarded – undo
1581 1581
                 ),
1582 1582
                 REG_ADMIN_URL
1583 1583
             );
1584
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1584
+            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1585 1585
                 array(
1586 1586
                     'action' => 'default',
1587 1587
                     'EVT_ID' => $event_id,
@@ -1589,7 +1589,7 @@  discard block
 block discarded – undo
1589 1589
                 ),
1590 1590
                 admin_url('admin.php')
1591 1591
             );
1592
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1592
+            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1593 1593
                 array(
1594 1594
                     'page'   => 'espresso_events',
1595 1595
                     'action' => 'edit',
@@ -1598,12 +1598,12 @@  discard block
 block discarded – undo
1598 1598
                 admin_url('admin.php')
1599 1599
             );
1600 1600
             //next and previous links
1601
-            $next_reg                                      = $this->_registration->next(
1601
+            $next_reg = $this->_registration->next(
1602 1602
                 null,
1603 1603
                 array(),
1604 1604
                 'REG_ID'
1605 1605
             );
1606
-            $this->_template_args['next_registration']     = $next_reg
1606
+            $this->_template_args['next_registration'] = $next_reg
1607 1607
                 ? $this->_next_link(
1608 1608
                     EE_Admin_Page::add_query_args_and_nonce(
1609 1609
                         array(
@@ -1615,7 +1615,7 @@  discard block
 block discarded – undo
1615 1615
                     'dashicons dashicons-arrow-right ee-icon-size-22'
1616 1616
                 )
1617 1617
                 : '';
1618
-            $previous_reg                                  = $this->_registration->previous(
1618
+            $previous_reg = $this->_registration->previous(
1619 1619
                 null,
1620 1620
                 array(),
1621 1621
                 'REG_ID'
@@ -1633,7 +1633,7 @@  discard block
 block discarded – undo
1633 1633
                 )
1634 1634
                 : '';
1635 1635
             // grab header
1636
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1636
+            $template_path                             = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1637 1637
             $this->_template_args['REG_ID']            = $this->_registration->ID();
1638 1638
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1639 1639
                 $template_path,
@@ -1753,7 +1753,7 @@  discard block
 block discarded – undo
1753 1753
                             EEH_HTML::strong(
1754 1754
                                 $this->_registration->pretty_status(),
1755 1755
                                 '',
1756
-                                'status-' . $this->_registration->status_ID(),
1756
+                                'status-'.$this->_registration->status_ID(),
1757 1757
                                 'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1758 1758
                             )
1759 1759
                         )
@@ -1833,11 +1833,11 @@  discard block
 block discarded – undo
1833 1833
     {
1834 1834
         if (isset($this->_req_data['reg_status_change_form'])) {
1835 1835
             $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1836
-                ? (array)$this->_req_data['reg_status_change_form']['REG_ID']
1836
+                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1837 1837
                 : array();
1838 1838
         } else {
1839 1839
             $REG_IDs = isset($this->_req_data['_REG_ID'])
1840
-                ? (array)$this->_req_data['_REG_ID']
1840
+                ? (array) $this->_req_data['_REG_ID']
1841 1841
                 : array();
1842 1842
         }
1843 1843
         // sanitize $REG_IDs
@@ -1900,7 +1900,7 @@  discard block
 block discarded – undo
1900 1900
     {
1901 1901
         $success = false;
1902 1902
         // typecast $REG_IDs
1903
-        $REG_IDs = (array)$REG_IDs;
1903
+        $REG_IDs = (array) $REG_IDs;
1904 1904
         if ( ! empty($REG_IDs)) {
1905 1905
             $success = true;
1906 1906
             // set default status if none is passed
@@ -2050,7 +2050,7 @@  discard block
 block discarded – undo
2050 2050
             $action,
2051 2051
             $notify
2052 2052
         );
2053
-        $method = $action . '_registration';
2053
+        $method = $action.'_registration';
2054 2054
         if (method_exists($this, $method)) {
2055 2055
             $this->$method($notify);
2056 2056
         }
@@ -2168,7 +2168,7 @@  discard block
 block discarded – undo
2168 2168
             $filtered_line_item_tree,
2169 2169
             array('EE_Registration' => $this->_registration)
2170 2170
         );
2171
-        $attendee                                = $this->_registration->attendee();
2171
+        $attendee = $this->_registration->attendee();
2172 2172
         if (EE_Registry::instance()->CAP->current_user_can(
2173 2173
             'ee_read_transaction',
2174 2174
             'espresso_transactions_view_transaction'
@@ -2247,7 +2247,7 @@  discard block
 block discarded – undo
2247 2247
                 'Payment method response',
2248 2248
                 'event_espresso'
2249 2249
             );
2250
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2250
+            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2251 2251
         }
2252 2252
         $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2253 2253
         $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
@@ -2275,7 +2275,7 @@  discard block
 block discarded – undo
2275 2275
         $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2276 2276
         $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2277 2277
         $template_path                                                        =
2278
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2278
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2279 2279
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2280 2280
     }
2281 2281
 
@@ -2304,7 +2304,7 @@  discard block
 block discarded – undo
2304 2304
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2305 2305
             $this->_template_args['REG_ID']                    = $this->_registration->ID();
2306 2306
             $template_path                                     =
2307
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2307
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2308 2308
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2309 2309
         }
2310 2310
     }
@@ -2321,7 +2321,7 @@  discard block
 block discarded – undo
2321 2321
     public function form_before_question_group($output)
2322 2322
     {
2323 2323
         EE_Error::doing_it_wrong(
2324
-            __CLASS__ . '::' . __FUNCTION__,
2324
+            __CLASS__.'::'.__FUNCTION__,
2325 2325
             esc_html__(
2326 2326
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2327 2327
                 'event_espresso'
@@ -2346,7 +2346,7 @@  discard block
 block discarded – undo
2346 2346
     public function form_after_question_group($output)
2347 2347
     {
2348 2348
         EE_Error::doing_it_wrong(
2349
-            __CLASS__ . '::' . __FUNCTION__,
2349
+            __CLASS__.'::'.__FUNCTION__,
2350 2350
             esc_html__(
2351 2351
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2352 2352
                 'event_espresso'
@@ -2384,7 +2384,7 @@  discard block
 block discarded – undo
2384 2384
     public function form_form_field_label_wrap($label)
2385 2385
     {
2386 2386
         EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2387
+            __CLASS__.'::'.__FUNCTION__,
2388 2388
             esc_html__(
2389 2389
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390 2390
                 'event_espresso'
@@ -2394,7 +2394,7 @@  discard block
 block discarded – undo
2394 2394
         return '
2395 2395
 			<tr>
2396 2396
 				<th>
2397
-					' . $label . '
2397
+					' . $label.'
2398 2398
 				</th>';
2399 2399
     }
2400 2400
 
@@ -2410,7 +2410,7 @@  discard block
 block discarded – undo
2410 2410
     public function form_form_field_input__wrap($input)
2411 2411
     {
2412 2412
         EE_Error::doing_it_wrong(
2413
-            __CLASS__ . '::' . __FUNCTION__,
2413
+            __CLASS__.'::'.__FUNCTION__,
2414 2414
             esc_html__(
2415 2415
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2416 2416
                 'event_espresso'
@@ -2419,7 +2419,7 @@  discard block
 block discarded – undo
2419 2419
         );
2420 2420
         return '
2421 2421
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2422
-					' . $input . '
2422
+					' . $input.'
2423 2423
 				</td>
2424 2424
 			</tr>';
2425 2425
     }
@@ -2464,7 +2464,7 @@  discard block
 block discarded – undo
2464 2464
     protected function _get_reg_custom_questions_form($REG_ID)
2465 2465
     {
2466 2466
         if ( ! $this->_reg_custom_questions_form) {
2467
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2467
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2468 2468
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2469 2469
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2470 2470
             );
@@ -2500,7 +2500,7 @@  discard block
 block discarded – undo
2500 2500
         if ($form->is_valid()) {
2501 2501
             foreach ($form->subforms() as $question_group_id => $question_group_form) {
2502 2502
                 foreach ($question_group_form->inputs() as $question_id => $input) {
2503
-                    $where_conditions    = array(
2503
+                    $where_conditions = array(
2504 2504
                         'QST_ID' => $question_id,
2505 2505
                         'REG_ID' => $REG_ID,
2506 2506
                     );
@@ -2541,7 +2541,7 @@  discard block
 block discarded – undo
2541 2541
         $REG = EEM_Registration::instance();
2542 2542
         //get all other registrations on this transaction, and cache
2543 2543
         //the attendees for them so we don't have to run another query using force_join
2544
-        $registrations                           = $REG->get_all(array(
2544
+        $registrations = $REG->get_all(array(
2545 2545
             array(
2546 2546
                 'TXN_ID' => $this->_registration->transaction_ID(),
2547 2547
                 'REG_ID' => array('!=', $this->_registration->ID()),
@@ -2565,7 +2565,7 @@  discard block
 block discarded – undo
2565 2565
             $att_nmbr = 1;
2566 2566
             foreach ($registrations as $registration) {
2567 2567
                 /* @var $registration EE_Registration */
2568
-                $attendee                                                    = $registration->attendee()
2568
+                $attendee = $registration->attendee()
2569 2569
                     ? $registration->attendee()
2570 2570
                     : EEM_Attendee::instance()
2571 2571
                                   ->create_default_object();
@@ -2578,19 +2578,19 @@  discard block
 block discarded – undo
2578 2578
                     ', ',
2579 2579
                     $attendee->full_address_as_array()
2580 2580
                 );
2581
-                $this->_template_args['attendees'][$att_nmbr]['att_link']    = self::add_query_args_and_nonce(
2581
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2582 2582
                     array(
2583 2583
                         'action' => 'edit_attendee',
2584 2584
                         'post'   => $attendee->ID(),
2585 2585
                     ),
2586 2586
                     REG_ADMIN_URL
2587 2587
                 );
2588
-                $this->_template_args['attendees'][$att_nmbr]['event_name']  = $registration->event_obj()->name();
2588
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj()->name();
2589 2589
                 $att_nmbr++;
2590 2590
             }
2591 2591
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2592 2592
         }
2593
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2593
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2594 2594
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2595 2595
     }
2596 2596
 
@@ -2633,20 +2633,20 @@  discard block
 block discarded – undo
2633 2633
         $this->_template_args['phone']             = $attendee->phone();
2634 2634
         $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2635 2635
         //edit link
2636
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(array(
2636
+        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(array(
2637 2637
             'action' => 'edit_attendee',
2638 2638
             'post'   => $attendee->ID(),
2639 2639
         ), REG_ADMIN_URL);
2640 2640
         $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2641 2641
         //create link
2642
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2642
+        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2643 2643
             ? EE_Admin_Page::add_query_args_and_nonce(array(
2644 2644
                 'action'  => 'duplicate_attendee',
2645 2645
                 '_REG_ID' => $this->_registration->ID(),
2646 2646
             ), REG_ADMIN_URL) : '';
2647 2647
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2648 2648
         $this->_template_args['att_check']    = $att_check;
2649
-        $template_path                        = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2649
+        $template_path                        = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2650 2650
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2651 2651
     }
2652 2652
 
@@ -2691,7 +2691,7 @@  discard block
 block discarded – undo
2691 2691
             /** @var EE_Registration $REG */
2692 2692
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2693 2693
             $payments = $REG->registration_payments();
2694
-            if (! empty($payments)) {
2694
+            if ( ! empty($payments)) {
2695 2695
                 $name = $REG->attendee() instanceof EE_Attendee
2696 2696
                     ? $REG->attendee()->full_name()
2697 2697
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2887,7 +2887,7 @@  discard block
 block discarded – undo
2887 2887
                 'action' => 'edit',
2888 2888
                 'post'   => $this->_reg_event->ID(),
2889 2889
             ), EVENTS_ADMIN_URL);
2890
-            $edit_event_lnk                     = '<a href="'
2890
+            $edit_event_lnk = '<a href="'
2891 2891
                                                   . $edit_event_url
2892 2892
                                                   . '" title="'
2893 2893
                                                   . esc_attr__('Edit ', 'event_espresso')
@@ -2905,7 +2905,7 @@  discard block
 block discarded – undo
2905 2905
         }
2906 2906
         // grab header
2907 2907
         $template_path                              =
2908
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2908
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2909 2909
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path,
2910 2910
             $this->_template_args, true);
2911 2911
         //$this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
@@ -2943,7 +2943,7 @@  discard block
 block discarded – undo
2943 2943
                 '</b>'
2944 2944
             );
2945 2945
             return '
2946
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2946
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
2947 2947
 	<script >
2948 2948
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
2949 2949
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3011,7 +3011,7 @@  discard block
 block discarded – undo
3011 3011
         //we come back to the process_registration_step route.
3012 3012
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3013 3013
         return EEH_Template::display_template(
3014
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3014
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3015 3015
             $template_args,
3016 3016
             true
3017 3017
         );
@@ -3033,7 +3033,7 @@  discard block
 block discarded – undo
3033 3033
         if (is_object($this->_reg_event)) {
3034 3034
             return true;
3035 3035
         }
3036
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3036
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3037 3037
         if ( ! $EVT_ID) {
3038 3038
             return false;
3039 3039
         }
@@ -3103,7 +3103,7 @@  discard block
 block discarded – undo
3103 3103
                 }
3104 3104
                 break;
3105 3105
             case 'questions' :
3106
-                if (! isset(
3106
+                if ( ! isset(
3107 3107
                     $this->_req_data['txn_reg_status_change'],
3108 3108
                     $this->_req_data['txn_reg_status_change']['send_notifications'])
3109 3109
                 ) {
@@ -3223,7 +3223,7 @@  discard block
 block discarded – undo
3223 3223
     public function get_attendees($per_page, $count = false, $trash = false)
3224 3224
     {
3225 3225
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3226
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3226
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3227 3227
         $ATT_MDL                    = EEM_Attendee::instance();
3228 3228
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3229 3229
         switch ($this->_req_data['orderby']) {
@@ -3263,7 +3263,7 @@  discard block
 block discarded – undo
3263 3263
             : $per_page;
3264 3264
         $_where       = array();
3265 3265
         if ( ! empty($this->_req_data['s'])) {
3266
-            $sstr         = '%' . $this->_req_data['s'] . '%';
3266
+            $sstr         = '%'.$this->_req_data['s'].'%';
3267 3267
             $_where['OR'] = array(
3268 3268
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3269 3269
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3290,17 +3290,17 @@  discard block
 block discarded – undo
3290 3290
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3291 3291
             'limit' => $limit
3292 3292
         );
3293
-        if (! $count) {
3293
+        if ( ! $count) {
3294 3294
             $query_args['order_by'] = array($orderby => $sort);
3295 3295
         }
3296 3296
         if ($trash) {
3297 3297
             $query_args[0]['status'] = array('!=', 'publish');
3298
-            $all_attendees    = $count
3298
+            $all_attendees = $count
3299 3299
                 ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3300 3300
                 : $ATT_MDL->get_all($query_args);
3301 3301
         } else {
3302 3302
             $query_args[0]['status'] = array('IN', array('publish'));
3303
-            $all_attendees    = $count
3303
+            $all_attendees = $count
3304 3304
                 ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3305 3305
                 : $ATT_MDL->get_all($query_args);
3306 3306
         }
@@ -3330,9 +3330,9 @@  discard block
 block discarded – undo
3330 3330
      *                                                     the query parameters from the request
3331 3331
      * @return void ends the request with a redirect or download
3332 3332
      */
3333
-    public function _registrations_report_base( $method_name_for_getting_query_params )
3333
+    public function _registrations_report_base($method_name_for_getting_query_params)
3334 3334
     {
3335
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3335
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3336 3336
             wp_redirect(EE_Admin_Page::add_query_args_and_nonce(
3337 3337
                 array(
3338 3338
                     'page'        => 'espresso_batch',
@@ -3341,7 +3341,7 @@  discard block
 block discarded – undo
3341 3341
                     'filters'     => urlencode(
3342 3342
                         serialize(
3343 3343
                             call_user_func(
3344
-                                array( $this, $method_name_for_getting_query_params ),
3344
+                                array($this, $method_name_for_getting_query_params),
3345 3345
                                 EEH_Array::is_set(
3346 3346
                                     $this->_req_data,
3347 3347
                                     'filters',
@@ -3361,8 +3361,8 @@  discard block
 block discarded – undo
3361 3361
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3362 3362
             );
3363 3363
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3364
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3365
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3364
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3365
+                require_once(EE_CLASSES.'EE_Export.class.php');
3366 3366
                 $EE_Export = EE_Export::instance($this->_req_data);
3367 3367
                 $EE_Export->export();
3368 3368
             }
@@ -3383,8 +3383,8 @@  discard block
 block discarded – undo
3383 3383
 
3384 3384
     public function _contact_list_export()
3385 3385
     {
3386
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3387
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3386
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3387
+            require_once(EE_CLASSES.'EE_Export.class.php');
3388 3388
             $EE_Export = EE_Export::instance($this->_req_data);
3389 3389
             $EE_Export->export_attendees();
3390 3390
         }
@@ -3401,8 +3401,8 @@  discard block
 block discarded – undo
3401 3401
                 'return_url'  => urlencode($this->_req_data['return_url']),
3402 3402
             )));
3403 3403
         } else {
3404
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3405
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3404
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3405
+                require_once(EE_CLASSES.'EE_Export.class.php');
3406 3406
                 $EE_Export = EE_Export::instance($this->_req_data);
3407 3407
                 $EE_Export->report_attendees();
3408 3408
             }
@@ -3484,7 +3484,7 @@  discard block
 block discarded – undo
3484 3484
             $updated_fields = array(
3485 3485
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3486 3486
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3487
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3487
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3488 3488
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3489 3489
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3490 3490
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3702,8 +3702,8 @@  discard block
 block discarded – undo
3702 3702
                 )
3703 3703
             )
3704 3704
         );
3705
-        $template                             =
3706
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3705
+        $template =
3706
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3707 3707
         EEH_Template::display_template($template, $this->_template_args);
3708 3708
     }
3709 3709
 
@@ -3722,7 +3722,7 @@  discard block
 block discarded – undo
3722 3722
         $this->_template_args['attendee']      = $this->_cpt_model_obj;
3723 3723
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3724 3724
         $template                              =
3725
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3725
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3726 3726
         EEH_Template::display_template($template, $this->_template_args);
3727 3727
     }
3728 3728
 
@@ -3737,7 +3737,7 @@  discard block
 block discarded – undo
3737 3737
     public function after_title_form_fields($post)
3738 3738
     {
3739 3739
         if ($post->post_type == 'espresso_attendees') {
3740
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3740
+            $template                  = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3741 3741
             $template_args['attendee'] = $this->_cpt_model_obj;
3742 3742
             EEH_Template::display_template($template, $template_args);
3743 3743
         }
Please login to merge, or discard this patch.
admin_pages/transactions/templates/txn_admin_details_header.template.php 1 patch
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -1,17 +1,17 @@
 block discarded – undo
1 1
 
2
-		<h3 class="txn-navigation-strip"><?php echo $previous_transaction . '&nbsp;'; echo __( 'Transaction # ', 'event_espresso' ) . $txn_nmbr['value']; echo '&nbsp;' . $next_transaction; ?></h3>
3
-		<h2 id="txn-date-h2" class="txn-date-h2"><?php echo $txn_datetime['value'];?></h2>
2
+		<h3 class="txn-navigation-strip"><?php echo $previous_transaction.'&nbsp;'; echo __('Transaction # ', 'event_espresso').$txn_nmbr['value']; echo '&nbsp;'.$next_transaction; ?></h3>
3
+		<h2 id="txn-date-h2" class="txn-date-h2"><?php echo $txn_datetime['value']; ?></h2>
4 4
 		<h2 id="txn-status-h2" class="txn-status-h2">
5
-			<?php echo __( 'Transaction Status: ', 'event_espresso' );?><span id="txn-status" class="<?php echo $txn_status['class'];?>"><?php echo $txn_status['value'];?></span>
5
+			<?php echo __('Transaction Status: ', 'event_espresso'); ?><span id="txn-status" class="<?php echo $txn_status['class']; ?>"><?php echo $txn_status['value']; ?></span>
6 6
 		</h2>
7 7
 
8 8
 	<?php $attributes = $amount_due ? 'class="txn-amount-due-h2"' : 'class="txn-amount-due-h2 hidden"'; ?>
9 9
 		<h2 id="txn-amount-due-h2" <?php echo $attributes; ?>>
10
-			<?php echo __( 'Total Amount Due: ', 'event_espresso' );?><span id="txn-admin-total-amount-due" class="<?php echo $amount_due_class;?>"><?php echo $amount_due;?></span>
10
+			<?php echo __('Total Amount Due: ', 'event_espresso'); ?><span id="txn-admin-total-amount-due" class="<?php echo $amount_due_class; ?>"><?php echo $amount_due; ?></span>
11 11
 		</h2>
12 12
 
13 13
 		<h3 id="txn-selected-method-of-payment-h3" class="txn-selected-method-of-payment-h3">
14
-			<?php echo __( 'Last Method of Payment: ', 'event_espresso' );?><?php echo $method_of_payment_name;?>
14
+			<?php echo __('Last Method of Payment: ', 'event_espresso'); ?><?php echo $method_of_payment_name; ?>
15 15
 		</h3>
16 16
 
17 17
 
Please login to merge, or discard this patch.
core/services/Benchmark.php 2 patches
Indentation   +304 added lines, -304 removed lines patch added patch discarded remove patch
@@ -20,310 +20,310 @@
 block discarded – undo
20 20
 class Benchmark
21 21
 {
22 22
 
23
-    /**
24
-     * array containing the start time for the timers
25
-     */
26
-    private static $start_times;
27
-
28
-    /**
29
-     * array containing all the timer'd times, which can be outputted via show_times()
30
-     */
31
-    private static $times = array();
32
-
33
-    /**
34
-     * @var array
35
-     */
36
-    protected static $memory_usage = array();
37
-
38
-
39
-
40
-    /**
41
-     * whether to benchmark code or not
42
-     */
43
-    public static function doNotRun()
44
-    {
45
-        return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX);
46
-    }
47
-
48
-
49
-
50
-    /**
51
-     * resetTimes
52
-     */
53
-    public static function resetTimes()
54
-    {
55
-        Benchmark::$times = array();
56
-    }
57
-
58
-
59
-
60
-    /**
61
-     * Add Benchmark::startTimer() before a block of code you want to measure the performance of
62
-     *
63
-     * @param null $timer_name
64
-     */
65
-    public static function startTimer($timer_name = null)
66
-    {
67
-        if (Benchmark::doNotRun()) {
68
-            return;
69
-        }
70
-        $timer_name = $timer_name !== '' ? $timer_name : get_called_class();
71
-        Benchmark::$start_times[$timer_name] = microtime(true);
72
-    }
73
-
74
-
75
-
76
-    /**
77
-     * Add Benchmark::stopTimer() after a block of code you want to measure the performance of
78
-     *
79
-     * @param string $timer_name
80
-     */
81
-    public static function stopTimer($timer_name = '')
82
-    {
83
-        if (Benchmark::doNotRun()) {
84
-            return;
85
-        }
86
-        $timer_name = $timer_name !== '' ? $timer_name : get_called_class();
87
-        if (isset(Benchmark::$start_times[$timer_name])) {
88
-            $start_time = Benchmark::$start_times[$timer_name];
89
-            unset(Benchmark::$start_times[$timer_name]);
90
-        } else {
91
-            $start_time = array_pop(Benchmark::$start_times);
92
-        }
93
-        Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8);
94
-    }
95
-
96
-
97
-
98
-    /**
99
-     * Measure the memory usage by PHP so far.
100
-     *
101
-     * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
102
-     * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
103
-     * @param bool    $formatted
104
-     * @return void
105
-     */
106
-    public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true)
107
-    {
108
-        if (Benchmark::doNotRun()) {
109
-            return;
110
-        }
111
-        $memory_used = Benchmark::convert(memory_get_usage(true));
112
-        Benchmark::$memory_usage[$label] = $memory_used;
113
-        if ($output_now) {
114
-            echo $formatted
115
-                ? "<br>{$label} : {$memory_used}"
116
-                : "\n {$label} : {$memory_used}";
117
-        }
118
-    }
119
-
120
-
121
-
122
-    /**
123
-     * will display the benchmarking results at shutdown
124
-     *
125
-     * @param bool $formatted
126
-     * @return void
127
-     */
128
-    public static function displayResultsAtShutdown($formatted = true)
129
-    {
130
-        add_action(
131
-            'shutdown',
132
-            function () use ($formatted) {
133
-                Benchmark::displayResults(true, $formatted);
134
-            }
135
-        );
136
-    }
137
-
138
-
139
-
140
-    /**
141
-     * will display the benchmarking results at shutdown
142
-     *
143
-     * @param string $filepath
144
-     * @param bool   $formatted
145
-     * @param bool   $append
146
-     * @return void
147
-     */
148
-    public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true)
149
-    {
150
-        add_action(
151
-            'shutdown',
152
-            function () use ($filepath, $formatted, $append) {
153
-                Benchmark::writeResultsToFile($filepath, $formatted, $append);
154
-            }
155
-        );
156
-    }
157
-
158
-
159
-
160
-    /**
161
-     * @param bool $formatted
162
-     * @return string
163
-     */
164
-    private static function generateResults($formatted = true)
165
-    {
166
-        if (Benchmark::doNotRun()) {
167
-            return '';
168
-        }
169
-        $output = '';
170
-        if (! empty(Benchmark::$times)) {
171
-            $total = 0;
172
-            $output .= $formatted
173
-                ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
174
-                : '';
175
-            foreach (Benchmark::$times as $timer_name => $total_time) {
176
-                $output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
177
-                $output .= $formatted ? '<br />'  : "\n";
178
-                $total += $total_time;
179
-            }
180
-            if($formatted) {
181
-                $output .= '<br />';
182
-                $output .= '<h4>TOTAL TIME</h4>';
183
-                $output .= Benchmark::formatTime('', $total, $formatted);
184
-                $output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />';
185
-                $output .= '<br />';
186
-                $output .= '<h5>Performance scale (from best to worse)</h5>';
187
-                $output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />';
188
-                $output .= '<span style="color:deepskyblue">Like...no way man!</span><br />';
189
-                $output .= '<span style="color:limegreen">Like...groovy!</span><br />';
190
-                $output .= '<span style="color:gold">Ruh Oh</span><br />';
191
-                $output .= '<span style="color:darkorange">Zoinks!</span><br />';
192
-                $output .= '<span style="color:red">Like...HEEELLLP</span><br />';
193
-            }
194
-        }
195
-        if (! empty(Benchmark::$memory_usage)) {
196
-            $output .= $formatted
197
-                ? '<h5>Memory</h5>'
198
-                : "\nMemory";
199
-            foreach (Benchmark::$memory_usage as $label => $memory_usage) {
200
-                $output .= $formatted
201
-                    ? '<br />'
202
-                    : "\n";
203
-                $output .= "{$memory_usage} : {$label}";
204
-            }
205
-        }
206
-        if (empty($output)) {
207
-            return '';
208
-        }
209
-        $output = $formatted
210
-            ? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
211
-              . (is_admin()
212
-                ? ' margin:2em 2em 2em 180px;'
213
-                : ' margin:2em;')
214
-              . ' padding:2em;">'
215
-              . '<h4>BENCHMARKING</h4>'
216
-              . $output
217
-              . '</div>'
218
-            : $output;
219
-        return $output;
220
-    }
221
-
222
-
223
-
224
-    /**
225
-     * @param bool $echo
226
-     * @param bool $formatted
227
-     * @return string
228
-     */
229
-    public static function displayResults($echo = true, $formatted = true)
230
-    {
231
-        $results = Benchmark::generateResults($formatted);
232
-        if ($echo) {
233
-            echo $results;
234
-            $results = '';
235
-        }
236
-        return $results;
237
-    }
238
-
239
-
240
-    /**
241
-     * @param string $filepath
242
-     * @param bool   $formatted
243
-     * @param bool   $append
244
-     * @throws EE_Error
245
-     */
246
-    public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
247
-    {
248
-        $filepath = ! empty($filepath) && is_readable(dirname($filepath))
249
-            ? $filepath
250
-            : '';
251
-        if( empty($filepath)) {
252
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
253
-        }
254
-        EEH_File::ensure_file_exists_and_is_writable($filepath);
255
-        file_put_contents(
256
-            $filepath,
257
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
258
-            $append ? FILE_APPEND | LOCK_EX : LOCK_EX
259
-        );
260
-    }
261
-
262
-
263
-
264
-    /**
265
-     * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
266
-     *
267
-     * @param int $size
268
-     * @return string
269
-     */
270
-    public static function convert($size)
271
-    {
272
-        $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
273
-        return round(
274
-            $size / pow(1024, $i = floor(log($size, 1024))),
275
-            2
276
-        ) . ' ' . $unit[absint($i)];
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * @param string $timer_name
283
-     * @param float  $total_time
284
-     * @param bool   $formatted
285
-     * @return string
286
-     */
287
-    public static function formatTime($timer_name, $total_time, $formatted = true)
288
-    {
289
-        $total_time *= 1000;
290
-        switch ($total_time) {
291
-            case $total_time > 12500 :
292
-                $color = 'red';
293
-                $bold = 'bold';
294
-                break;
295
-            case $total_time > 2500 :
296
-                $color = 'darkorange';
297
-                $bold = 'bold';
298
-                break;
299
-            case $total_time > 500 :
300
-                $color = 'gold';
301
-                $bold = 'bold';
302
-                break;
303
-            case $total_time > 100 :
304
-                $color = 'limegreen';
305
-                $bold = 'normal';
306
-                break;
307
-            case $total_time > 20 :
308
-                $color = 'deepskyblue';
309
-                $bold = 'normal';
310
-                break;
311
-            default :
312
-                $color = 'mediumpurple';
313
-                $bold = 'normal';
314
-                break;
315
-        }
316
-        return $formatted
317
-            ? '<span style="min-width: 10px; margin:0 1em; color:'
318
-               . $color
319
-               . '; font-weight:'
320
-               . $bold
321
-               . '; font-size:1.2em;">'
322
-               . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
323
-               . '</span> '
324
-               . $timer_name
325
-            :  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
326
-    }
23
+	/**
24
+	 * array containing the start time for the timers
25
+	 */
26
+	private static $start_times;
27
+
28
+	/**
29
+	 * array containing all the timer'd times, which can be outputted via show_times()
30
+	 */
31
+	private static $times = array();
32
+
33
+	/**
34
+	 * @var array
35
+	 */
36
+	protected static $memory_usage = array();
37
+
38
+
39
+
40
+	/**
41
+	 * whether to benchmark code or not
42
+	 */
43
+	public static function doNotRun()
44
+	{
45
+		return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX);
46
+	}
47
+
48
+
49
+
50
+	/**
51
+	 * resetTimes
52
+	 */
53
+	public static function resetTimes()
54
+	{
55
+		Benchmark::$times = array();
56
+	}
57
+
58
+
59
+
60
+	/**
61
+	 * Add Benchmark::startTimer() before a block of code you want to measure the performance of
62
+	 *
63
+	 * @param null $timer_name
64
+	 */
65
+	public static function startTimer($timer_name = null)
66
+	{
67
+		if (Benchmark::doNotRun()) {
68
+			return;
69
+		}
70
+		$timer_name = $timer_name !== '' ? $timer_name : get_called_class();
71
+		Benchmark::$start_times[$timer_name] = microtime(true);
72
+	}
73
+
74
+
75
+
76
+	/**
77
+	 * Add Benchmark::stopTimer() after a block of code you want to measure the performance of
78
+	 *
79
+	 * @param string $timer_name
80
+	 */
81
+	public static function stopTimer($timer_name = '')
82
+	{
83
+		if (Benchmark::doNotRun()) {
84
+			return;
85
+		}
86
+		$timer_name = $timer_name !== '' ? $timer_name : get_called_class();
87
+		if (isset(Benchmark::$start_times[$timer_name])) {
88
+			$start_time = Benchmark::$start_times[$timer_name];
89
+			unset(Benchmark::$start_times[$timer_name]);
90
+		} else {
91
+			$start_time = array_pop(Benchmark::$start_times);
92
+		}
93
+		Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8);
94
+	}
95
+
96
+
97
+
98
+	/**
99
+	 * Measure the memory usage by PHP so far.
100
+	 *
101
+	 * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
102
+	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
103
+	 * @param bool    $formatted
104
+	 * @return void
105
+	 */
106
+	public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true)
107
+	{
108
+		if (Benchmark::doNotRun()) {
109
+			return;
110
+		}
111
+		$memory_used = Benchmark::convert(memory_get_usage(true));
112
+		Benchmark::$memory_usage[$label] = $memory_used;
113
+		if ($output_now) {
114
+			echo $formatted
115
+				? "<br>{$label} : {$memory_used}"
116
+				: "\n {$label} : {$memory_used}";
117
+		}
118
+	}
119
+
120
+
121
+
122
+	/**
123
+	 * will display the benchmarking results at shutdown
124
+	 *
125
+	 * @param bool $formatted
126
+	 * @return void
127
+	 */
128
+	public static function displayResultsAtShutdown($formatted = true)
129
+	{
130
+		add_action(
131
+			'shutdown',
132
+			function () use ($formatted) {
133
+				Benchmark::displayResults(true, $formatted);
134
+			}
135
+		);
136
+	}
137
+
138
+
139
+
140
+	/**
141
+	 * will display the benchmarking results at shutdown
142
+	 *
143
+	 * @param string $filepath
144
+	 * @param bool   $formatted
145
+	 * @param bool   $append
146
+	 * @return void
147
+	 */
148
+	public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true)
149
+	{
150
+		add_action(
151
+			'shutdown',
152
+			function () use ($filepath, $formatted, $append) {
153
+				Benchmark::writeResultsToFile($filepath, $formatted, $append);
154
+			}
155
+		);
156
+	}
157
+
158
+
159
+
160
+	/**
161
+	 * @param bool $formatted
162
+	 * @return string
163
+	 */
164
+	private static function generateResults($formatted = true)
165
+	{
166
+		if (Benchmark::doNotRun()) {
167
+			return '';
168
+		}
169
+		$output = '';
170
+		if (! empty(Benchmark::$times)) {
171
+			$total = 0;
172
+			$output .= $formatted
173
+				? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
174
+				: '';
175
+			foreach (Benchmark::$times as $timer_name => $total_time) {
176
+				$output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
177
+				$output .= $formatted ? '<br />'  : "\n";
178
+				$total += $total_time;
179
+			}
180
+			if($formatted) {
181
+				$output .= '<br />';
182
+				$output .= '<h4>TOTAL TIME</h4>';
183
+				$output .= Benchmark::formatTime('', $total, $formatted);
184
+				$output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />';
185
+				$output .= '<br />';
186
+				$output .= '<h5>Performance scale (from best to worse)</h5>';
187
+				$output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />';
188
+				$output .= '<span style="color:deepskyblue">Like...no way man!</span><br />';
189
+				$output .= '<span style="color:limegreen">Like...groovy!</span><br />';
190
+				$output .= '<span style="color:gold">Ruh Oh</span><br />';
191
+				$output .= '<span style="color:darkorange">Zoinks!</span><br />';
192
+				$output .= '<span style="color:red">Like...HEEELLLP</span><br />';
193
+			}
194
+		}
195
+		if (! empty(Benchmark::$memory_usage)) {
196
+			$output .= $formatted
197
+				? '<h5>Memory</h5>'
198
+				: "\nMemory";
199
+			foreach (Benchmark::$memory_usage as $label => $memory_usage) {
200
+				$output .= $formatted
201
+					? '<br />'
202
+					: "\n";
203
+				$output .= "{$memory_usage} : {$label}";
204
+			}
205
+		}
206
+		if (empty($output)) {
207
+			return '';
208
+		}
209
+		$output = $formatted
210
+			? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
211
+			  . (is_admin()
212
+				? ' margin:2em 2em 2em 180px;'
213
+				: ' margin:2em;')
214
+			  . ' padding:2em;">'
215
+			  . '<h4>BENCHMARKING</h4>'
216
+			  . $output
217
+			  . '</div>'
218
+			: $output;
219
+		return $output;
220
+	}
221
+
222
+
223
+
224
+	/**
225
+	 * @param bool $echo
226
+	 * @param bool $formatted
227
+	 * @return string
228
+	 */
229
+	public static function displayResults($echo = true, $formatted = true)
230
+	{
231
+		$results = Benchmark::generateResults($formatted);
232
+		if ($echo) {
233
+			echo $results;
234
+			$results = '';
235
+		}
236
+		return $results;
237
+	}
238
+
239
+
240
+	/**
241
+	 * @param string $filepath
242
+	 * @param bool   $formatted
243
+	 * @param bool   $append
244
+	 * @throws EE_Error
245
+	 */
246
+	public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
247
+	{
248
+		$filepath = ! empty($filepath) && is_readable(dirname($filepath))
249
+			? $filepath
250
+			: '';
251
+		if( empty($filepath)) {
252
+			$filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
253
+		}
254
+		EEH_File::ensure_file_exists_and_is_writable($filepath);
255
+		file_put_contents(
256
+			$filepath,
257
+			"\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
258
+			$append ? FILE_APPEND | LOCK_EX : LOCK_EX
259
+		);
260
+	}
261
+
262
+
263
+
264
+	/**
265
+	 * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
266
+	 *
267
+	 * @param int $size
268
+	 * @return string
269
+	 */
270
+	public static function convert($size)
271
+	{
272
+		$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
273
+		return round(
274
+			$size / pow(1024, $i = floor(log($size, 1024))),
275
+			2
276
+		) . ' ' . $unit[absint($i)];
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * @param string $timer_name
283
+	 * @param float  $total_time
284
+	 * @param bool   $formatted
285
+	 * @return string
286
+	 */
287
+	public static function formatTime($timer_name, $total_time, $formatted = true)
288
+	{
289
+		$total_time *= 1000;
290
+		switch ($total_time) {
291
+			case $total_time > 12500 :
292
+				$color = 'red';
293
+				$bold = 'bold';
294
+				break;
295
+			case $total_time > 2500 :
296
+				$color = 'darkorange';
297
+				$bold = 'bold';
298
+				break;
299
+			case $total_time > 500 :
300
+				$color = 'gold';
301
+				$bold = 'bold';
302
+				break;
303
+			case $total_time > 100 :
304
+				$color = 'limegreen';
305
+				$bold = 'normal';
306
+				break;
307
+			case $total_time > 20 :
308
+				$color = 'deepskyblue';
309
+				$bold = 'normal';
310
+				break;
311
+			default :
312
+				$color = 'mediumpurple';
313
+				$bold = 'normal';
314
+				break;
315
+		}
316
+		return $formatted
317
+			? '<span style="min-width: 10px; margin:0 1em; color:'
318
+			   . $color
319
+			   . '; font-weight:'
320
+			   . $bold
321
+			   . '; font-size:1.2em;">'
322
+			   . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
323
+			   . '</span> '
324
+			   . $timer_name
325
+			:  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
326
+	}
327 327
 
328 328
 
329 329
 
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
     {
130 130
         add_action(
131 131
             'shutdown',
132
-            function () use ($formatted) {
132
+            function() use ($formatted) {
133 133
                 Benchmark::displayResults(true, $formatted);
134 134
             }
135 135
         );
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
     {
150 150
         add_action(
151 151
             'shutdown',
152
-            function () use ($filepath, $formatted, $append) {
152
+            function() use ($filepath, $formatted, $append) {
153 153
                 Benchmark::writeResultsToFile($filepath, $formatted, $append);
154 154
             }
155 155
         );
@@ -167,17 +167,17 @@  discard block
 block discarded – undo
167 167
             return '';
168 168
         }
169 169
         $output = '';
170
-        if (! empty(Benchmark::$times)) {
170
+        if ( ! empty(Benchmark::$times)) {
171 171
             $total = 0;
172 172
             $output .= $formatted
173 173
                 ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
174 174
                 : '';
175 175
             foreach (Benchmark::$times as $timer_name => $total_time) {
176 176
                 $output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
177
-                $output .= $formatted ? '<br />'  : "\n";
177
+                $output .= $formatted ? '<br />' : "\n";
178 178
                 $total += $total_time;
179 179
             }
180
-            if($formatted) {
180
+            if ($formatted) {
181 181
                 $output .= '<br />';
182 182
                 $output .= '<h4>TOTAL TIME</h4>';
183 183
                 $output .= Benchmark::formatTime('', $total, $formatted);
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
                 $output .= '<span style="color:red">Like...HEEELLLP</span><br />';
193 193
             }
194 194
         }
195
-        if (! empty(Benchmark::$memory_usage)) {
195
+        if ( ! empty(Benchmark::$memory_usage)) {
196 196
             $output .= $formatted
197 197
                 ? '<h5>Memory</h5>'
198 198
                 : "\nMemory";
@@ -248,13 +248,13 @@  discard block
 block discarded – undo
248 248
         $filepath = ! empty($filepath) && is_readable(dirname($filepath))
249 249
             ? $filepath
250 250
             : '';
251
-        if( empty($filepath)) {
252
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
251
+        if (empty($filepath)) {
252
+            $filepath = EVENT_ESPRESSO_UPLOAD_DIR.'logs/benchmarking-'.date('Y-m-d').'.html';
253 253
         }
254 254
         EEH_File::ensure_file_exists_and_is_writable($filepath);
255 255
         file_put_contents(
256 256
             $filepath,
257
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
257
+            "\n".date('Y-m-d H:i:s').Benchmark::generateResults($formatted),
258 258
             $append ? FILE_APPEND | LOCK_EX : LOCK_EX
259 259
         );
260 260
     }
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
         return round(
274 274
             $size / pow(1024, $i = floor(log($size, 1024))),
275 275
             2
276
-        ) . ' ' . $unit[absint($i)];
276
+        ).' '.$unit[absint($i)];
277 277
     }
278 278
 
279 279
 
Please login to merge, or discard this patch.
core/helpers/EEH_Activation.helper.php 2 patches
Indentation   +1581 added lines, -1581 removed lines patch added patch discarded remove patch
@@ -18,233 +18,233 @@  discard block
 block discarded – undo
18 18
 class EEH_Activation implements ResettableInterface
19 19
 {
20 20
 
21
-    /**
22
-     * constant used to indicate a cron task is no longer in use
23
-     */
24
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
25
-
26
-    /**
27
-     * WP_User->ID
28
-     *
29
-     * @var int
30
-     */
31
-    private static $_default_creator_id;
32
-
33
-    /**
34
-     * indicates whether or not we've already verified core's default data during this request,
35
-     * because after migrations are done, any addons activated while in maintenance mode
36
-     * will want to setup their own default data, and they might hook into core's default data
37
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
38
-     * This prevents doing that for EVERY single addon.
39
-     *
40
-     * @var boolean
41
-     */
42
-    protected static $_initialized_db_content_already_in_this_request = false;
43
-
44
-    /**
45
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
46
-     */
47
-    private static $table_analysis;
48
-
49
-    /**
50
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
51
-     */
52
-    private static $table_manager;
53
-
54
-
55
-    /**
56
-     * @return \EventEspresso\core\services\database\TableAnalysis
57
-     */
58
-    public static function getTableAnalysis()
59
-    {
60
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62
-        }
63
-        return self::$table_analysis;
64
-    }
65
-
66
-
67
-    /**
68
-     * @return \EventEspresso\core\services\database\TableManager
69
-     */
70
-    public static function getTableManager()
71
-    {
72
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74
-        }
75
-        return self::$table_manager;
76
-    }
77
-
78
-
79
-    /**
80
-     *    _ensure_table_name_has_prefix
81
-     *
82
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
83
-     * @access     public
84
-     * @static
85
-     * @param $table_name
86
-     * @return string
87
-     */
88
-    public static function ensure_table_name_has_prefix($table_name)
89
-    {
90
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
91
-    }
92
-
93
-
94
-    /**
95
-     *    system_initialization
96
-     *    ensures the EE configuration settings are loaded with at least default options set
97
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
98
-     *
99
-     * @access public
100
-     * @static
101
-     * @return void
102
-     */
103
-    public static function system_initialization()
104
-    {
105
-        EEH_Activation::reset_and_update_config();
106
-        //which is fired BEFORE activation of plugin anyways
107
-        EEH_Activation::verify_default_pages_exist();
108
-    }
109
-
110
-
111
-    /**
112
-     * Sets the database schema and creates folders. This should
113
-     * be called on plugin activation and reactivation
114
-     *
115
-     * @return boolean success, whether the database and folders are setup properly
116
-     * @throws \EE_Error
117
-     */
118
-    public static function initialize_db_and_folders()
119
-    {
120
-        return EEH_Activation::create_database_tables();
121
-    }
122
-
123
-
124
-    /**
125
-     * assuming we have an up-to-date database schema, this will populate it
126
-     * with default and initial data. This should be called
127
-     * upon activation of a new plugin, reactivation, and at the end
128
-     * of running migration scripts
129
-     *
130
-     * @throws \EE_Error
131
-     */
132
-    public static function initialize_db_content()
133
-    {
134
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
135
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
136
-            return;
137
-        }
138
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
139
-
140
-        EEH_Activation::initialize_system_questions();
141
-        EEH_Activation::insert_default_status_codes();
142
-        EEH_Activation::generate_default_message_templates();
143
-        EEH_Activation::create_no_ticket_prices_array();
144
-
145
-        EEH_Activation::validate_messages_system();
146
-        EEH_Activation::insert_default_payment_methods();
147
-        //in case we've
148
-        EEH_Activation::remove_cron_tasks();
149
-        EEH_Activation::create_cron_tasks();
150
-        // remove all TXN locks since that is being done via extra meta now
151
-        delete_option('ee_locked_transactions');
152
-        //also, check for CAF default db content
153
-        do_action('AHEE__EEH_Activation__initialize_db_content');
154
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
155
-        //which users really won't care about on initial activation
156
-        EE_Error::overwrite_success();
157
-    }
158
-
159
-
160
-    /**
161
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
162
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
163
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
164
-     * (null)
165
-     *
166
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
167
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
168
-     * @return array
169
-     * @throws \EE_Error
170
-     */
171
-    public static function get_cron_tasks($which_to_include)
172
-    {
173
-        $cron_tasks = apply_filters(
174
-            'FHEE__EEH_Activation__get_cron_tasks',
175
-            array(
176
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
21
+	/**
22
+	 * constant used to indicate a cron task is no longer in use
23
+	 */
24
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
25
+
26
+	/**
27
+	 * WP_User->ID
28
+	 *
29
+	 * @var int
30
+	 */
31
+	private static $_default_creator_id;
32
+
33
+	/**
34
+	 * indicates whether or not we've already verified core's default data during this request,
35
+	 * because after migrations are done, any addons activated while in maintenance mode
36
+	 * will want to setup their own default data, and they might hook into core's default data
37
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
38
+	 * This prevents doing that for EVERY single addon.
39
+	 *
40
+	 * @var boolean
41
+	 */
42
+	protected static $_initialized_db_content_already_in_this_request = false;
43
+
44
+	/**
45
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
46
+	 */
47
+	private static $table_analysis;
48
+
49
+	/**
50
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
51
+	 */
52
+	private static $table_manager;
53
+
54
+
55
+	/**
56
+	 * @return \EventEspresso\core\services\database\TableAnalysis
57
+	 */
58
+	public static function getTableAnalysis()
59
+	{
60
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62
+		}
63
+		return self::$table_analysis;
64
+	}
65
+
66
+
67
+	/**
68
+	 * @return \EventEspresso\core\services\database\TableManager
69
+	 */
70
+	public static function getTableManager()
71
+	{
72
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74
+		}
75
+		return self::$table_manager;
76
+	}
77
+
78
+
79
+	/**
80
+	 *    _ensure_table_name_has_prefix
81
+	 *
82
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
83
+	 * @access     public
84
+	 * @static
85
+	 * @param $table_name
86
+	 * @return string
87
+	 */
88
+	public static function ensure_table_name_has_prefix($table_name)
89
+	{
90
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
91
+	}
92
+
93
+
94
+	/**
95
+	 *    system_initialization
96
+	 *    ensures the EE configuration settings are loaded with at least default options set
97
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
98
+	 *
99
+	 * @access public
100
+	 * @static
101
+	 * @return void
102
+	 */
103
+	public static function system_initialization()
104
+	{
105
+		EEH_Activation::reset_and_update_config();
106
+		//which is fired BEFORE activation of plugin anyways
107
+		EEH_Activation::verify_default_pages_exist();
108
+	}
109
+
110
+
111
+	/**
112
+	 * Sets the database schema and creates folders. This should
113
+	 * be called on plugin activation and reactivation
114
+	 *
115
+	 * @return boolean success, whether the database and folders are setup properly
116
+	 * @throws \EE_Error
117
+	 */
118
+	public static function initialize_db_and_folders()
119
+	{
120
+		return EEH_Activation::create_database_tables();
121
+	}
122
+
123
+
124
+	/**
125
+	 * assuming we have an up-to-date database schema, this will populate it
126
+	 * with default and initial data. This should be called
127
+	 * upon activation of a new plugin, reactivation, and at the end
128
+	 * of running migration scripts
129
+	 *
130
+	 * @throws \EE_Error
131
+	 */
132
+	public static function initialize_db_content()
133
+	{
134
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
135
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
136
+			return;
137
+		}
138
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
139
+
140
+		EEH_Activation::initialize_system_questions();
141
+		EEH_Activation::insert_default_status_codes();
142
+		EEH_Activation::generate_default_message_templates();
143
+		EEH_Activation::create_no_ticket_prices_array();
144
+
145
+		EEH_Activation::validate_messages_system();
146
+		EEH_Activation::insert_default_payment_methods();
147
+		//in case we've
148
+		EEH_Activation::remove_cron_tasks();
149
+		EEH_Activation::create_cron_tasks();
150
+		// remove all TXN locks since that is being done via extra meta now
151
+		delete_option('ee_locked_transactions');
152
+		//also, check for CAF default db content
153
+		do_action('AHEE__EEH_Activation__initialize_db_content');
154
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
155
+		//which users really won't care about on initial activation
156
+		EE_Error::overwrite_success();
157
+	}
158
+
159
+
160
+	/**
161
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
162
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
163
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
164
+	 * (null)
165
+	 *
166
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
167
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
168
+	 * @return array
169
+	 * @throws \EE_Error
170
+	 */
171
+	public static function get_cron_tasks($which_to_include)
172
+	{
173
+		$cron_tasks = apply_filters(
174
+			'FHEE__EEH_Activation__get_cron_tasks',
175
+			array(
176
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
177 177
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
178
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
179
-                //there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
180
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
181
-            )
182
-        );
183
-        if ($which_to_include === 'old') {
184
-            $cron_tasks = array_filter(
185
-                $cron_tasks,
186
-                function ($value) {
187
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
188
-                }
189
-            );
190
-        } elseif ($which_to_include === 'current') {
191
-            $cron_tasks = array_filter($cron_tasks);
192
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
193
-            throw new EE_Error(
194
-                sprintf(
195
-                    __(
196
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
197
-                        'event_espresso'
198
-                    ),
199
-                    $which_to_include
200
-                )
201
-            );
202
-        }
203
-        return $cron_tasks;
204
-    }
205
-
206
-
207
-    /**
208
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
209
-     *
210
-     * @throws \EE_Error
211
-     */
212
-    public static function create_cron_tasks()
213
-    {
214
-
215
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
-            if (! wp_next_scheduled($hook_name)) {
217
-                /**
218
-                 * This allows client code to define the initial start timestamp for this schedule.
219
-                 */
220
-                if (is_array($frequency)
221
-                    && count($frequency) === 2
222
-                    && isset($frequency[0], $frequency[1])
223
-                ) {
224
-                    $start_timestamp = $frequency[0];
225
-                    $frequency = $frequency[1];
226
-                } else {
227
-                    $start_timestamp = time();
228
-                }
229
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
230
-            }
231
-        }
232
-
233
-    }
234
-
235
-
236
-    /**
237
-     * Remove the currently-existing and now-removed cron tasks.
238
-     *
239
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
240
-     * @throws \EE_Error
241
-     */
242
-    public static function remove_cron_tasks($remove_all = true)
243
-    {
244
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
245
-        $crons                = _get_cron_array();
246
-        $crons                = is_array($crons) ? $crons : array();
247
-        /* reminder of what $crons look like:
178
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
179
+				//there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
180
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
181
+			)
182
+		);
183
+		if ($which_to_include === 'old') {
184
+			$cron_tasks = array_filter(
185
+				$cron_tasks,
186
+				function ($value) {
187
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
188
+				}
189
+			);
190
+		} elseif ($which_to_include === 'current') {
191
+			$cron_tasks = array_filter($cron_tasks);
192
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
193
+			throw new EE_Error(
194
+				sprintf(
195
+					__(
196
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
197
+						'event_espresso'
198
+					),
199
+					$which_to_include
200
+				)
201
+			);
202
+		}
203
+		return $cron_tasks;
204
+	}
205
+
206
+
207
+	/**
208
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
209
+	 *
210
+	 * @throws \EE_Error
211
+	 */
212
+	public static function create_cron_tasks()
213
+	{
214
+
215
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
+			if (! wp_next_scheduled($hook_name)) {
217
+				/**
218
+				 * This allows client code to define the initial start timestamp for this schedule.
219
+				 */
220
+				if (is_array($frequency)
221
+					&& count($frequency) === 2
222
+					&& isset($frequency[0], $frequency[1])
223
+				) {
224
+					$start_timestamp = $frequency[0];
225
+					$frequency = $frequency[1];
226
+				} else {
227
+					$start_timestamp = time();
228
+				}
229
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
230
+			}
231
+		}
232
+
233
+	}
234
+
235
+
236
+	/**
237
+	 * Remove the currently-existing and now-removed cron tasks.
238
+	 *
239
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
240
+	 * @throws \EE_Error
241
+	 */
242
+	public static function remove_cron_tasks($remove_all = true)
243
+	{
244
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
245
+		$crons                = _get_cron_array();
246
+		$crons                = is_array($crons) ? $crons : array();
247
+		/* reminder of what $crons look like:
248 248
          * Top-level keys are timestamps, and their values are arrays.
249 249
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
250 250
          * and their values are arrays.
@@ -261,911 +261,911 @@  discard block
 block discarded – undo
261 261
          *					...
262 262
          *      ...
263 263
          */
264
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
265
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
266
-            if (is_array($hooks_to_fire_at_time)) {
267
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
268
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
269
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
270
-                    ) {
271
-                        unset($crons[$timestamp][$hook_name]);
272
-                    }
273
-                }
274
-                //also take care of any empty cron timestamps.
275
-                if (empty($hooks_to_fire_at_time)) {
276
-                    unset($crons[$timestamp]);
277
-                }
278
-            }
279
-        }
280
-        _set_cron_array($crons);
281
-    }
282
-
283
-
284
-    /**
285
-     *    CPT_initialization
286
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
287
-     *
288
-     * @access public
289
-     * @static
290
-     * @return void
291
-     */
292
-    public static function CPT_initialization()
293
-    {
294
-        // register Custom Post Types
295
-        EE_Registry::instance()->load_core('Register_CPTs');
296
-        flush_rewrite_rules();
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     *    reset_and_update_config
303
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
304
-     * If there is old calendar config data saved, then it will get converted on activation.
305
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
306
-     *
307
-     * @access public
308
-     * @static
309
-     * @return void
310
-     */
311
-    public static function reset_and_update_config()
312
-    {
313
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
314
-        add_filter(
315
-            'FHEE__EE_Config___load_core_config__config_settings',
316
-            array('EEH_Activation', 'migrate_old_config_data'),
317
-            10,
318
-            3
319
-        );
320
-        //EE_Config::reset();
321
-        if (! EE_Config::logging_enabled()) {
322
-            delete_option(EE_Config::LOG_NAME);
323
-        }
324
-    }
325
-
326
-
327
-    /**
328
-     *    load_calendar_config
329
-     *
330
-     * @access    public
331
-     * @return    void
332
-     */
333
-    public static function load_calendar_config()
334
-    {
335
-        // grab array of all plugin folders and loop thru it
336
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
337
-        if (empty($plugins)) {
338
-            return;
339
-        }
340
-        foreach ($plugins as $plugin_path) {
341
-            // grab plugin folder name from path
342
-            $plugin = basename($plugin_path);
343
-            // drill down to Espresso plugins
344
-            // then to calendar related plugins
345
-            if (
346
-                strpos($plugin, 'espresso') !== false
347
-                || strpos($plugin, 'Espresso') !== false
348
-                || strpos($plugin, 'ee4') !== false
349
-                || strpos($plugin, 'EE4') !== false
350
-                || strpos($plugin, 'calendar') !== false
351
-            ) {
352
-                // this is what we are looking for
353
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
354
-                // does it exist in this folder ?
355
-                if (is_readable($calendar_config)) {
356
-                    // YEAH! let's load it
357
-                    require_once($calendar_config);
358
-                }
359
-            }
360
-        }
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     *    _migrate_old_config_data
367
-     *
368
-     * @access    public
369
-     * @param array|stdClass $settings
370
-     * @param string         $config
371
-     * @param \EE_Config     $EE_Config
372
-     * @return \stdClass
373
-     */
374
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
375
-    {
376
-        $convert_from_array = array('addons');
377
-        // in case old settings were saved as an array
378
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
379
-            // convert existing settings to an object
380
-            $config_array = $settings;
381
-            $settings = new stdClass();
382
-            foreach ($config_array as $key => $value) {
383
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
384
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
385
-                } else {
386
-                    $settings->{$key} = $value;
387
-                }
388
-            }
389
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
390
-        }
391
-        return $settings;
392
-    }
393
-
394
-
395
-    /**
396
-     * deactivate_event_espresso
397
-     *
398
-     * @access public
399
-     * @static
400
-     * @return void
401
-     */
402
-    public static function deactivate_event_espresso()
403
-    {
404
-        // check permissions
405
-        if (current_user_can('activate_plugins')) {
406
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
407
-        }
408
-    }
409
-
410
-
411
-
412
-    /**
413
-     * verify_default_pages_exist
414
-     *
415
-     * @access public
416
-     * @static
417
-     * @return void
418
-     * @throws InvalidDataTypeException
419
-     */
420
-    public static function verify_default_pages_exist()
421
-    {
422
-        $critical_page_problem = false;
423
-        $critical_pages = array(
424
-            array(
425
-                'id'   => 'reg_page_id',
426
-                'name' => __('Registration Checkout', 'event_espresso'),
427
-                'post' => null,
428
-                'code' => 'ESPRESSO_CHECKOUT',
429
-            ),
430
-            array(
431
-                'id'   => 'txn_page_id',
432
-                'name' => __('Transactions', 'event_espresso'),
433
-                'post' => null,
434
-                'code' => 'ESPRESSO_TXN_PAGE',
435
-            ),
436
-            array(
437
-                'id'   => 'thank_you_page_id',
438
-                'name' => __('Thank You', 'event_espresso'),
439
-                'post' => null,
440
-                'code' => 'ESPRESSO_THANK_YOU',
441
-            ),
442
-            array(
443
-                'id'   => 'cancel_page_id',
444
-                'name' => __('Registration Cancelled', 'event_espresso'),
445
-                'post' => null,
446
-                'code' => 'ESPRESSO_CANCELLED',
447
-            ),
448
-        );
449
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
450
-        foreach ($critical_pages as $critical_page) {
451
-            // is critical page ID set in config ?
452
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
453
-                // attempt to find post by ID
454
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
455
-            }
456
-            // no dice?
457
-            if ($critical_page['post'] === null) {
458
-                // attempt to find post by title
459
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
460
-                // still nothing?
461
-                if ($critical_page['post'] === null) {
462
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
463
-                    // REALLY? Still nothing ??!?!?
464
-                    if ($critical_page['post'] === null) {
465
-                        $msg = __(
466
-                            'The Event Espresso critical page configuration settings could not be updated.',
467
-                            'event_espresso'
468
-                        );
469
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
470
-                        break;
471
-                    }
472
-                }
473
-            }
474
-            // check that Post ID matches critical page ID in config
475
-            if (
476
-                isset($critical_page['post']->ID)
477
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
478
-            ) {
479
-                //update Config with post ID
480
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
482
-                    $msg = __(
483
-                        'The Event Espresso critical page configuration settings could not be updated.',
484
-                        'event_espresso'
485
-                    );
486
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
487
-                }
488
-            }
489
-            $critical_page_problem =
490
-                ! isset($critical_page['post']->post_status)
491
-                || $critical_page['post']->post_status !== 'publish'
492
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
493
-                    ? true
494
-                    : $critical_page_problem;
495
-        }
496
-        if ($critical_page_problem) {
497
-            new PersistentAdminNotice(
498
-                'critical_page_problem',
499
-                sprintf(
500
-                    esc_html__(
501
-                        'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502
-                        'event_espresso'
503
-                    ),
504
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
505
-                    . __('Event Espresso Critical Pages Settings', 'event_espresso')
506
-                    . '</a>'
507
-                )
508
-            );
509
-        }
510
-        if (EE_Error::has_notices()) {
511
-            EE_Error::get_notices(false, true, true);
512
-        }
513
-    }
514
-
515
-
516
-
517
-    /**
518
-     * Returns the first post which uses the specified shortcode
519
-     *
520
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
521
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
522
-     *                             "[ESPRESSO_THANK_YOU"
523
-     *                             (we don't search for the closing shortcode bracket because they might have added
524
-     *                             parameter to the shortcode
525
-     * @return WP_Post or NULl
526
-     */
527
-    public static function get_page_by_ee_shortcode($ee_shortcode)
528
-    {
529
-        global $wpdb;
530
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
531
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532
-        if ($post_id) {
533
-            return get_post($post_id);
534
-        } else {
535
-            return null;
536
-        }
537
-    }
538
-
539
-
540
-    /**
541
-     *    This function generates a post for critical espresso pages
542
-     *
543
-     * @access public
544
-     * @static
545
-     * @param array $critical_page
546
-     * @return array
547
-     */
548
-    public static function create_critical_page($critical_page)
549
-    {
550
-
551
-        $post_args = array(
552
-            'post_title'     => $critical_page['name'],
553
-            'post_status'    => 'publish',
554
-            'post_type'      => 'page',
555
-            'comment_status' => 'closed',
556
-            'post_content'   => '[' . $critical_page['code'] . ']',
557
-        );
558
-
559
-        $post_id = wp_insert_post($post_args);
560
-        if (! $post_id) {
561
-            $msg = sprintf(
562
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563
-                $critical_page['name']
564
-            );
565
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
566
-            return $critical_page;
567
-        }
568
-        // get newly created post's details
569
-        if (! $critical_page['post'] = get_post($post_id)) {
570
-            $msg = sprintf(
571
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572
-                $critical_page['name']
573
-            );
574
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
575
-        }
576
-
577
-        return $critical_page;
578
-
579
-    }
580
-
581
-
582
-
583
-
584
-    /**
585
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
586
-     * The role being used to check is filterable.
587
-     *
588
-     * @since  4.6.0
589
-     * @global WPDB $wpdb
590
-     * @return mixed null|int WP_user ID or NULL
591
-     */
592
-    public static function get_default_creator_id()
593
-    {
594
-        global $wpdb;
595
-        if ( ! empty(self::$_default_creator_id)) {
596
-            return self::$_default_creator_id;
597
-        }/**/
598
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
599
-        //let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
600
-        $pre_filtered_id = apply_filters(
601
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
602
-            false,
603
-            $role_to_check
604
-        );
605
-        if ($pre_filtered_id !== false) {
606
-            return (int)$pre_filtered_id;
607
-        }
608
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609
-        $query = $wpdb->prepare(
610
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
-            '%' . $role_to_check . '%'
612
-        );
613
-        $user_id = $wpdb->get_var($query);
614
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
-        if ($user_id && (int)$user_id) {
616
-            self::$_default_creator_id = (int)$user_id;
617
-            return self::$_default_creator_id;
618
-        } else {
619
-            return null;
620
-        }
621
-    }
622
-
623
-
624
-
625
-    /**
626
-     * used by EE and EE addons during plugin activation to create tables.
627
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
628
-     * but includes extra logic regarding activations.
629
-     *
630
-     * @access public
631
-     * @static
632
-     * @param string  $table_name              without the $wpdb->prefix
633
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
634
-     *                                         table query)
635
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
636
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
637
-     *                                         and new once this function is done (ie, you really do want to CREATE a
638
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
639
-     *                                         you just want to verify the table exists and matches this definition
640
-     *                                         (and if it HAS data in it you want to leave it be)
641
-     * @return void
642
-     * @throws EE_Error if there are database errors
643
-     */
644
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
645
-    {
646
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
647
-            return;
648
-        }
649
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650
-        if ( ! function_exists('dbDelta')) {
651
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
652
-        }
653
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
654
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
655
-        // do we need to first delete an existing version of this table ?
656
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
657
-            // ok, delete the table... but ONLY if it's empty
658
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
659
-            // table is NOT empty, are you SURE you want to delete this table ???
660
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
661
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
662
-            } else if ( ! $deleted_safely) {
663
-                // so we should be more cautious rather than just dropping tables so easily
664
-                error_log(
665
-                    sprintf(
666
-                        __(
667
-                            'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
668
-                            'event_espresso'
669
-                        ),
670
-                        $wp_table_name,
671
-                        '<br/>',
672
-                        'espresso_db_update'
673
-                    )
674
-                );
675
-            }
676
-        }
677
-        $engine = str_replace('ENGINE=', '', $engine);
678
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     *    add_column_if_it_doesn't_exist
685
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
686
-     *
687
-     * @access     public
688
-     * @static
689
-     * @deprecated instead use TableManager::addColumn()
690
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
691
-     * @param string $column_name
692
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
693
-     *                            'VARCHAR(10)'
694
-     * @return bool|int
695
-     */
696
-    public static function add_column_if_it_doesnt_exist(
697
-        $table_name,
698
-        $column_name,
699
-        $column_info = 'INT UNSIGNED NOT NULL'
700
-    ) {
701
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
702
-    }
703
-
704
-
705
-    /**
706
-     * get_fields_on_table
707
-     * Gets all the fields on the database table.
708
-     *
709
-     * @access     public
710
-     * @deprecated instead use TableManager::getTableColumns()
711
-     * @static
712
-     * @param string $table_name , without prefixed $wpdb->prefix
713
-     * @return array of database column names
714
-     */
715
-    public static function get_fields_on_table($table_name = null)
716
-    {
717
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
718
-    }
719
-
720
-
721
-    /**
722
-     * db_table_is_empty
723
-     *
724
-     * @access     public\
725
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
726
-     * @static
727
-     * @param string $table_name
728
-     * @return bool
729
-     */
730
-    public static function db_table_is_empty($table_name)
731
-    {
732
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
733
-    }
734
-
735
-
736
-    /**
737
-     * delete_db_table_if_empty
738
-     *
739
-     * @access public
740
-     * @static
741
-     * @param string $table_name
742
-     * @return bool | int
743
-     */
744
-    public static function delete_db_table_if_empty($table_name)
745
-    {
746
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
747
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
748
-        }
749
-        return false;
750
-    }
751
-
752
-
753
-    /**
754
-     * delete_unused_db_table
755
-     *
756
-     * @access     public
757
-     * @static
758
-     * @deprecated instead use TableManager::dropTable()
759
-     * @param string $table_name
760
-     * @return bool | int
761
-     */
762
-    public static function delete_unused_db_table($table_name)
763
-    {
764
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
765
-    }
766
-
767
-
768
-    /**
769
-     * drop_index
770
-     *
771
-     * @access     public
772
-     * @static
773
-     * @deprecated instead use TableManager::dropIndex()
774
-     * @param string $table_name
775
-     * @param string $index_name
776
-     * @return bool | int
777
-     */
778
-    public static function drop_index($table_name, $index_name)
779
-    {
780
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
781
-    }
782
-
783
-
784
-
785
-    /**
786
-     * create_database_tables
787
-     *
788
-     * @access public
789
-     * @static
790
-     * @throws EE_Error
791
-     * @return boolean success (whether database is setup properly or not)
792
-     */
793
-    public static function create_database_tables()
794
-    {
795
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
796
-        //find the migration script that sets the database to be compatible with the code
797
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
798
-        if ($dms_name) {
799
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
800
-            $current_data_migration_script->set_migrating(false);
801
-            $current_data_migration_script->schema_changes_before_migration();
802
-            $current_data_migration_script->schema_changes_after_migration();
803
-            if ($current_data_migration_script->get_errors()) {
804
-                if (WP_DEBUG) {
805
-                    foreach ($current_data_migration_script->get_errors() as $error) {
806
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
807
-                    }
808
-                } else {
809
-                    EE_Error::add_error(
810
-                        __(
811
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
264
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
265
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
266
+			if (is_array($hooks_to_fire_at_time)) {
267
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
268
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
269
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
270
+					) {
271
+						unset($crons[$timestamp][$hook_name]);
272
+					}
273
+				}
274
+				//also take care of any empty cron timestamps.
275
+				if (empty($hooks_to_fire_at_time)) {
276
+					unset($crons[$timestamp]);
277
+				}
278
+			}
279
+		}
280
+		_set_cron_array($crons);
281
+	}
282
+
283
+
284
+	/**
285
+	 *    CPT_initialization
286
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
287
+	 *
288
+	 * @access public
289
+	 * @static
290
+	 * @return void
291
+	 */
292
+	public static function CPT_initialization()
293
+	{
294
+		// register Custom Post Types
295
+		EE_Registry::instance()->load_core('Register_CPTs');
296
+		flush_rewrite_rules();
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 *    reset_and_update_config
303
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
304
+	 * If there is old calendar config data saved, then it will get converted on activation.
305
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
306
+	 *
307
+	 * @access public
308
+	 * @static
309
+	 * @return void
310
+	 */
311
+	public static function reset_and_update_config()
312
+	{
313
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
314
+		add_filter(
315
+			'FHEE__EE_Config___load_core_config__config_settings',
316
+			array('EEH_Activation', 'migrate_old_config_data'),
317
+			10,
318
+			3
319
+		);
320
+		//EE_Config::reset();
321
+		if (! EE_Config::logging_enabled()) {
322
+			delete_option(EE_Config::LOG_NAME);
323
+		}
324
+	}
325
+
326
+
327
+	/**
328
+	 *    load_calendar_config
329
+	 *
330
+	 * @access    public
331
+	 * @return    void
332
+	 */
333
+	public static function load_calendar_config()
334
+	{
335
+		// grab array of all plugin folders and loop thru it
336
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
337
+		if (empty($plugins)) {
338
+			return;
339
+		}
340
+		foreach ($plugins as $plugin_path) {
341
+			// grab plugin folder name from path
342
+			$plugin = basename($plugin_path);
343
+			// drill down to Espresso plugins
344
+			// then to calendar related plugins
345
+			if (
346
+				strpos($plugin, 'espresso') !== false
347
+				|| strpos($plugin, 'Espresso') !== false
348
+				|| strpos($plugin, 'ee4') !== false
349
+				|| strpos($plugin, 'EE4') !== false
350
+				|| strpos($plugin, 'calendar') !== false
351
+			) {
352
+				// this is what we are looking for
353
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
354
+				// does it exist in this folder ?
355
+				if (is_readable($calendar_config)) {
356
+					// YEAH! let's load it
357
+					require_once($calendar_config);
358
+				}
359
+			}
360
+		}
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 *    _migrate_old_config_data
367
+	 *
368
+	 * @access    public
369
+	 * @param array|stdClass $settings
370
+	 * @param string         $config
371
+	 * @param \EE_Config     $EE_Config
372
+	 * @return \stdClass
373
+	 */
374
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
375
+	{
376
+		$convert_from_array = array('addons');
377
+		// in case old settings were saved as an array
378
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
379
+			// convert existing settings to an object
380
+			$config_array = $settings;
381
+			$settings = new stdClass();
382
+			foreach ($config_array as $key => $value) {
383
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
384
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
385
+				} else {
386
+					$settings->{$key} = $value;
387
+				}
388
+			}
389
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
390
+		}
391
+		return $settings;
392
+	}
393
+
394
+
395
+	/**
396
+	 * deactivate_event_espresso
397
+	 *
398
+	 * @access public
399
+	 * @static
400
+	 * @return void
401
+	 */
402
+	public static function deactivate_event_espresso()
403
+	{
404
+		// check permissions
405
+		if (current_user_can('activate_plugins')) {
406
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
407
+		}
408
+	}
409
+
410
+
411
+
412
+	/**
413
+	 * verify_default_pages_exist
414
+	 *
415
+	 * @access public
416
+	 * @static
417
+	 * @return void
418
+	 * @throws InvalidDataTypeException
419
+	 */
420
+	public static function verify_default_pages_exist()
421
+	{
422
+		$critical_page_problem = false;
423
+		$critical_pages = array(
424
+			array(
425
+				'id'   => 'reg_page_id',
426
+				'name' => __('Registration Checkout', 'event_espresso'),
427
+				'post' => null,
428
+				'code' => 'ESPRESSO_CHECKOUT',
429
+			),
430
+			array(
431
+				'id'   => 'txn_page_id',
432
+				'name' => __('Transactions', 'event_espresso'),
433
+				'post' => null,
434
+				'code' => 'ESPRESSO_TXN_PAGE',
435
+			),
436
+			array(
437
+				'id'   => 'thank_you_page_id',
438
+				'name' => __('Thank You', 'event_espresso'),
439
+				'post' => null,
440
+				'code' => 'ESPRESSO_THANK_YOU',
441
+			),
442
+			array(
443
+				'id'   => 'cancel_page_id',
444
+				'name' => __('Registration Cancelled', 'event_espresso'),
445
+				'post' => null,
446
+				'code' => 'ESPRESSO_CANCELLED',
447
+			),
448
+		);
449
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
450
+		foreach ($critical_pages as $critical_page) {
451
+			// is critical page ID set in config ?
452
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
453
+				// attempt to find post by ID
454
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
455
+			}
456
+			// no dice?
457
+			if ($critical_page['post'] === null) {
458
+				// attempt to find post by title
459
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
460
+				// still nothing?
461
+				if ($critical_page['post'] === null) {
462
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
463
+					// REALLY? Still nothing ??!?!?
464
+					if ($critical_page['post'] === null) {
465
+						$msg = __(
466
+							'The Event Espresso critical page configuration settings could not be updated.',
467
+							'event_espresso'
468
+						);
469
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
470
+						break;
471
+					}
472
+				}
473
+			}
474
+			// check that Post ID matches critical page ID in config
475
+			if (
476
+				isset($critical_page['post']->ID)
477
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
478
+			) {
479
+				//update Config with post ID
480
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
482
+					$msg = __(
483
+						'The Event Espresso critical page configuration settings could not be updated.',
484
+						'event_espresso'
485
+					);
486
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
487
+				}
488
+			}
489
+			$critical_page_problem =
490
+				! isset($critical_page['post']->post_status)
491
+				|| $critical_page['post']->post_status !== 'publish'
492
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
493
+					? true
494
+					: $critical_page_problem;
495
+		}
496
+		if ($critical_page_problem) {
497
+			new PersistentAdminNotice(
498
+				'critical_page_problem',
499
+				sprintf(
500
+					esc_html__(
501
+						'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502
+						'event_espresso'
503
+					),
504
+					'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
505
+					. __('Event Espresso Critical Pages Settings', 'event_espresso')
506
+					. '</a>'
507
+				)
508
+			);
509
+		}
510
+		if (EE_Error::has_notices()) {
511
+			EE_Error::get_notices(false, true, true);
512
+		}
513
+	}
514
+
515
+
516
+
517
+	/**
518
+	 * Returns the first post which uses the specified shortcode
519
+	 *
520
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
521
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
522
+	 *                             "[ESPRESSO_THANK_YOU"
523
+	 *                             (we don't search for the closing shortcode bracket because they might have added
524
+	 *                             parameter to the shortcode
525
+	 * @return WP_Post or NULl
526
+	 */
527
+	public static function get_page_by_ee_shortcode($ee_shortcode)
528
+	{
529
+		global $wpdb;
530
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
531
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532
+		if ($post_id) {
533
+			return get_post($post_id);
534
+		} else {
535
+			return null;
536
+		}
537
+	}
538
+
539
+
540
+	/**
541
+	 *    This function generates a post for critical espresso pages
542
+	 *
543
+	 * @access public
544
+	 * @static
545
+	 * @param array $critical_page
546
+	 * @return array
547
+	 */
548
+	public static function create_critical_page($critical_page)
549
+	{
550
+
551
+		$post_args = array(
552
+			'post_title'     => $critical_page['name'],
553
+			'post_status'    => 'publish',
554
+			'post_type'      => 'page',
555
+			'comment_status' => 'closed',
556
+			'post_content'   => '[' . $critical_page['code'] . ']',
557
+		);
558
+
559
+		$post_id = wp_insert_post($post_args);
560
+		if (! $post_id) {
561
+			$msg = sprintf(
562
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563
+				$critical_page['name']
564
+			);
565
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
566
+			return $critical_page;
567
+		}
568
+		// get newly created post's details
569
+		if (! $critical_page['post'] = get_post($post_id)) {
570
+			$msg = sprintf(
571
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572
+				$critical_page['name']
573
+			);
574
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
575
+		}
576
+
577
+		return $critical_page;
578
+
579
+	}
580
+
581
+
582
+
583
+
584
+	/**
585
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
586
+	 * The role being used to check is filterable.
587
+	 *
588
+	 * @since  4.6.0
589
+	 * @global WPDB $wpdb
590
+	 * @return mixed null|int WP_user ID or NULL
591
+	 */
592
+	public static function get_default_creator_id()
593
+	{
594
+		global $wpdb;
595
+		if ( ! empty(self::$_default_creator_id)) {
596
+			return self::$_default_creator_id;
597
+		}/**/
598
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
599
+		//let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
600
+		$pre_filtered_id = apply_filters(
601
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
602
+			false,
603
+			$role_to_check
604
+		);
605
+		if ($pre_filtered_id !== false) {
606
+			return (int)$pre_filtered_id;
607
+		}
608
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609
+		$query = $wpdb->prepare(
610
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
+			'%' . $role_to_check . '%'
612
+		);
613
+		$user_id = $wpdb->get_var($query);
614
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
+		if ($user_id && (int)$user_id) {
616
+			self::$_default_creator_id = (int)$user_id;
617
+			return self::$_default_creator_id;
618
+		} else {
619
+			return null;
620
+		}
621
+	}
622
+
623
+
624
+
625
+	/**
626
+	 * used by EE and EE addons during plugin activation to create tables.
627
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
628
+	 * but includes extra logic regarding activations.
629
+	 *
630
+	 * @access public
631
+	 * @static
632
+	 * @param string  $table_name              without the $wpdb->prefix
633
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
634
+	 *                                         table query)
635
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
636
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
637
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
638
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
639
+	 *                                         you just want to verify the table exists and matches this definition
640
+	 *                                         (and if it HAS data in it you want to leave it be)
641
+	 * @return void
642
+	 * @throws EE_Error if there are database errors
643
+	 */
644
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
645
+	{
646
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
647
+			return;
648
+		}
649
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650
+		if ( ! function_exists('dbDelta')) {
651
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
652
+		}
653
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
654
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
655
+		// do we need to first delete an existing version of this table ?
656
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
657
+			// ok, delete the table... but ONLY if it's empty
658
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
659
+			// table is NOT empty, are you SURE you want to delete this table ???
660
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
661
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
662
+			} else if ( ! $deleted_safely) {
663
+				// so we should be more cautious rather than just dropping tables so easily
664
+				error_log(
665
+					sprintf(
666
+						__(
667
+							'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
668
+							'event_espresso'
669
+						),
670
+						$wp_table_name,
671
+						'<br/>',
672
+						'espresso_db_update'
673
+					)
674
+				);
675
+			}
676
+		}
677
+		$engine = str_replace('ENGINE=', '', $engine);
678
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 *    add_column_if_it_doesn't_exist
685
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
686
+	 *
687
+	 * @access     public
688
+	 * @static
689
+	 * @deprecated instead use TableManager::addColumn()
690
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
691
+	 * @param string $column_name
692
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
693
+	 *                            'VARCHAR(10)'
694
+	 * @return bool|int
695
+	 */
696
+	public static function add_column_if_it_doesnt_exist(
697
+		$table_name,
698
+		$column_name,
699
+		$column_info = 'INT UNSIGNED NOT NULL'
700
+	) {
701
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
702
+	}
703
+
704
+
705
+	/**
706
+	 * get_fields_on_table
707
+	 * Gets all the fields on the database table.
708
+	 *
709
+	 * @access     public
710
+	 * @deprecated instead use TableManager::getTableColumns()
711
+	 * @static
712
+	 * @param string $table_name , without prefixed $wpdb->prefix
713
+	 * @return array of database column names
714
+	 */
715
+	public static function get_fields_on_table($table_name = null)
716
+	{
717
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
718
+	}
719
+
720
+
721
+	/**
722
+	 * db_table_is_empty
723
+	 *
724
+	 * @access     public\
725
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
726
+	 * @static
727
+	 * @param string $table_name
728
+	 * @return bool
729
+	 */
730
+	public static function db_table_is_empty($table_name)
731
+	{
732
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
733
+	}
734
+
735
+
736
+	/**
737
+	 * delete_db_table_if_empty
738
+	 *
739
+	 * @access public
740
+	 * @static
741
+	 * @param string $table_name
742
+	 * @return bool | int
743
+	 */
744
+	public static function delete_db_table_if_empty($table_name)
745
+	{
746
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
747
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
748
+		}
749
+		return false;
750
+	}
751
+
752
+
753
+	/**
754
+	 * delete_unused_db_table
755
+	 *
756
+	 * @access     public
757
+	 * @static
758
+	 * @deprecated instead use TableManager::dropTable()
759
+	 * @param string $table_name
760
+	 * @return bool | int
761
+	 */
762
+	public static function delete_unused_db_table($table_name)
763
+	{
764
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
765
+	}
766
+
767
+
768
+	/**
769
+	 * drop_index
770
+	 *
771
+	 * @access     public
772
+	 * @static
773
+	 * @deprecated instead use TableManager::dropIndex()
774
+	 * @param string $table_name
775
+	 * @param string $index_name
776
+	 * @return bool | int
777
+	 */
778
+	public static function drop_index($table_name, $index_name)
779
+	{
780
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
781
+	}
782
+
783
+
784
+
785
+	/**
786
+	 * create_database_tables
787
+	 *
788
+	 * @access public
789
+	 * @static
790
+	 * @throws EE_Error
791
+	 * @return boolean success (whether database is setup properly or not)
792
+	 */
793
+	public static function create_database_tables()
794
+	{
795
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
796
+		//find the migration script that sets the database to be compatible with the code
797
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
798
+		if ($dms_name) {
799
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
800
+			$current_data_migration_script->set_migrating(false);
801
+			$current_data_migration_script->schema_changes_before_migration();
802
+			$current_data_migration_script->schema_changes_after_migration();
803
+			if ($current_data_migration_script->get_errors()) {
804
+				if (WP_DEBUG) {
805
+					foreach ($current_data_migration_script->get_errors() as $error) {
806
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
807
+					}
808
+				} else {
809
+					EE_Error::add_error(
810
+						__(
811
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
812 812
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
813
-                            'event_espresso'
814
-                        )
815
-                    );
816
-                }
817
-                return false;
818
-            }
819
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
820
-        } else {
821
-            EE_Error::add_error(
822
-                __(
823
-                    'Could not determine most up-to-date data migration script from which to pull database schema
813
+							'event_espresso'
814
+						)
815
+					);
816
+				}
817
+				return false;
818
+			}
819
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
820
+		} else {
821
+			EE_Error::add_error(
822
+				__(
823
+					'Could not determine most up-to-date data migration script from which to pull database schema
824 824
                      structure. So database is probably not setup properly',
825
-                    'event_espresso'
826
-                ),
827
-                __FILE__,
828
-                __FUNCTION__,
829
-                __LINE__
830
-            );
831
-            return false;
832
-        }
833
-        return true;
834
-    }
835
-
836
-
837
-
838
-    /**
839
-     * initialize_system_questions
840
-     *
841
-     * @access public
842
-     * @static
843
-     * @return void
844
-     */
845
-    public static function initialize_system_questions()
846
-    {
847
-        // QUESTION GROUPS
848
-        global $wpdb;
849
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
850
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
851
-        // what we have
852
-        $question_groups = $wpdb->get_col($SQL);
853
-        // check the response
854
-        $question_groups = is_array($question_groups) ? $question_groups : array();
855
-        // what we should have
856
-        $QSG_systems = array(1, 2);
857
-        // loop thru what we should have and compare to what we have
858
-        foreach ($QSG_systems as $QSG_system) {
859
-            // reset values array
860
-            $QSG_values = array();
861
-            // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
-            if (! in_array("$QSG_system", $question_groups)) {
863
-                // add it
864
-                switch ($QSG_system) {
865
-                    case 1:
866
-                        $QSG_values = array(
867
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
868
-                            'QSG_identifier'      => 'personal-information-' . time(),
869
-                            'QSG_desc'            => '',
870
-                            'QSG_order'           => 1,
871
-                            'QSG_show_group_name' => 1,
872
-                            'QSG_show_group_desc' => 1,
873
-                            'QSG_system'          => EEM_Question_Group::system_personal,
874
-                            'QSG_deleted'         => 0,
875
-                        );
876
-                        break;
877
-                    case 2:
878
-                        $QSG_values = array(
879
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
880
-                            'QSG_identifier'      => 'address-information-' . time(),
881
-                            'QSG_desc'            => '',
882
-                            'QSG_order'           => 2,
883
-                            'QSG_show_group_name' => 1,
884
-                            'QSG_show_group_desc' => 1,
885
-                            'QSG_system'          => EEM_Question_Group::system_address,
886
-                            'QSG_deleted'         => 0,
887
-                        );
888
-                        break;
889
-                }
890
-                // make sure we have some values before inserting them
891
-                if (! empty($QSG_values)) {
892
-                    // insert system question
893
-                    $wpdb->insert(
894
-                        $table_name,
895
-                        $QSG_values,
896
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
897
-                    );
898
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
899
-                }
900
-            }
901
-        }
902
-        // QUESTIONS
903
-        global $wpdb;
904
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
905
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
906
-        // what we have
907
-        $questions = $wpdb->get_col($SQL);
908
-        // what we should have
909
-        $QST_systems = array(
910
-            'fname',
911
-            'lname',
912
-            'email',
913
-            'address',
914
-            'address2',
915
-            'city',
916
-            'country',
917
-            'state',
918
-            'zip',
919
-            'phone',
920
-        );
921
-        $order_for_group_1 = 1;
922
-        $order_for_group_2 = 1;
923
-        // loop thru what we should have and compare to what we have
924
-        foreach ($QST_systems as $QST_system) {
925
-            // reset values array
926
-            $QST_values = array();
927
-            // if we don't have what we should have
928
-            if (! in_array($QST_system, $questions)) {
929
-                // add it
930
-                switch ($QST_system) {
931
-                    case 'fname':
932
-                        $QST_values = array(
933
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
934
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
935
-                            'QST_system'        => 'fname',
936
-                            'QST_type'          => 'TEXT',
937
-                            'QST_required'      => 1,
938
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
939
-                            'QST_order'         => 1,
940
-                            'QST_admin_only'    => 0,
941
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
942
-                            'QST_wp_user'       => self::get_default_creator_id(),
943
-                            'QST_deleted'       => 0,
944
-                        );
945
-                        break;
946
-                    case 'lname':
947
-                        $QST_values = array(
948
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
949
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
950
-                            'QST_system'        => 'lname',
951
-                            'QST_type'          => 'TEXT',
952
-                            'QST_required'      => 1,
953
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
954
-                            'QST_order'         => 2,
955
-                            'QST_admin_only'    => 0,
956
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
957
-                            'QST_wp_user'       => self::get_default_creator_id(),
958
-                            'QST_deleted'       => 0,
959
-                        );
960
-                        break;
961
-                    case 'email':
962
-                        $QST_values = array(
963
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
964
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
965
-                            'QST_system'        => 'email',
966
-                            'QST_type'          => 'EMAIL',
967
-                            'QST_required'      => 1,
968
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
969
-                            'QST_order'         => 3,
970
-                            'QST_admin_only'    => 0,
971
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
972
-                            'QST_wp_user'       => self::get_default_creator_id(),
973
-                            'QST_deleted'       => 0,
974
-                        );
975
-                        break;
976
-                    case 'address':
977
-                        $QST_values = array(
978
-                            'QST_display_text'  => __('Address', 'event_espresso'),
979
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
980
-                            'QST_system'        => 'address',
981
-                            'QST_type'          => 'TEXT',
982
-                            'QST_required'      => 0,
983
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
984
-                            'QST_order'         => 4,
985
-                            'QST_admin_only'    => 0,
986
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
987
-                            'QST_wp_user'       => self::get_default_creator_id(),
988
-                            'QST_deleted'       => 0,
989
-                        );
990
-                        break;
991
-                    case 'address2':
992
-                        $QST_values = array(
993
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
994
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
995
-                            'QST_system'        => 'address2',
996
-                            'QST_type'          => 'TEXT',
997
-                            'QST_required'      => 0,
998
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
999
-                            'QST_order'         => 5,
1000
-                            'QST_admin_only'    => 0,
1001
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1002
-                            'QST_wp_user'       => self::get_default_creator_id(),
1003
-                            'QST_deleted'       => 0,
1004
-                        );
1005
-                        break;
1006
-                    case 'city':
1007
-                        $QST_values = array(
1008
-                            'QST_display_text'  => __('City', 'event_espresso'),
1009
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1010
-                            'QST_system'        => 'city',
1011
-                            'QST_type'          => 'TEXT',
1012
-                            'QST_required'      => 0,
1013
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1014
-                            'QST_order'         => 6,
1015
-                            'QST_admin_only'    => 0,
1016
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1017
-                            'QST_wp_user'       => self::get_default_creator_id(),
1018
-                            'QST_deleted'       => 0,
1019
-                        );
1020
-                        break;
1021
-                    case 'country':
1022
-                        $QST_values = array(
1023
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1024
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1025
-                            'QST_system'        => 'country',
1026
-                            'QST_type'          => 'COUNTRY',
1027
-                            'QST_required'      => 0,
1028
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1029
-                            'QST_order'         => 7,
1030
-                            'QST_admin_only'    => 0,
1031
-                            'QST_wp_user'       => self::get_default_creator_id(),
1032
-                            'QST_deleted'       => 0,
1033
-                        );
1034
-                        break;
1035
-                    case 'state':
1036
-                        $QST_values = array(
1037
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1038
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1039
-                            'QST_system'        => 'state',
1040
-                            'QST_type'          => 'STATE',
1041
-                            'QST_required'      => 0,
1042
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1043
-                            'QST_order'         => 8,
1044
-                            'QST_admin_only'    => 0,
1045
-                            'QST_wp_user'       => self::get_default_creator_id(),
1046
-                            'QST_deleted'       => 0,
1047
-                        );
1048
-                        break;
1049
-                    case 'zip':
1050
-                        $QST_values = array(
1051
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1052
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1053
-                            'QST_system'        => 'zip',
1054
-                            'QST_type'          => 'TEXT',
1055
-                            'QST_required'      => 0,
1056
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1057
-                            'QST_order'         => 9,
1058
-                            'QST_admin_only'    => 0,
1059
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1060
-                            'QST_wp_user'       => self::get_default_creator_id(),
1061
-                            'QST_deleted'       => 0,
1062
-                        );
1063
-                        break;
1064
-                    case 'phone':
1065
-                        $QST_values = array(
1066
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1067
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1068
-                            'QST_system'        => 'phone',
1069
-                            'QST_type'          => 'TEXT',
1070
-                            'QST_required'      => 0,
1071
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1072
-                            'QST_order'         => 10,
1073
-                            'QST_admin_only'    => 0,
1074
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1075
-                            'QST_wp_user'       => self::get_default_creator_id(),
1076
-                            'QST_deleted'       => 0,
1077
-                        );
1078
-                        break;
1079
-                }
1080
-                if (! empty($QST_values)) {
1081
-                    // insert system question
1082
-                    $wpdb->insert(
1083
-                        $table_name,
1084
-                        $QST_values,
1085
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1086
-                    );
1087
-                    $QST_ID = $wpdb->insert_id;
1088
-                    // QUESTION GROUP QUESTIONS
1089
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1090
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1091
-                    } else {
1092
-                        $system_question_we_want = EEM_Question_Group::system_address;
1093
-                    }
1094
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1095
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1096
-                    } else {
1097
-                        $id_col = EEM_Question_Group::instance()
1098
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1099
-                        if (is_array($id_col)) {
1100
-                            $QSG_ID = reset($id_col);
1101
-                        } else {
1102
-                            //ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1103
-                            EE_Log::instance()->log(
1104
-                                __FILE__,
1105
-                                __FUNCTION__,
1106
-                                sprintf(
1107
-                                    __(
1108
-                                        'Could not associate question %1$s to a question group because no system question
825
+					'event_espresso'
826
+				),
827
+				__FILE__,
828
+				__FUNCTION__,
829
+				__LINE__
830
+			);
831
+			return false;
832
+		}
833
+		return true;
834
+	}
835
+
836
+
837
+
838
+	/**
839
+	 * initialize_system_questions
840
+	 *
841
+	 * @access public
842
+	 * @static
843
+	 * @return void
844
+	 */
845
+	public static function initialize_system_questions()
846
+	{
847
+		// QUESTION GROUPS
848
+		global $wpdb;
849
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
850
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
851
+		// what we have
852
+		$question_groups = $wpdb->get_col($SQL);
853
+		// check the response
854
+		$question_groups = is_array($question_groups) ? $question_groups : array();
855
+		// what we should have
856
+		$QSG_systems = array(1, 2);
857
+		// loop thru what we should have and compare to what we have
858
+		foreach ($QSG_systems as $QSG_system) {
859
+			// reset values array
860
+			$QSG_values = array();
861
+			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
+			if (! in_array("$QSG_system", $question_groups)) {
863
+				// add it
864
+				switch ($QSG_system) {
865
+					case 1:
866
+						$QSG_values = array(
867
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
868
+							'QSG_identifier'      => 'personal-information-' . time(),
869
+							'QSG_desc'            => '',
870
+							'QSG_order'           => 1,
871
+							'QSG_show_group_name' => 1,
872
+							'QSG_show_group_desc' => 1,
873
+							'QSG_system'          => EEM_Question_Group::system_personal,
874
+							'QSG_deleted'         => 0,
875
+						);
876
+						break;
877
+					case 2:
878
+						$QSG_values = array(
879
+							'QSG_name'            => __('Address Information', 'event_espresso'),
880
+							'QSG_identifier'      => 'address-information-' . time(),
881
+							'QSG_desc'            => '',
882
+							'QSG_order'           => 2,
883
+							'QSG_show_group_name' => 1,
884
+							'QSG_show_group_desc' => 1,
885
+							'QSG_system'          => EEM_Question_Group::system_address,
886
+							'QSG_deleted'         => 0,
887
+						);
888
+						break;
889
+				}
890
+				// make sure we have some values before inserting them
891
+				if (! empty($QSG_values)) {
892
+					// insert system question
893
+					$wpdb->insert(
894
+						$table_name,
895
+						$QSG_values,
896
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
897
+					);
898
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
899
+				}
900
+			}
901
+		}
902
+		// QUESTIONS
903
+		global $wpdb;
904
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
905
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
906
+		// what we have
907
+		$questions = $wpdb->get_col($SQL);
908
+		// what we should have
909
+		$QST_systems = array(
910
+			'fname',
911
+			'lname',
912
+			'email',
913
+			'address',
914
+			'address2',
915
+			'city',
916
+			'country',
917
+			'state',
918
+			'zip',
919
+			'phone',
920
+		);
921
+		$order_for_group_1 = 1;
922
+		$order_for_group_2 = 1;
923
+		// loop thru what we should have and compare to what we have
924
+		foreach ($QST_systems as $QST_system) {
925
+			// reset values array
926
+			$QST_values = array();
927
+			// if we don't have what we should have
928
+			if (! in_array($QST_system, $questions)) {
929
+				// add it
930
+				switch ($QST_system) {
931
+					case 'fname':
932
+						$QST_values = array(
933
+							'QST_display_text'  => __('First Name', 'event_espresso'),
934
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
935
+							'QST_system'        => 'fname',
936
+							'QST_type'          => 'TEXT',
937
+							'QST_required'      => 1,
938
+							'QST_required_text' => __('This field is required', 'event_espresso'),
939
+							'QST_order'         => 1,
940
+							'QST_admin_only'    => 0,
941
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
942
+							'QST_wp_user'       => self::get_default_creator_id(),
943
+							'QST_deleted'       => 0,
944
+						);
945
+						break;
946
+					case 'lname':
947
+						$QST_values = array(
948
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
949
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
950
+							'QST_system'        => 'lname',
951
+							'QST_type'          => 'TEXT',
952
+							'QST_required'      => 1,
953
+							'QST_required_text' => __('This field is required', 'event_espresso'),
954
+							'QST_order'         => 2,
955
+							'QST_admin_only'    => 0,
956
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
957
+							'QST_wp_user'       => self::get_default_creator_id(),
958
+							'QST_deleted'       => 0,
959
+						);
960
+						break;
961
+					case 'email':
962
+						$QST_values = array(
963
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
964
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
965
+							'QST_system'        => 'email',
966
+							'QST_type'          => 'EMAIL',
967
+							'QST_required'      => 1,
968
+							'QST_required_text' => __('This field is required', 'event_espresso'),
969
+							'QST_order'         => 3,
970
+							'QST_admin_only'    => 0,
971
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
972
+							'QST_wp_user'       => self::get_default_creator_id(),
973
+							'QST_deleted'       => 0,
974
+						);
975
+						break;
976
+					case 'address':
977
+						$QST_values = array(
978
+							'QST_display_text'  => __('Address', 'event_espresso'),
979
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
980
+							'QST_system'        => 'address',
981
+							'QST_type'          => 'TEXT',
982
+							'QST_required'      => 0,
983
+							'QST_required_text' => __('This field is required', 'event_espresso'),
984
+							'QST_order'         => 4,
985
+							'QST_admin_only'    => 0,
986
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
987
+							'QST_wp_user'       => self::get_default_creator_id(),
988
+							'QST_deleted'       => 0,
989
+						);
990
+						break;
991
+					case 'address2':
992
+						$QST_values = array(
993
+							'QST_display_text'  => __('Address2', 'event_espresso'),
994
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
995
+							'QST_system'        => 'address2',
996
+							'QST_type'          => 'TEXT',
997
+							'QST_required'      => 0,
998
+							'QST_required_text' => __('This field is required', 'event_espresso'),
999
+							'QST_order'         => 5,
1000
+							'QST_admin_only'    => 0,
1001
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1002
+							'QST_wp_user'       => self::get_default_creator_id(),
1003
+							'QST_deleted'       => 0,
1004
+						);
1005
+						break;
1006
+					case 'city':
1007
+						$QST_values = array(
1008
+							'QST_display_text'  => __('City', 'event_espresso'),
1009
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1010
+							'QST_system'        => 'city',
1011
+							'QST_type'          => 'TEXT',
1012
+							'QST_required'      => 0,
1013
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1014
+							'QST_order'         => 6,
1015
+							'QST_admin_only'    => 0,
1016
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1017
+							'QST_wp_user'       => self::get_default_creator_id(),
1018
+							'QST_deleted'       => 0,
1019
+						);
1020
+						break;
1021
+					case 'country':
1022
+						$QST_values = array(
1023
+							'QST_display_text'  => __('Country', 'event_espresso'),
1024
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1025
+							'QST_system'        => 'country',
1026
+							'QST_type'          => 'COUNTRY',
1027
+							'QST_required'      => 0,
1028
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1029
+							'QST_order'         => 7,
1030
+							'QST_admin_only'    => 0,
1031
+							'QST_wp_user'       => self::get_default_creator_id(),
1032
+							'QST_deleted'       => 0,
1033
+						);
1034
+						break;
1035
+					case 'state':
1036
+						$QST_values = array(
1037
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1038
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1039
+							'QST_system'        => 'state',
1040
+							'QST_type'          => 'STATE',
1041
+							'QST_required'      => 0,
1042
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1043
+							'QST_order'         => 8,
1044
+							'QST_admin_only'    => 0,
1045
+							'QST_wp_user'       => self::get_default_creator_id(),
1046
+							'QST_deleted'       => 0,
1047
+						);
1048
+						break;
1049
+					case 'zip':
1050
+						$QST_values = array(
1051
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1052
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1053
+							'QST_system'        => 'zip',
1054
+							'QST_type'          => 'TEXT',
1055
+							'QST_required'      => 0,
1056
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1057
+							'QST_order'         => 9,
1058
+							'QST_admin_only'    => 0,
1059
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1060
+							'QST_wp_user'       => self::get_default_creator_id(),
1061
+							'QST_deleted'       => 0,
1062
+						);
1063
+						break;
1064
+					case 'phone':
1065
+						$QST_values = array(
1066
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1067
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1068
+							'QST_system'        => 'phone',
1069
+							'QST_type'          => 'TEXT',
1070
+							'QST_required'      => 0,
1071
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1072
+							'QST_order'         => 10,
1073
+							'QST_admin_only'    => 0,
1074
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1075
+							'QST_wp_user'       => self::get_default_creator_id(),
1076
+							'QST_deleted'       => 0,
1077
+						);
1078
+						break;
1079
+				}
1080
+				if (! empty($QST_values)) {
1081
+					// insert system question
1082
+					$wpdb->insert(
1083
+						$table_name,
1084
+						$QST_values,
1085
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1086
+					);
1087
+					$QST_ID = $wpdb->insert_id;
1088
+					// QUESTION GROUP QUESTIONS
1089
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1090
+						$system_question_we_want = EEM_Question_Group::system_personal;
1091
+					} else {
1092
+						$system_question_we_want = EEM_Question_Group::system_address;
1093
+					}
1094
+					if (isset($QSG_IDs[$system_question_we_want])) {
1095
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1096
+					} else {
1097
+						$id_col = EEM_Question_Group::instance()
1098
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1099
+						if (is_array($id_col)) {
1100
+							$QSG_ID = reset($id_col);
1101
+						} else {
1102
+							//ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1103
+							EE_Log::instance()->log(
1104
+								__FILE__,
1105
+								__FUNCTION__,
1106
+								sprintf(
1107
+									__(
1108
+										'Could not associate question %1$s to a question group because no system question
1109 1109
                                          group existed',
1110
-                                        'event_espresso'
1111
-                                    ),
1112
-                                    $QST_ID),
1113
-                                'error');
1114
-                            continue;
1115
-                        }
1116
-                    }
1117
-                    // add system questions to groups
1118
-                    $wpdb->insert(
1119
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1120
-                        array(
1121
-                            'QSG_ID'    => $QSG_ID,
1122
-                            'QST_ID'    => $QST_ID,
1123
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1124
-                        ),
1125
-                        array('%d', '%d', '%d')
1126
-                    );
1127
-                }
1128
-            }
1129
-        }
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     * Makes sure the default payment method (Invoice) is active.
1135
-     * This used to be done automatically as part of constructing the old gateways config
1136
-     *
1137
-     * @throws \EE_Error
1138
-     */
1139
-    public static function insert_default_payment_methods()
1140
-    {
1141
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144
-        } else {
1145
-            EEM_Payment_Method::instance()->verify_button_urls();
1146
-        }
1147
-    }
1148
-
1149
-    /**
1150
-     * insert_default_status_codes
1151
-     *
1152
-     * @access public
1153
-     * @static
1154
-     * @return void
1155
-     */
1156
-    public static function insert_default_status_codes()
1157
-    {
1158
-
1159
-        global $wpdb;
1160
-
1161
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1162
-
1163
-            $table_name = EEM_Status::instance()->table();
1164
-
1165
-            $SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1166
-            $wpdb->query($SQL);
1167
-
1168
-            $SQL = "INSERT INTO $table_name
1110
+										'event_espresso'
1111
+									),
1112
+									$QST_ID),
1113
+								'error');
1114
+							continue;
1115
+						}
1116
+					}
1117
+					// add system questions to groups
1118
+					$wpdb->insert(
1119
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1120
+						array(
1121
+							'QSG_ID'    => $QSG_ID,
1122
+							'QST_ID'    => $QST_ID,
1123
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1124
+						),
1125
+						array('%d', '%d', '%d')
1126
+					);
1127
+				}
1128
+			}
1129
+		}
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 * Makes sure the default payment method (Invoice) is active.
1135
+	 * This used to be done automatically as part of constructing the old gateways config
1136
+	 *
1137
+	 * @throws \EE_Error
1138
+	 */
1139
+	public static function insert_default_payment_methods()
1140
+	{
1141
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144
+		} else {
1145
+			EEM_Payment_Method::instance()->verify_button_urls();
1146
+		}
1147
+	}
1148
+
1149
+	/**
1150
+	 * insert_default_status_codes
1151
+	 *
1152
+	 * @access public
1153
+	 * @static
1154
+	 * @return void
1155
+	 */
1156
+	public static function insert_default_status_codes()
1157
+	{
1158
+
1159
+		global $wpdb;
1160
+
1161
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1162
+
1163
+			$table_name = EEM_Status::instance()->table();
1164
+
1165
+			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1166
+			$wpdb->query($SQL);
1167
+
1168
+			$SQL = "INSERT INTO $table_name
1169 1169
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1170 1170
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1171 1171
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1205,462 +1205,462 @@  discard block
 block discarded – undo
1205 1205
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1206 1206
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1207 1207
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1208
-            $wpdb->query($SQL);
1209
-
1210
-        }
1211
-
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * generate_default_message_templates
1217
-     *
1218
-     * @static
1219
-     * @throws EE_Error
1220
-     * @return bool     true means new templates were created.
1221
-     *                  false means no templates were created.
1222
-     *                  This is NOT an error flag. To check for errors you will want
1223
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1224
-     */
1225
-    public static function generate_default_message_templates()
1226
-    {
1227
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1228
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1229
-        /*
1208
+			$wpdb->query($SQL);
1209
+
1210
+		}
1211
+
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * generate_default_message_templates
1217
+	 *
1218
+	 * @static
1219
+	 * @throws EE_Error
1220
+	 * @return bool     true means new templates were created.
1221
+	 *                  false means no templates were created.
1222
+	 *                  This is NOT an error flag. To check for errors you will want
1223
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1224
+	 */
1225
+	public static function generate_default_message_templates()
1226
+	{
1227
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1228
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1229
+		/*
1230 1230
          * This first method is taking care of ensuring any default messengers
1231 1231
          * that should be made active and have templates generated are done.
1232 1232
          */
1233
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1234
-            $message_resource_manager
1235
-        );
1236
-        /**
1237
-         * This method is verifying there are no NEW default message types
1238
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1239
-         */
1240
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1241
-            $message_resource_manager
1242
-        );
1243
-        //after all is done, let's persist these changes to the db.
1244
-        $message_resource_manager->update_has_activated_messengers_option();
1245
-        $message_resource_manager->update_active_messengers_option();
1246
-        // will return true if either of these are true.  Otherwise will return false.
1247
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1248
-    }
1249
-
1250
-
1251
-
1252
-    /**
1253
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1254
-     * @return array|bool
1255
-     * @throws \EE_Error
1256
-     */
1257
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1258
-        EE_Message_Resource_Manager $message_resource_manager
1259
-    ) {
1260
-        /** @type EE_messenger[] $active_messengers */
1261
-        $active_messengers = $message_resource_manager->active_messengers();
1262
-        $installed_message_types = $message_resource_manager->installed_message_types();
1263
-        $templates_created = false;
1264
-        foreach ($active_messengers as $active_messenger) {
1265
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1266
-            $default_message_type_names_to_activate = array();
1267
-            // looping through each default message type reported by the messenger
1268
-            // and setup the actual message types to activate.
1269
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1270
-                // if already active or has already been activated before we skip
1271
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1272
-                // we also skip if the message type is not installed.
1273
-                if (
1274
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1275
-                        $default_message_type_name_for_messenger,
1276
-                        $active_messenger->name
1277
-                    )
1278
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1279
-                        $active_messenger->name,
1280
-                        $default_message_type_name_for_messenger
1281
-                    )
1282
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1283
-                ) {
1284
-                    continue;
1285
-                }
1286
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1287
-            }
1288
-            //let's activate!
1289
-            $message_resource_manager->ensure_message_types_are_active(
1290
-                $default_message_type_names_to_activate,
1291
-                $active_messenger->name,
1292
-                false
1293
-            );
1294
-            //activate the templates for these message types
1295
-            if ( ! empty($default_message_type_names_to_activate)) {
1296
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1297
-                    $active_messenger->name,
1298
-                    $default_message_type_names_for_messenger,
1299
-                    '',
1300
-                    true
1301
-                );
1302
-            }
1303
-        }
1304
-        return $templates_created;
1305
-    }
1306
-
1307
-
1308
-
1309
-    /**
1310
-     * This will activate and generate default messengers and default message types for those messengers.
1311
-     *
1312
-     * @param EE_message_Resource_Manager $message_resource_manager
1313
-     * @return array|bool  True means there were default messengers and message type templates generated.
1314
-     *                     False means that there were no templates generated
1315
-     *                     (which could simply mean there are no default message types for a messenger).
1316
-     * @throws EE_Error
1317
-     */
1318
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1319
-        EE_Message_Resource_Manager $message_resource_manager
1320
-    ) {
1321
-        /** @type EE_messenger[] $messengers_to_generate */
1322
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1323
-        $installed_message_types = $message_resource_manager->installed_message_types();
1324
-        $templates_generated = false;
1325
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1326
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1327
-            //verify the default message types match an installed message type.
1328
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1329
-                if (
1330
-                    ! isset($installed_message_types[$name])
1331
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1332
-                        $name,
1333
-                        $messenger_to_generate->name
1334
-                    )
1335
-                ) {
1336
-                    unset($default_message_type_names_for_messenger[$key]);
1337
-                }
1338
-            }
1339
-            // in previous iterations, the active_messengers option in the db
1340
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1341
-            // This comment is left here just in case we discover that we _do_ need to update before
1342
-            // passing off to create templates (after the refactor is done).
1343
-            // @todo remove this comment when determined not necessary.
1344
-            $message_resource_manager->activate_messenger(
1345
-                $messenger_to_generate->name,
1346
-                $default_message_type_names_for_messenger,
1347
-                false
1348
-            );
1349
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1350
-            if ( ! empty($default_message_type_names_for_messenger)) {
1351
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1352
-                    $messenger_to_generate->name,
1353
-                    $default_message_type_names_for_messenger,
1354
-                    '',
1355
-                    true
1356
-                );
1357
-            }
1358
-        }
1359
-        return $templates_generated;
1360
-    }
1361
-
1362
-
1363
-    /**
1364
-     * This returns the default messengers to generate templates for on activation of EE.
1365
-     * It considers:
1366
-     * - whether a messenger is already active in the db.
1367
-     * - whether a messenger has been made active at any time in the past.
1368
-     *
1369
-     * @static
1370
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1371
-     * @return EE_messenger[]
1372
-     */
1373
-    protected static function _get_default_messengers_to_generate_on_activation(
1374
-        EE_Message_Resource_Manager $message_resource_manager
1375
-    ) {
1376
-        $active_messengers    = $message_resource_manager->active_messengers();
1377
-        $installed_messengers = $message_resource_manager->installed_messengers();
1378
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1379
-
1380
-        $messengers_to_generate = array();
1381
-        foreach ($installed_messengers as $installed_messenger) {
1382
-            //if installed messenger is a messenger that should be activated on install
1383
-            //and is not already active
1384
-            //and has never been activated
1385
-            if (
1386
-                ! $installed_messenger->activate_on_install
1387
-                || isset($active_messengers[$installed_messenger->name])
1388
-                || isset($has_activated[$installed_messenger->name])
1389
-            ) {
1390
-                continue;
1391
-            }
1392
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1393
-        }
1394
-        return $messengers_to_generate;
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * This simply validates active message types to ensure they actually match installed
1400
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1401
-     * rows are set inactive.
1402
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1403
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1404
-     * are still handled in here.
1405
-     *
1406
-     * @since 4.3.1
1407
-     * @return void
1408
-     */
1409
-    public static function validate_messages_system()
1410
-    {
1411
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1412
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1413
-        $message_resource_manager->validate_active_message_types_are_installed();
1414
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1415
-    }
1416
-
1417
-
1418
-    /**
1419
-     * create_no_ticket_prices_array
1420
-     *
1421
-     * @access public
1422
-     * @static
1423
-     * @return void
1424
-     */
1425
-    public static function create_no_ticket_prices_array()
1426
-    {
1427
-        // this creates an array for tracking events that have no active ticket prices created
1428
-        // this allows us to warn admins of the situation so that it can be corrected
1429
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
-        if (! $espresso_no_ticket_prices) {
1431
-            add_option('ee_no_ticket_prices', array(), '', false);
1432
-        }
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * plugin_deactivation
1438
-     *
1439
-     * @access public
1440
-     * @static
1441
-     * @return void
1442
-     */
1443
-    public static function plugin_deactivation()
1444
-    {
1445
-    }
1446
-
1447
-
1448
-    /**
1449
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1450
-     * (like post meta or term relations)
1451
-     *
1452
-     * @global wpdb $wpdb
1453
-     * @throws \EE_Error
1454
-     */
1455
-    public static function delete_all_espresso_cpt_data()
1456
-    {
1457
-        global $wpdb;
1458
-        //get all the CPT post_types
1459
-        $ee_post_types = array();
1460
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1461
-            if (method_exists($model_name, 'instance')) {
1462
-                $model_obj = call_user_func(array($model_name, 'instance'));
1463
-                if ($model_obj instanceof EEM_CPT_Base) {
1464
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1465
-                }
1466
-            }
1467
-        }
1468
-        //get all our CPTs
1469
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1470
-        $cpt_ids = $wpdb->get_col($query);
1471
-        //delete each post meta and term relations too
1472
-        foreach ($cpt_ids as $post_id) {
1473
-            wp_delete_post($post_id, true);
1474
-        }
1475
-    }
1476
-
1477
-    /**
1478
-     * Deletes all EE custom tables
1479
-     *
1480
-     * @return array
1481
-     */
1482
-    public static function drop_espresso_tables()
1483
-    {
1484
-        $tables = array();
1485
-        // load registry
1486
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1487
-            if (method_exists($model_name, 'instance')) {
1488
-                $model_obj = call_user_func(array($model_name, 'instance'));
1489
-                if ($model_obj instanceof EEM_Base) {
1490
-                    foreach ($model_obj->get_tables() as $table) {
1491
-                        if (strpos($table->get_table_name(), 'esp_')
1492
-                            &&
1493
-                            (
1494
-                                is_main_site()//main site? nuke them all
1495
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1496
-                            )
1497
-                        ) {
1498
-                            $tables[$table->get_table_name()] = $table->get_table_name();
1499
-                        }
1500
-                    }
1501
-                }
1502
-            }
1503
-        }
1504
-
1505
-        //there are some tables whose models were removed.
1506
-        //they should be removed when removing all EE core's data
1507
-        $tables_without_models = array(
1508
-            'esp_promotion',
1509
-            'esp_promotion_applied',
1510
-            'esp_promotion_object',
1511
-            'esp_promotion_rule',
1512
-            'esp_rule',
1513
-        );
1514
-        foreach ($tables_without_models as $table) {
1515
-            $tables[$table] = $table;
1516
-        }
1517
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1518
-    }
1519
-
1520
-
1521
-
1522
-    /**
1523
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1524
-     * each table name provided has a wpdb prefix attached, and that it exists.
1525
-     * Returns the list actually deleted
1526
-     *
1527
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1528
-     * @global WPDB $wpdb
1529
-     * @param array $table_names
1530
-     * @return array of table names which we deleted
1531
-     */
1532
-    public static function drop_tables($table_names)
1533
-    {
1534
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1535
-    }
1536
-
1537
-
1538
-
1539
-    /**
1540
-     * plugin_uninstall
1541
-     *
1542
-     * @access public
1543
-     * @static
1544
-     * @param bool $remove_all
1545
-     * @return void
1546
-     */
1547
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1548
-    {
1549
-        global $wpdb;
1550
-        self::drop_espresso_tables();
1551
-        $wp_options_to_delete = array(
1552
-            'ee_no_ticket_prices'                => true,
1553
-            'ee_active_messengers'               => true,
1554
-            'ee_has_activated_messenger'         => true,
1555
-            'ee_flush_rewrite_rules'             => true,
1556
-            'ee_config'                          => false,
1557
-            'ee_data_migration_current_db_state' => true,
1558
-            'ee_data_migration_mapping_'         => false,
1559
-            'ee_data_migration_script_'          => false,
1560
-            'ee_data_migrations'                 => true,
1561
-            'ee_dms_map'                         => false,
1562
-            'ee_notices'                         => true,
1563
-            'lang_file_check_'                   => false,
1564
-            'ee_maintenance_mode'                => true,
1565
-            'ee_ueip_optin'                      => true,
1566
-            'ee_ueip_has_notified'               => true,
1567
-            'ee_plugin_activation_errors'        => true,
1568
-            'ee_id_mapping_from'                 => false,
1569
-            'espresso_persistent_admin_notices'  => true,
1570
-            'ee_encryption_key'                  => true,
1571
-            'pue_force_upgrade_'                 => false,
1572
-            'pue_json_error_'                    => false,
1573
-            'pue_install_key_'                   => false,
1574
-            'pue_verification_error_'            => false,
1575
-            'pu_dismissed_upgrade_'              => false,
1576
-            'external_updates-'                  => false,
1577
-            'ee_extra_data'                      => true,
1578
-            'ee_ssn_'                            => false,
1579
-            'ee_rss_'                            => false,
1580
-            'ee_rte_n_tx_'                       => false,
1581
-            'ee_pers_admin_notices'              => true,
1582
-            'ee_job_parameters_'                 => false,
1583
-            'ee_upload_directories_incomplete'   => true,
1584
-            'ee_verified_db_collations'          => true,
1585
-        );
1586
-        if (is_main_site()) {
1587
-            $wp_options_to_delete['ee_network_config'] = true;
1588
-        }
1589
-        $undeleted_options = array();
1590
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1591
-            if ($no_wildcard) {
1592
-                if ( ! delete_option($option_name)) {
1593
-                    $undeleted_options[] = $option_name;
1594
-                }
1595
-            } else {
1596
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1597
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1598
-                    if ( ! delete_option($option_name_from_wildcard)) {
1599
-                        $undeleted_options[] = $option_name_from_wildcard;
1600
-                    }
1601
-                }
1602
-            }
1603
-        }
1604
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1605
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1606
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607
-            $db_update_sans_ee4 = array();
1608
-            foreach ($espresso_db_update as $version => $times_activated) {
1609
-                if ((string)$version[0] === '3') {//if its NON EE4
1610
-                    $db_update_sans_ee4[$version] = $times_activated;
1611
-                }
1612
-            }
1613
-            update_option('espresso_db_update', $db_update_sans_ee4);
1614
-        }
1615
-        $errors = '';
1616
-        if ( ! empty($undeleted_options)) {
1617
-            $errors .= sprintf(
1618
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1619
-                '<br/>',
1620
-                implode(',<br/>', $undeleted_options)
1621
-            );
1622
-        }
1623
-        if ( ! empty($errors)) {
1624
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1625
-        }
1626
-    }
1627
-
1628
-    /**
1629
-     * Gets the mysql error code from the last used query by wpdb
1630
-     *
1631
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1632
-     */
1633
-    public static function last_wpdb_error_code()
1634
-    {
1635
-        global $wpdb;
1636
-        if ($wpdb->use_mysqli) {
1637
-            return mysqli_errno($wpdb->dbh);
1638
-        } else {
1639
-            return mysql_errno($wpdb->dbh);
1640
-        }
1641
-    }
1642
-
1643
-    /**
1644
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1645
-     *
1646
-     * @global wpdb  $wpdb
1647
-     * @deprecated instead use TableAnalysis::tableExists()
1648
-     * @param string $table_name with or without $wpdb->prefix
1649
-     * @return boolean
1650
-     */
1651
-    public static function table_exists($table_name)
1652
-    {
1653
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1654
-    }
1655
-
1656
-    /**
1657
-     * Resets the cache on EEH_Activation
1658
-     */
1659
-    public static function reset()
1660
-    {
1661
-        self::$_default_creator_id                             = null;
1662
-        self::$_initialized_db_content_already_in_this_request = false;
1663
-    }
1233
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1234
+			$message_resource_manager
1235
+		);
1236
+		/**
1237
+		 * This method is verifying there are no NEW default message types
1238
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1239
+		 */
1240
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1241
+			$message_resource_manager
1242
+		);
1243
+		//after all is done, let's persist these changes to the db.
1244
+		$message_resource_manager->update_has_activated_messengers_option();
1245
+		$message_resource_manager->update_active_messengers_option();
1246
+		// will return true if either of these are true.  Otherwise will return false.
1247
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1248
+	}
1249
+
1250
+
1251
+
1252
+	/**
1253
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1254
+	 * @return array|bool
1255
+	 * @throws \EE_Error
1256
+	 */
1257
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1258
+		EE_Message_Resource_Manager $message_resource_manager
1259
+	) {
1260
+		/** @type EE_messenger[] $active_messengers */
1261
+		$active_messengers = $message_resource_manager->active_messengers();
1262
+		$installed_message_types = $message_resource_manager->installed_message_types();
1263
+		$templates_created = false;
1264
+		foreach ($active_messengers as $active_messenger) {
1265
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1266
+			$default_message_type_names_to_activate = array();
1267
+			// looping through each default message type reported by the messenger
1268
+			// and setup the actual message types to activate.
1269
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1270
+				// if already active or has already been activated before we skip
1271
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1272
+				// we also skip if the message type is not installed.
1273
+				if (
1274
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1275
+						$default_message_type_name_for_messenger,
1276
+						$active_messenger->name
1277
+					)
1278
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1279
+						$active_messenger->name,
1280
+						$default_message_type_name_for_messenger
1281
+					)
1282
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1283
+				) {
1284
+					continue;
1285
+				}
1286
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1287
+			}
1288
+			//let's activate!
1289
+			$message_resource_manager->ensure_message_types_are_active(
1290
+				$default_message_type_names_to_activate,
1291
+				$active_messenger->name,
1292
+				false
1293
+			);
1294
+			//activate the templates for these message types
1295
+			if ( ! empty($default_message_type_names_to_activate)) {
1296
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1297
+					$active_messenger->name,
1298
+					$default_message_type_names_for_messenger,
1299
+					'',
1300
+					true
1301
+				);
1302
+			}
1303
+		}
1304
+		return $templates_created;
1305
+	}
1306
+
1307
+
1308
+
1309
+	/**
1310
+	 * This will activate and generate default messengers and default message types for those messengers.
1311
+	 *
1312
+	 * @param EE_message_Resource_Manager $message_resource_manager
1313
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1314
+	 *                     False means that there were no templates generated
1315
+	 *                     (which could simply mean there are no default message types for a messenger).
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1319
+		EE_Message_Resource_Manager $message_resource_manager
1320
+	) {
1321
+		/** @type EE_messenger[] $messengers_to_generate */
1322
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1323
+		$installed_message_types = $message_resource_manager->installed_message_types();
1324
+		$templates_generated = false;
1325
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1326
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1327
+			//verify the default message types match an installed message type.
1328
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1329
+				if (
1330
+					! isset($installed_message_types[$name])
1331
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1332
+						$name,
1333
+						$messenger_to_generate->name
1334
+					)
1335
+				) {
1336
+					unset($default_message_type_names_for_messenger[$key]);
1337
+				}
1338
+			}
1339
+			// in previous iterations, the active_messengers option in the db
1340
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1341
+			// This comment is left here just in case we discover that we _do_ need to update before
1342
+			// passing off to create templates (after the refactor is done).
1343
+			// @todo remove this comment when determined not necessary.
1344
+			$message_resource_manager->activate_messenger(
1345
+				$messenger_to_generate->name,
1346
+				$default_message_type_names_for_messenger,
1347
+				false
1348
+			);
1349
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1350
+			if ( ! empty($default_message_type_names_for_messenger)) {
1351
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1352
+					$messenger_to_generate->name,
1353
+					$default_message_type_names_for_messenger,
1354
+					'',
1355
+					true
1356
+				);
1357
+			}
1358
+		}
1359
+		return $templates_generated;
1360
+	}
1361
+
1362
+
1363
+	/**
1364
+	 * This returns the default messengers to generate templates for on activation of EE.
1365
+	 * It considers:
1366
+	 * - whether a messenger is already active in the db.
1367
+	 * - whether a messenger has been made active at any time in the past.
1368
+	 *
1369
+	 * @static
1370
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1371
+	 * @return EE_messenger[]
1372
+	 */
1373
+	protected static function _get_default_messengers_to_generate_on_activation(
1374
+		EE_Message_Resource_Manager $message_resource_manager
1375
+	) {
1376
+		$active_messengers    = $message_resource_manager->active_messengers();
1377
+		$installed_messengers = $message_resource_manager->installed_messengers();
1378
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1379
+
1380
+		$messengers_to_generate = array();
1381
+		foreach ($installed_messengers as $installed_messenger) {
1382
+			//if installed messenger is a messenger that should be activated on install
1383
+			//and is not already active
1384
+			//and has never been activated
1385
+			if (
1386
+				! $installed_messenger->activate_on_install
1387
+				|| isset($active_messengers[$installed_messenger->name])
1388
+				|| isset($has_activated[$installed_messenger->name])
1389
+			) {
1390
+				continue;
1391
+			}
1392
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1393
+		}
1394
+		return $messengers_to_generate;
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * This simply validates active message types to ensure they actually match installed
1400
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1401
+	 * rows are set inactive.
1402
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1403
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1404
+	 * are still handled in here.
1405
+	 *
1406
+	 * @since 4.3.1
1407
+	 * @return void
1408
+	 */
1409
+	public static function validate_messages_system()
1410
+	{
1411
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1412
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1413
+		$message_resource_manager->validate_active_message_types_are_installed();
1414
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1415
+	}
1416
+
1417
+
1418
+	/**
1419
+	 * create_no_ticket_prices_array
1420
+	 *
1421
+	 * @access public
1422
+	 * @static
1423
+	 * @return void
1424
+	 */
1425
+	public static function create_no_ticket_prices_array()
1426
+	{
1427
+		// this creates an array for tracking events that have no active ticket prices created
1428
+		// this allows us to warn admins of the situation so that it can be corrected
1429
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
+		if (! $espresso_no_ticket_prices) {
1431
+			add_option('ee_no_ticket_prices', array(), '', false);
1432
+		}
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * plugin_deactivation
1438
+	 *
1439
+	 * @access public
1440
+	 * @static
1441
+	 * @return void
1442
+	 */
1443
+	public static function plugin_deactivation()
1444
+	{
1445
+	}
1446
+
1447
+
1448
+	/**
1449
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1450
+	 * (like post meta or term relations)
1451
+	 *
1452
+	 * @global wpdb $wpdb
1453
+	 * @throws \EE_Error
1454
+	 */
1455
+	public static function delete_all_espresso_cpt_data()
1456
+	{
1457
+		global $wpdb;
1458
+		//get all the CPT post_types
1459
+		$ee_post_types = array();
1460
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1461
+			if (method_exists($model_name, 'instance')) {
1462
+				$model_obj = call_user_func(array($model_name, 'instance'));
1463
+				if ($model_obj instanceof EEM_CPT_Base) {
1464
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1465
+				}
1466
+			}
1467
+		}
1468
+		//get all our CPTs
1469
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1470
+		$cpt_ids = $wpdb->get_col($query);
1471
+		//delete each post meta and term relations too
1472
+		foreach ($cpt_ids as $post_id) {
1473
+			wp_delete_post($post_id, true);
1474
+		}
1475
+	}
1476
+
1477
+	/**
1478
+	 * Deletes all EE custom tables
1479
+	 *
1480
+	 * @return array
1481
+	 */
1482
+	public static function drop_espresso_tables()
1483
+	{
1484
+		$tables = array();
1485
+		// load registry
1486
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1487
+			if (method_exists($model_name, 'instance')) {
1488
+				$model_obj = call_user_func(array($model_name, 'instance'));
1489
+				if ($model_obj instanceof EEM_Base) {
1490
+					foreach ($model_obj->get_tables() as $table) {
1491
+						if (strpos($table->get_table_name(), 'esp_')
1492
+							&&
1493
+							(
1494
+								is_main_site()//main site? nuke them all
1495
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1496
+							)
1497
+						) {
1498
+							$tables[$table->get_table_name()] = $table->get_table_name();
1499
+						}
1500
+					}
1501
+				}
1502
+			}
1503
+		}
1504
+
1505
+		//there are some tables whose models were removed.
1506
+		//they should be removed when removing all EE core's data
1507
+		$tables_without_models = array(
1508
+			'esp_promotion',
1509
+			'esp_promotion_applied',
1510
+			'esp_promotion_object',
1511
+			'esp_promotion_rule',
1512
+			'esp_rule',
1513
+		);
1514
+		foreach ($tables_without_models as $table) {
1515
+			$tables[$table] = $table;
1516
+		}
1517
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1518
+	}
1519
+
1520
+
1521
+
1522
+	/**
1523
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1524
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1525
+	 * Returns the list actually deleted
1526
+	 *
1527
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1528
+	 * @global WPDB $wpdb
1529
+	 * @param array $table_names
1530
+	 * @return array of table names which we deleted
1531
+	 */
1532
+	public static function drop_tables($table_names)
1533
+	{
1534
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1535
+	}
1536
+
1537
+
1538
+
1539
+	/**
1540
+	 * plugin_uninstall
1541
+	 *
1542
+	 * @access public
1543
+	 * @static
1544
+	 * @param bool $remove_all
1545
+	 * @return void
1546
+	 */
1547
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1548
+	{
1549
+		global $wpdb;
1550
+		self::drop_espresso_tables();
1551
+		$wp_options_to_delete = array(
1552
+			'ee_no_ticket_prices'                => true,
1553
+			'ee_active_messengers'               => true,
1554
+			'ee_has_activated_messenger'         => true,
1555
+			'ee_flush_rewrite_rules'             => true,
1556
+			'ee_config'                          => false,
1557
+			'ee_data_migration_current_db_state' => true,
1558
+			'ee_data_migration_mapping_'         => false,
1559
+			'ee_data_migration_script_'          => false,
1560
+			'ee_data_migrations'                 => true,
1561
+			'ee_dms_map'                         => false,
1562
+			'ee_notices'                         => true,
1563
+			'lang_file_check_'                   => false,
1564
+			'ee_maintenance_mode'                => true,
1565
+			'ee_ueip_optin'                      => true,
1566
+			'ee_ueip_has_notified'               => true,
1567
+			'ee_plugin_activation_errors'        => true,
1568
+			'ee_id_mapping_from'                 => false,
1569
+			'espresso_persistent_admin_notices'  => true,
1570
+			'ee_encryption_key'                  => true,
1571
+			'pue_force_upgrade_'                 => false,
1572
+			'pue_json_error_'                    => false,
1573
+			'pue_install_key_'                   => false,
1574
+			'pue_verification_error_'            => false,
1575
+			'pu_dismissed_upgrade_'              => false,
1576
+			'external_updates-'                  => false,
1577
+			'ee_extra_data'                      => true,
1578
+			'ee_ssn_'                            => false,
1579
+			'ee_rss_'                            => false,
1580
+			'ee_rte_n_tx_'                       => false,
1581
+			'ee_pers_admin_notices'              => true,
1582
+			'ee_job_parameters_'                 => false,
1583
+			'ee_upload_directories_incomplete'   => true,
1584
+			'ee_verified_db_collations'          => true,
1585
+		);
1586
+		if (is_main_site()) {
1587
+			$wp_options_to_delete['ee_network_config'] = true;
1588
+		}
1589
+		$undeleted_options = array();
1590
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1591
+			if ($no_wildcard) {
1592
+				if ( ! delete_option($option_name)) {
1593
+					$undeleted_options[] = $option_name;
1594
+				}
1595
+			} else {
1596
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1597
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1598
+					if ( ! delete_option($option_name_from_wildcard)) {
1599
+						$undeleted_options[] = $option_name_from_wildcard;
1600
+					}
1601
+				}
1602
+			}
1603
+		}
1604
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1605
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1606
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607
+			$db_update_sans_ee4 = array();
1608
+			foreach ($espresso_db_update as $version => $times_activated) {
1609
+				if ((string)$version[0] === '3') {//if its NON EE4
1610
+					$db_update_sans_ee4[$version] = $times_activated;
1611
+				}
1612
+			}
1613
+			update_option('espresso_db_update', $db_update_sans_ee4);
1614
+		}
1615
+		$errors = '';
1616
+		if ( ! empty($undeleted_options)) {
1617
+			$errors .= sprintf(
1618
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1619
+				'<br/>',
1620
+				implode(',<br/>', $undeleted_options)
1621
+			);
1622
+		}
1623
+		if ( ! empty($errors)) {
1624
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1625
+		}
1626
+	}
1627
+
1628
+	/**
1629
+	 * Gets the mysql error code from the last used query by wpdb
1630
+	 *
1631
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1632
+	 */
1633
+	public static function last_wpdb_error_code()
1634
+	{
1635
+		global $wpdb;
1636
+		if ($wpdb->use_mysqli) {
1637
+			return mysqli_errno($wpdb->dbh);
1638
+		} else {
1639
+			return mysql_errno($wpdb->dbh);
1640
+		}
1641
+	}
1642
+
1643
+	/**
1644
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1645
+	 *
1646
+	 * @global wpdb  $wpdb
1647
+	 * @deprecated instead use TableAnalysis::tableExists()
1648
+	 * @param string $table_name with or without $wpdb->prefix
1649
+	 * @return boolean
1650
+	 */
1651
+	public static function table_exists($table_name)
1652
+	{
1653
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1654
+	}
1655
+
1656
+	/**
1657
+	 * Resets the cache on EEH_Activation
1658
+	 */
1659
+	public static function reset()
1660
+	{
1661
+		self::$_default_creator_id                             = null;
1662
+		self::$_initialized_db_content_already_in_this_request = false;
1663
+	}
1664 1664
 }
1665 1665
 // End of file EEH_Activation.helper.php
1666 1666
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@  discard block
 block discarded – undo
57 57
      */
58 58
     public static function getTableAnalysis()
59 59
     {
60
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
60
+        if ( ! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
61 61
             self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
62 62
         }
63 63
         return self::$table_analysis;
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
      */
70 70
     public static function getTableManager()
71 71
     {
72
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
72
+        if ( ! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
73 73
             self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
74 74
         }
75 75
         return self::$table_manager;
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
         if ($which_to_include === 'old') {
184 184
             $cron_tasks = array_filter(
185 185
                 $cron_tasks,
186
-                function ($value) {
186
+                function($value) {
187 187
                     return $value === EEH_Activation::cron_task_no_longer_in_use;
188 188
                 }
189 189
             );
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
     {
214 214
 
215 215
         foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
216
-            if (! wp_next_scheduled($hook_name)) {
216
+            if ( ! wp_next_scheduled($hook_name)) {
217 217
                 /**
218 218
                  * This allows client code to define the initial start timestamp for this schedule.
219 219
                  */
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
             3
319 319
         );
320 320
         //EE_Config::reset();
321
-        if (! EE_Config::logging_enabled()) {
321
+        if ( ! EE_Config::logging_enabled()) {
322 322
             delete_option(EE_Config::LOG_NAME);
323 323
         }
324 324
     }
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
     public static function load_calendar_config()
334 334
     {
335 335
         // grab array of all plugin folders and loop thru it
336
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
336
+        $plugins = glob(WP_PLUGIN_DIR.DS.'*', GLOB_ONLYDIR);
337 337
         if (empty($plugins)) {
338 338
             return;
339 339
         }
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
                 || strpos($plugin, 'calendar') !== false
351 351
             ) {
352 352
                 // this is what we are looking for
353
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
353
+                $calendar_config = $plugin_path.DS.'EE_Calendar_Config.php';
354 354
                 // does it exist in this folder ?
355 355
                 if (is_readable($calendar_config)) {
356 356
                     // YEAH! let's load it
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
             ) {
479 479
                 //update Config with post ID
480 480
                 $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
481
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
481
+                if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
482 482
                     $msg = __(
483 483
                         'The Event Espresso critical page configuration settings could not be updated.',
484 484
                         'event_espresso'
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
                         'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
502 502
                         'event_espresso'
503 503
                     ),
504
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
504
+                    '<a href="'.admin_url('admin.php?page=espresso_general_settings&action=critical_pages').'">'
505 505
                     . __('Event Espresso Critical Pages Settings', 'event_espresso')
506 506
                     . '</a>'
507 507
                 )
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
     public static function get_page_by_ee_shortcode($ee_shortcode)
528 528
     {
529 529
         global $wpdb;
530
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
530
+        $shortcode_and_opening_bracket = '['.$ee_shortcode;
531 531
         $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
532 532
         if ($post_id) {
533 533
             return get_post($post_id);
@@ -553,11 +553,11 @@  discard block
 block discarded – undo
553 553
             'post_status'    => 'publish',
554 554
             'post_type'      => 'page',
555 555
             'comment_status' => 'closed',
556
-            'post_content'   => '[' . $critical_page['code'] . ']',
556
+            'post_content'   => '['.$critical_page['code'].']',
557 557
         );
558 558
 
559 559
         $post_id = wp_insert_post($post_args);
560
-        if (! $post_id) {
560
+        if ( ! $post_id) {
561 561
             $msg = sprintf(
562 562
                 __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
563 563
                 $critical_page['name']
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
             return $critical_page;
567 567
         }
568 568
         // get newly created post's details
569
-        if (! $critical_page['post'] = get_post($post_id)) {
569
+        if ( ! $critical_page['post'] = get_post($post_id)) {
570 570
             $msg = sprintf(
571 571
                 __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
572 572
                 $critical_page['name']
@@ -603,17 +603,17 @@  discard block
 block discarded – undo
603 603
             $role_to_check
604 604
         );
605 605
         if ($pre_filtered_id !== false) {
606
-            return (int)$pre_filtered_id;
606
+            return (int) $pre_filtered_id;
607 607
         }
608 608
         $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
609 609
         $query = $wpdb->prepare(
610 610
             "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
611
-            '%' . $role_to_check . '%'
611
+            '%'.$role_to_check.'%'
612 612
         );
613 613
         $user_id = $wpdb->get_var($query);
614 614
         $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
615
-        if ($user_id && (int)$user_id) {
616
-            self::$_default_creator_id = (int)$user_id;
615
+        if ($user_id && (int) $user_id) {
616
+            self::$_default_creator_id = (int) $user_id;
617 617
             return self::$_default_creator_id;
618 618
         } else {
619 619
             return null;
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
         }
649 649
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
650 650
         if ( ! function_exists('dbDelta')) {
651
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
651
+            require_once(ABSPATH.'wp-admin/includes/upgrade.php');
652 652
         }
653 653
         $tableAnalysis = \EEH_Activation::getTableAnalysis();
654 654
         $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
@@ -859,13 +859,13 @@  discard block
 block discarded – undo
859 859
             // reset values array
860 860
             $QSG_values = array();
861 861
             // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
862
-            if (! in_array("$QSG_system", $question_groups)) {
862
+            if ( ! in_array("$QSG_system", $question_groups)) {
863 863
                 // add it
864 864
                 switch ($QSG_system) {
865 865
                     case 1:
866 866
                         $QSG_values = array(
867 867
                             'QSG_name'            => __('Personal Information', 'event_espresso'),
868
-                            'QSG_identifier'      => 'personal-information-' . time(),
868
+                            'QSG_identifier'      => 'personal-information-'.time(),
869 869
                             'QSG_desc'            => '',
870 870
                             'QSG_order'           => 1,
871 871
                             'QSG_show_group_name' => 1,
@@ -877,7 +877,7 @@  discard block
 block discarded – undo
877 877
                     case 2:
878 878
                         $QSG_values = array(
879 879
                             'QSG_name'            => __('Address Information', 'event_espresso'),
880
-                            'QSG_identifier'      => 'address-information-' . time(),
880
+                            'QSG_identifier'      => 'address-information-'.time(),
881 881
                             'QSG_desc'            => '',
882 882
                             'QSG_order'           => 2,
883 883
                             'QSG_show_group_name' => 1,
@@ -888,7 +888,7 @@  discard block
 block discarded – undo
888 888
                         break;
889 889
                 }
890 890
                 // make sure we have some values before inserting them
891
-                if (! empty($QSG_values)) {
891
+                if ( ! empty($QSG_values)) {
892 892
                     // insert system question
893 893
                     $wpdb->insert(
894 894
                         $table_name,
@@ -925,7 +925,7 @@  discard block
 block discarded – undo
925 925
             // reset values array
926 926
             $QST_values = array();
927 927
             // if we don't have what we should have
928
-            if (! in_array($QST_system, $questions)) {
928
+            if ( ! in_array($QST_system, $questions)) {
929 929
                 // add it
930 930
                 switch ($QST_system) {
931 931
                     case 'fname':
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
                         );
1078 1078
                         break;
1079 1079
                 }
1080
-                if (! empty($QST_values)) {
1080
+                if ( ! empty($QST_values)) {
1081 1081
                     // insert system question
1082 1082
                     $wpdb->insert(
1083 1083
                         $table_name,
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
      */
1139 1139
     public static function insert_default_payment_methods()
1140 1140
     {
1141
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1141
+        if ( ! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1142 1142
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
1143 1143
             EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1144 1144
         } else {
@@ -1427,7 +1427,7 @@  discard block
 block discarded – undo
1427 1427
         // this creates an array for tracking events that have no active ticket prices created
1428 1428
         // this allows us to warn admins of the situation so that it can be corrected
1429 1429
         $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1430
-        if (! $espresso_no_ticket_prices) {
1430
+        if ( ! $espresso_no_ticket_prices) {
1431 1431
             add_option('ee_no_ticket_prices', array(), '', false);
1432 1432
         }
1433 1433
     }
@@ -1466,7 +1466,7 @@  discard block
 block discarded – undo
1466 1466
             }
1467 1467
         }
1468 1468
         //get all our CPTs
1469
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1469
+        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",", $ee_post_types).")";
1470 1470
         $cpt_ids = $wpdb->get_col($query);
1471 1471
         //delete each post meta and term relations too
1472 1472
         foreach ($cpt_ids as $post_id) {
@@ -1606,7 +1606,7 @@  discard block
 block discarded – undo
1606 1606
         if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1607 1607
             $db_update_sans_ee4 = array();
1608 1608
             foreach ($espresso_db_update as $version => $times_activated) {
1609
-                if ((string)$version[0] === '3') {//if its NON EE4
1609
+                if ((string) $version[0] === '3') {//if its NON EE4
1610 1610
                     $db_update_sans_ee4[$version] = $times_activated;
1611 1611
                 }
1612 1612
             }
Please login to merge, or discard this patch.
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 1 patch
Indentation   +2870 added lines, -2870 removed lines patch added patch discarded remove patch
@@ -15,2874 +15,2874 @@
 block discarded – undo
15 15
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
16 16
 {
17 17
 
18
-    /**
19
-     * @access protected
20
-     * @var EE_Line_Item_Display $Line_Item_Display
21
-     */
22
-    protected $line_item_display;
23
-
24
-    /**
25
-     * @access protected
26
-     * @var boolean $handle_IPN_in_this_request
27
-     */
28
-    protected $handle_IPN_in_this_request = false;
29
-
30
-
31
-    /**
32
-     *    set_hooks - for hooking into EE Core, other modules, etc
33
-     *
34
-     * @access    public
35
-     * @return    void
36
-     */
37
-    public static function set_hooks()
38
-    {
39
-        add_filter(
40
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
-            array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
-        );
43
-        add_action(
44
-            'wp_ajax_switch_spco_billing_form',
45
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
-        );
47
-        add_action(
48
-            'wp_ajax_nopriv_switch_spco_billing_form',
49
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
-        );
51
-        add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
-        add_action(
53
-            'wp_ajax_nopriv_save_payer_details',
54
-            array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
-        );
56
-        add_action(
57
-            'wp_ajax_get_transaction_details_for_gateways',
58
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
-        );
60
-        add_action(
61
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
-        );
64
-        add_filter(
65
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
-            array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
-            10,
68
-            1
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     *    ajax switch_spco_billing_form
75
-     *
76
-     * @throws \EE_Error
77
-     */
78
-    public static function switch_spco_billing_form()
79
-    {
80
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
-    }
82
-
83
-
84
-    /**
85
-     *    ajax save_payer_details
86
-     *
87
-     * @throws \EE_Error
88
-     */
89
-    public static function save_payer_details()
90
-    {
91
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
-    }
93
-
94
-
95
-    /**
96
-     *    ajax get_transaction_details
97
-     *
98
-     * @throws \EE_Error
99
-     */
100
-    public static function get_transaction_details()
101
-    {
102
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
-    }
104
-
105
-
106
-    /**
107
-     * bypass_recaptcha_for_load_payment_method
108
-     *
109
-     * @access public
110
-     * @return array
111
-     * @throws InvalidArgumentException
112
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
-     */
115
-    public static function bypass_recaptcha_for_load_payment_method()
116
-    {
117
-        return array(
118
-            'EESID'  => EE_Registry::instance()->SSN->id(),
119
-            'step'   => 'payment_options',
120
-            'action' => 'spco_billing_form',
121
-        );
122
-    }
123
-
124
-
125
-    /**
126
-     *    class constructor
127
-     *
128
-     * @access    public
129
-     * @param    EE_Checkout $checkout
130
-     */
131
-    public function __construct(EE_Checkout $checkout)
132
-    {
133
-        $this->_slug     = 'payment_options';
134
-        $this->_name     = esc_html__('Payment Options', 'event_espresso');
135
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
-        $this->checkout  = $checkout;
137
-        $this->_reset_success_message();
138
-        $this->set_instructions(
139
-            esc_html__(
140
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
141
-                'event_espresso'
142
-            )
143
-        );
144
-    }
145
-
146
-
147
-    /**
148
-     * @return null
149
-     */
150
-    public function line_item_display()
151
-    {
152
-        return $this->line_item_display;
153
-    }
154
-
155
-
156
-    /**
157
-     * @param null $line_item_display
158
-     */
159
-    public function set_line_item_display($line_item_display)
160
-    {
161
-        $this->line_item_display = $line_item_display;
162
-    }
163
-
164
-
165
-    /**
166
-     * @return boolean
167
-     */
168
-    public function handle_IPN_in_this_request()
169
-    {
170
-        return $this->handle_IPN_in_this_request;
171
-    }
172
-
173
-
174
-    /**
175
-     * @param boolean $handle_IPN_in_this_request
176
-     */
177
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
-    {
179
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
-    }
181
-
182
-
183
-    /**
184
-     * translate_js_strings
185
-     *
186
-     * @return void
187
-     */
188
-    public function translate_js_strings()
189
-    {
190
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
-            'Please select a method of payment in order to continue.',
192
-            'event_espresso'
193
-        );
194
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
196
-            'event_espresso'
197
-        );
198
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
-            'Forwarding to Secure Payment Provider.',
200
-            'event_espresso'
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * enqueue_styles_and_scripts
207
-     *
208
-     * @return void
209
-     * @throws EE_Error
210
-     * @throws InvalidArgumentException
211
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
-     */
214
-    public function enqueue_styles_and_scripts()
215
-    {
216
-        $transaction = $this->checkout->transaction;
217
-        //if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
-            return;
220
-        }
221
-        foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
-            $type_obj = $payment_method->type_obj();
223
-            if ($type_obj instanceof EE_PMT_Base) {
224
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
225
-                if ($billing_form instanceof EE_Form_Section_Proper) {
226
-                    $billing_form->enqueue_js();
227
-                }
228
-            }
229
-        }
230
-    }
231
-
232
-
233
-    /**
234
-     * initialize_reg_step
235
-     *
236
-     * @return bool
237
-     * @throws EE_Error
238
-     * @throws InvalidArgumentException
239
-     * @throws ReflectionException
240
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
-     */
243
-    public function initialize_reg_step()
244
-    {
245
-        // TODO: if /when we implement donations, then this will need overriding
246
-        if (// don't need payment options for:
247
-            // 	registrations made via the admin
248
-            // 	completed transactions
249
-            // 	overpaid transactions
250
-            // 	$ 0.00 transactions (no payment required)
251
-            ! $this->checkout->payment_required()
252
-            // but do NOT remove if current action being called belongs to this reg step
253
-            && ! is_callable(array($this, $this->checkout->action))
254
-            && ! $this->completed()
255
-        ) {
256
-            // and if so, then we no longer need the Payment Options step
257
-            if ($this->is_current_step()) {
258
-                $this->checkout->generate_reg_form = false;
259
-            }
260
-            $this->checkout->remove_reg_step($this->_slug);
261
-            // DEBUG LOG
262
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
-            return false;
264
-        }
265
-        // load EEM_Payment_Method
266
-        EE_Registry::instance()->load_model('Payment_Method');
267
-        // get all active payment methods
268
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
-            $this->checkout->transaction,
270
-            EEM_Payment_Method::scope_cart
271
-        );
272
-        return true;
273
-    }
274
-
275
-
276
-    /**
277
-     * @return EE_Form_Section_Proper
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws ReflectionException
281
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
-     */
286
-    public function generate_reg_form()
287
-    {
288
-        // reset in case someone changes their mind
289
-        $this->_reset_selected_method_of_payment();
290
-        // set some defaults
291
-        $this->checkout->selected_method_of_payment = 'payments_closed';
292
-        $registrations_requiring_payment            = array();
293
-        $registrations_for_free_events              = array();
294
-        $registrations_requiring_pre_approval       = array();
295
-        $sold_out_events                            = array();
296
-        $insufficient_spaces_available              = array();
297
-        $no_payment_required                        = true;
298
-        // loop thru registrations to gather info
299
-        $registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
-            $registrations,
302
-            $this->checkout->revisit
303
-        );
304
-        foreach ($registrations as $REG_ID => $registration) {
305
-            /** @var $registration EE_Registration */
306
-            // has this registration lost it's space ?
307
-            if (isset($ejected_registrations[ $REG_ID ])) {
308
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
-                } else {
311
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
-                }
313
-                continue;
314
-            }
315
-            // event requires admin approval
316
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
-                // add event to list of events with pre-approval reg status
318
-                $registrations_requiring_pre_approval[$REG_ID] = $registration;
319
-                do_action(
320
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
-                    $registration->event(),
322
-                    $this
323
-                );
324
-                continue;
325
-            }
326
-            if ($this->checkout->revisit
327
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
328
-                && (
329
-                    $registration->event()->is_sold_out()
330
-                    || $registration->event()->is_sold_out(true)
331
-                )
332
-            ) {
333
-                // add event to list of events that are sold out
334
-                $sold_out_events[$registration->event()->ID()] = $registration->event();
335
-                do_action(
336
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
-                    $registration->event(),
338
-                    $this
339
-                );
340
-                continue;
341
-            }
342
-            // are they allowed to pay now and is there monies owing?
343
-            if ($registration->owes_monies_and_can_pay()) {
344
-                $registrations_requiring_payment[$REG_ID] = $registration;
345
-                do_action(
346
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
-                    $registration->event(),
348
-                    $this
349
-                );
350
-            } elseif (! $this->checkout->revisit
351
-                && $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
-                && $registration->ticket()->is_free()
353
-            ) {
354
-                $registrations_for_free_events[$registration->event()->ID()] = $registration;
355
-            }
356
-        }
357
-        $subsections = array();
358
-        // now decide which template to load
359
-        if (! empty($sold_out_events)) {
360
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
-        }
362
-        if (! empty($insufficient_spaces_available)) {
363
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
-                $insufficient_spaces_available
365
-            );
366
-        }
367
-        if (! empty($registrations_requiring_pre_approval)) {
368
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
-                $registrations_requiring_pre_approval
370
-            );
371
-        }
372
-        if (! empty($registrations_for_free_events)) {
373
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
-        }
375
-        if (! empty($registrations_requiring_payment)) {
376
-            if ($this->checkout->amount_owing > 0) {
377
-                // autoload Line_Item_Display classes
378
-                EEH_Autoloader::register_line_item_filter_autoloaders();
379
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
-                    apply_filters(
381
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
-                        new EE_Line_Item_Filter_Collection()
383
-                    ),
384
-                    $this->checkout->cart->get_grand_total()
385
-                );
386
-                /** @var EE_Line_Item $filtered_line_item_tree */
387
-                $filtered_line_item_tree = $line_item_filter_processor->process();
388
-                EEH_Autoloader::register_line_item_display_autoloaders();
389
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
-                $subsections['payment_options'] = $this->_display_payment_options(
391
-                    $this->line_item_display->display_line_item(
392
-                        $filtered_line_item_tree,
393
-                        array('registrations' => $registrations)
394
-                    )
395
-                );
396
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
-                $this->_apply_registration_payments_to_amount_owing($registrations);
398
-            }
399
-            $no_payment_required = false;
400
-        } else {
401
-            $this->_hide_reg_step_submit_button_if_revisit();
402
-        }
403
-        $this->_save_selected_method_of_payment();
404
-
405
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
-        $subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
-
408
-        return new EE_Form_Section_Proper(
409
-            array(
410
-                'name'            => $this->reg_form_name(),
411
-                'html_id'         => $this->reg_form_name(),
412
-                'subsections'     => $subsections,
413
-                'layout_strategy' => new EE_No_Layout(),
414
-            )
415
-        );
416
-    }
417
-
418
-
419
-    /**
420
-     * add line item filters required for this reg step
421
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
-     *        payment options reg step, can apply these filters via the following: apply_filters(
425
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
-     *        filter collection by passing that instead of instantiating a new collection
427
-     *
428
-     * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
-     * @return EE_Line_Item_Filter_Collection
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws ReflectionException
433
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
-     */
438
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
-    {
440
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
-            return $line_item_filter_collection;
442
-        }
443
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
-            return $line_item_filter_collection;
445
-        }
446
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
-            return $line_item_filter_collection;
448
-        }
449
-        $line_item_filter_collection->add(
450
-            new EE_Billable_Line_Item_Filter(
451
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
-                    )
455
-                )
456
-            )
457
-        );
458
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
-        return $line_item_filter_collection;
460
-    }
461
-
462
-
463
-    /**
464
-     * remove_ejected_registrations
465
-     * if a registrant has lost their potential space at an event due to lack of payment,
466
-     * then this method removes them from the list of registrations being paid for during this request
467
-     *
468
-     * @param \EE_Registration[] $registrations
469
-     * @return EE_Registration[]
470
-     * @throws EE_Error
471
-     * @throws InvalidArgumentException
472
-     * @throws ReflectionException
473
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
-     */
478
-    public static function remove_ejected_registrations(array $registrations)
479
-    {
480
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
-            $registrations,
482
-            EE_Registry::instance()->SSN->checkout()->revisit
483
-        );
484
-        foreach ($registrations as $REG_ID => $registration) {
485
-            // has this registration lost it's space ?
486
-            if (isset($ejected_registrations[$REG_ID])) {
487
-                unset($registrations[$REG_ID]);
488
-                continue;
489
-            }
490
-        }
491
-        return $registrations;
492
-    }
493
-
494
-
495
-    /**
496
-     * find_registrations_that_lost_their_space
497
-     * If a registrant chooses an offline payment method like Invoice,
498
-     * then no space is reserved for them at the event until they fully pay fo that site
499
-     * (unless the event's default reg status is set to APPROVED)
500
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
-     * then this method will determine which registrations have lost the ability to complete the reg process.
502
-     *
503
-     * @param \EE_Registration[] $registrations
504
-     * @param bool               $revisit
505
-     * @return array
506
-     * @throws EE_Error
507
-     * @throws InvalidArgumentException
508
-     * @throws ReflectionException
509
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
-     */
514
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
-    {
516
-        // registrations per event
517
-        $event_reg_count = array();
518
-        // spaces left per event
519
-        $event_spaces_remaining = array();
520
-        // tickets left sorted by ID
521
-        $tickets_remaining = array();
522
-        // registrations that have lost their space
523
-        $ejected_registrations = array();
524
-        foreach ($registrations as $REG_ID => $registration) {
525
-            if ($registration->status_ID() === EEM_Registration::status_id_approved
526
-                || apply_filters(
527
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
-                    false,
529
-                    $registration,
530
-                    $revisit
531
-                )
532
-            ) {
533
-                continue;
534
-            }
535
-            $EVT_ID = $registration->event_ID();
536
-            $ticket = $registration->ticket();
537
-            if (! isset($tickets_remaining[$ticket->ID()])) {
538
-                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
-            }
540
-            if ($tickets_remaining[$ticket->ID()] > 0) {
541
-                if (! isset($event_reg_count[$EVT_ID])) {
542
-                    $event_reg_count[$EVT_ID] = 0;
543
-                }
544
-                $event_reg_count[$EVT_ID]++;
545
-                if (! isset($event_spaces_remaining[$EVT_ID])) {
546
-                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
-                }
548
-            }
549
-            if ($revisit
550
-                && ($tickets_remaining[$ticket->ID()] === 0
551
-                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
-                )
553
-            ) {
554
-                $ejected_registrations[$REG_ID] = $registration->event();
555
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
-                    /** @type EE_Registration_Processor $registration_processor */
557
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
-                    // at this point, we should have enough details about the registrant to consider the registration
559
-                    // NOT incomplete
560
-                    $registration_processor->manually_update_registration_status(
561
-                        $registration,
562
-                        EEM_Registration::status_id_wait_list
563
-                    );
564
-                }
565
-            }
566
-        }
567
-        return $ejected_registrations;
568
-    }
569
-
570
-
571
-    /**
572
-     * _hide_reg_step_submit_button
573
-     * removes the html for the reg step submit button
574
-     * by replacing it with an empty string via filter callback
575
-     *
576
-     * @return void
577
-     */
578
-    protected function _adjust_registration_status_if_event_old_sold()
579
-    {
580
-    }
581
-
582
-
583
-    /**
584
-     * _hide_reg_step_submit_button
585
-     * removes the html for the reg step submit button
586
-     * by replacing it with an empty string via filter callback
587
-     *
588
-     * @return void
589
-     */
590
-    protected function _hide_reg_step_submit_button_if_revisit()
591
-    {
592
-        if ($this->checkout->revisit) {
593
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
-        }
595
-    }
596
-
597
-
598
-    /**
599
-     * sold_out_events
600
-     * displays notices regarding events that have sold out since hte registrant first signed up
601
-     *
602
-     * @param \EE_Event[] $sold_out_events_array
603
-     * @return \EE_Form_Section_Proper
604
-     * @throws \EE_Error
605
-     */
606
-    private function _sold_out_events($sold_out_events_array = array())
607
-    {
608
-        // set some defaults
609
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
610
-        $sold_out_events                            = '';
611
-        foreach ($sold_out_events_array as $sold_out_event) {
612
-            $sold_out_events .= EEH_HTML::li(
613
-                EEH_HTML::span(
614
-                    '  ' . $sold_out_event->name(),
615
-                    '',
616
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
-                )
618
-            );
619
-        }
620
-        return new EE_Form_Section_Proper(
621
-            array(
622
-                'layout_strategy' => new EE_Template_Layout(
623
-                    array(
624
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
625
-                                                  . $this->_slug
626
-                                                  . DS
627
-                                                  . 'sold_out_events.template.php',
628
-                        'template_args'        => apply_filters(
629
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
-                            array(
631
-                                'sold_out_events'     => $sold_out_events,
632
-                                'sold_out_events_msg' => apply_filters(
633
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
-                                    sprintf(
635
-                                        esc_html__(
636
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
-                                            'event_espresso'
638
-                                        ),
639
-                                        '<strong>',
640
-                                        '</strong>',
641
-                                        '<br />'
642
-                                    )
643
-                                ),
644
-                            )
645
-                        ),
646
-                    )
647
-                ),
648
-            )
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * _insufficient_spaces_available
655
-     * displays notices regarding events that do not have enough remaining spaces
656
-     * to satisfy the current number of registrations looking to pay
657
-     *
658
-     * @param \EE_Event[] $insufficient_spaces_events_array
659
-     * @return \EE_Form_Section_Proper
660
-     * @throws \EE_Error
661
-     */
662
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
-    {
664
-        // set some defaults
665
-        $this->checkout->selected_method_of_payment = 'invoice';
666
-        $insufficient_space_events                  = '';
667
-        foreach ($insufficient_spaces_events_array as $event) {
668
-            if ($event instanceof EE_Event) {
669
-                $insufficient_space_events .= EEH_HTML::li(
670
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
-                );
672
-            }
673
-        }
674
-        return new EE_Form_Section_Proper(
675
-            array(
676
-                'subsections'     => array(
677
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
-                ),
680
-                'layout_strategy' => new EE_Template_Layout(
681
-                    array(
682
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
683
-                                                  . $this->_slug
684
-                                                  . DS
685
-                                                  . 'sold_out_events.template.php',
686
-                        'template_args'        => apply_filters(
687
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
-                            array(
689
-                                'sold_out_events'     => $insufficient_space_events,
690
-                                'sold_out_events_msg' => apply_filters(
691
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
-                                    esc_html__(
693
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
-                                        'event_espresso'
695
-                                    )
696
-                                ),
697
-                            )
698
-                        ),
699
-                    )
700
-                ),
701
-            )
702
-        );
703
-    }
704
-
705
-
706
-    /**
707
-     * registrations_requiring_pre_approval
708
-     *
709
-     * @param array $registrations_requiring_pre_approval
710
-     * @return EE_Form_Section_Proper
711
-     * @throws EE_Error
712
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
-     */
714
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
-    {
716
-        $events_requiring_pre_approval = '';
717
-        foreach ($registrations_requiring_pre_approval as $registration) {
718
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
-                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
-                    EEH_HTML::span(
721
-                        '',
722
-                        '',
723
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
-                    )
725
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
-                );
727
-            }
728
-        }
729
-        return new EE_Form_Section_Proper(
730
-            array(
731
-                'layout_strategy' => new EE_Template_Layout(
732
-                    array(
733
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
734
-                                                  . $this->_slug
735
-                                                  . DS
736
-                                                  . 'events_requiring_pre_approval.template.php', // layout_template
737
-                        'template_args'        => apply_filters(
738
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
-                            array(
740
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
-                                'events_requiring_pre_approval_msg' => apply_filters(
742
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
-                                    esc_html__(
744
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
-                                        'event_espresso'
746
-                                    )
747
-                                ),
748
-                            )
749
-                        ),
750
-                    )
751
-                ),
752
-            )
753
-        );
754
-    }
755
-
756
-
757
-    /**
758
-     * _no_payment_required
759
-     *
760
-     * @param \EE_Event[] $registrations_for_free_events
761
-     * @return \EE_Form_Section_Proper
762
-     * @throws \EE_Error
763
-     */
764
-    private function _no_payment_required($registrations_for_free_events = array())
765
-    {
766
-        // set some defaults
767
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
768
-        // generate no_payment_required form
769
-        return new EE_Form_Section_Proper(
770
-            array(
771
-                'layout_strategy' => new EE_Template_Layout(
772
-                    array(
773
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
774
-                                                  . $this->_slug
775
-                                                  . DS
776
-                                                  . 'no_payment_required.template.php', // layout_template
777
-                        'template_args'        => apply_filters(
778
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
-                            array(
780
-                                'revisit'                       => $this->checkout->revisit,
781
-                                'registrations'                 => array(),
782
-                                'ticket_count'                  => array(),
783
-                                'registrations_for_free_events' => $registrations_for_free_events,
784
-                                'no_payment_required_msg'       => EEH_HTML::p(
785
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
-                                ),
787
-                            )
788
-                        ),
789
-                    )
790
-                ),
791
-            )
792
-        );
793
-    }
794
-
795
-
796
-    /**
797
-     * _display_payment_options
798
-     *
799
-     * @param string $transaction_details
800
-     * @return EE_Form_Section_Proper
801
-     * @throws EE_Error
802
-     * @throws InvalidArgumentException
803
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
-     */
806
-    private function _display_payment_options($transaction_details = '')
807
-    {
808
-        // has method_of_payment been set by no-js user?
809
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
-        // build payment options form
811
-        return apply_filters(
812
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
-            new EE_Form_Section_Proper(
814
-                array(
815
-                    'subsections'     => array(
816
-                        'before_payment_options' => apply_filters(
817
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
-                            new EE_Form_Section_Proper(
819
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
-                            )
821
-                        ),
822
-                        'payment_options'        => $this->_setup_payment_options(),
823
-                        'after_payment_options'  => apply_filters(
824
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
-                            new EE_Form_Section_Proper(
826
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
-                            )
828
-                        ),
829
-                    ),
830
-                    'layout_strategy' => new EE_Template_Layout(
831
-                        array(
832
-                            'layout_template_file' => $this->_template,
833
-                            'template_args'        => apply_filters(
834
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
-                                array(
836
-                                    'reg_count'                 => $this->line_item_display->total_items(),
837
-                                    'transaction_details'       => $transaction_details,
838
-                                    'available_payment_methods' => array(),
839
-                                )
840
-                            ),
841
-                        )
842
-                    ),
843
-                )
844
-            )
845
-        );
846
-    }
847
-
848
-
849
-    /**
850
-     * _extra_hidden_inputs
851
-     *
852
-     * @param bool $no_payment_required
853
-     * @return \EE_Form_Section_Proper
854
-     * @throws \EE_Error
855
-     */
856
-    private function _extra_hidden_inputs($no_payment_required = true)
857
-    {
858
-        return new EE_Form_Section_Proper(
859
-            array(
860
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
-                'subsections'     => array(
863
-                    'spco_no_payment_required' => new EE_Hidden_Input(
864
-                        array(
865
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
866
-                            'html_name'              => 'spco_no_payment_required',
867
-                            'html_id'                => 'spco-no-payment-required-payment_options',
868
-                            'default'                => $no_payment_required,
869
-                        )
870
-                    ),
871
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
-                        array(
873
-                            'normalization_strategy' => new EE_Int_Normalization(),
874
-                            'html_name'              => 'spco_transaction_id',
875
-                            'html_id'                => 'spco-transaction-id',
876
-                            'default'                => $this->checkout->transaction->ID(),
877
-                        )
878
-                    ),
879
-                ),
880
-            )
881
-        );
882
-    }
883
-
884
-
885
-    /**
886
-     *    _apply_registration_payments_to_amount_owing
887
-     *
888
-     * @access protected
889
-     * @param array $registrations
890
-     * @throws EE_Error
891
-     */
892
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
-    {
894
-        $payments = array();
895
-        foreach ($registrations as $registration) {
896
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
-                $payments += $registration->registration_payments();
898
-            }
899
-        }
900
-        if (! empty($payments)) {
901
-            foreach ($payments as $payment) {
902
-                if ($payment instanceof EE_Registration_Payment) {
903
-                    $this->checkout->amount_owing -= $payment->amount();
904
-                }
905
-            }
906
-        }
907
-    }
908
-
909
-
910
-    /**
911
-     *    _reset_selected_method_of_payment
912
-     *
913
-     * @access    private
914
-     * @param    bool $force_reset
915
-     * @return void
916
-     * @throws InvalidArgumentException
917
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
-     */
920
-    private function _reset_selected_method_of_payment($force_reset = false)
921
-    {
922
-        $reset_payment_method = $force_reset
923
-            ? true
924
-            : sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
-        if ($reset_payment_method) {
926
-            $this->checkout->selected_method_of_payment = null;
927
-            $this->checkout->payment_method             = null;
928
-            $this->checkout->billing_form               = null;
929
-            $this->_save_selected_method_of_payment();
930
-        }
931
-    }
932
-
933
-
934
-    /**
935
-     * _save_selected_method_of_payment
936
-     * stores the selected_method_of_payment in the session
937
-     * so that it's available for all subsequent requests including AJAX
938
-     *
939
-     * @access        private
940
-     * @param string $selected_method_of_payment
941
-     * @return void
942
-     * @throws InvalidArgumentException
943
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
-     */
946
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
-    {
948
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
949
-            ? $selected_method_of_payment
950
-            : $this->checkout->selected_method_of_payment;
951
-        EE_Registry::instance()->SSN->set_session_data(
952
-            array('selected_method_of_payment' => $selected_method_of_payment)
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * _setup_payment_options
959
-     *
960
-     * @return EE_Form_Section_Proper
961
-     * @throws EE_Error
962
-     * @throws InvalidArgumentException
963
-     * @throws ReflectionException
964
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
-     */
967
-    public function _setup_payment_options()
968
-    {
969
-        // load payment method classes
970
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
-        if (empty($this->checkout->available_payment_methods)) {
972
-            EE_Error::add_error(
973
-                apply_filters(
974
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
-                    sprintf(
976
-                        esc_html__(
977
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
-                            'event_espresso'
979
-                        ),
980
-                        '<br>',
981
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
982
-                    )
983
-                ),
984
-                __FILE__,
985
-                __FUNCTION__,
986
-                __LINE__
987
-            );
988
-        }
989
-        // switch up header depending on number of available payment methods
990
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
-            ? apply_filters(
992
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
-            )
995
-            : apply_filters(
996
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
-                esc_html__('Method of Payment', 'event_espresso')
998
-            );
999
-        $available_payment_methods = array(
1000
-            // display the "Payment Method" header
1001
-            'payment_method_header' => new EE_Form_Section_HTML(
1002
-                EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
-            ),
1004
-        );
1005
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
-        $available_payment_method_options = array();
1007
-        $default_payment_method_option    = array();
1008
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
-        $payment_methods_billing_info = array(
1010
-            new EE_Form_Section_HTML(
1011
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
-            ),
1013
-        );
1014
-        // loop through payment methods
1015
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
-            if ($payment_method instanceof EE_Payment_Method) {
1017
-                $payment_method_button = EEH_HTML::img(
1018
-                    $payment_method->button_url(),
1019
-                    $payment_method->name(),
1020
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
-                    'spco-payment-method-btn-img'
1022
-                );
1023
-                // check if any payment methods are set as default
1024
-                // if payment method is already selected OR nothing is selected and this payment method should be
1025
-                // open_by_default
1026
-                if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
-                ) {
1029
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1030
-                    $this->_save_selected_method_of_payment();
1031
-                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
-                } else {
1033
-                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
-                }
1035
-                $payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
-                    $payment_method
1037
-                );
1038
-            }
1039
-        }
1040
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
-        // of PMs
1042
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
-        // now generate the actual form  inputs
1044
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
-            $available_payment_method_options
1046
-        );
1047
-        $available_payment_methods                              += $payment_methods_billing_info;
1048
-        // build the available payment methods form
1049
-        return new EE_Form_Section_Proper(
1050
-            array(
1051
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1052
-                'subsections'     => $available_payment_methods,
1053
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
-            )
1055
-        );
1056
-    }
1057
-
1058
-
1059
-    /**
1060
-     * _get_available_payment_methods
1061
-     *
1062
-     * @return EE_Payment_Method[]
1063
-     * @throws EE_Error
1064
-     * @throws InvalidArgumentException
1065
-     * @throws ReflectionException
1066
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
-     */
1069
-    protected function _get_available_payment_methods()
1070
-    {
1071
-        if (! empty($this->checkout->available_payment_methods)) {
1072
-            return $this->checkout->available_payment_methods;
1073
-        }
1074
-        $available_payment_methods = array();
1075
-        // load EEM_Payment_Method
1076
-        EE_Registry::instance()->load_model('Payment_Method');
1077
-        /** @type EEM_Payment_Method $EEM_Payment_Method */
1078
-        $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
-        // get all active payment methods
1080
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
-            $this->checkout->transaction,
1082
-            EEM_Payment_Method::scope_cart
1083
-        );
1084
-        foreach ($payment_methods as $payment_method) {
1085
-            if ($payment_method instanceof EE_Payment_Method) {
1086
-                $available_payment_methods[$payment_method->slug()] = $payment_method;
1087
-            }
1088
-        }
1089
-        return $available_payment_methods;
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     *    _available_payment_method_inputs
1095
-     *
1096
-     * @access    private
1097
-     * @param    array $available_payment_method_options
1098
-     * @return    \EE_Form_Section_Proper
1099
-     */
1100
-    private function _available_payment_method_inputs($available_payment_method_options = array())
1101
-    {
1102
-        // generate inputs
1103
-        return new EE_Form_Section_Proper(
1104
-            array(
1105
-                'html_id'         => 'ee-available-payment-method-inputs',
1106
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
-                'subsections'     => array(
1108
-                    '' => new EE_Radio_Button_Input(
1109
-                        $available_payment_method_options,
1110
-                        array(
1111
-                            'html_name'          => 'selected_method_of_payment',
1112
-                            'html_class'         => 'spco-payment-method',
1113
-                            'default'            => $this->checkout->selected_method_of_payment,
1114
-                            'label_size'         => 11,
1115
-                            'enforce_label_size' => true,
1116
-                        )
1117
-                    ),
1118
-                ),
1119
-            )
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    /**
1125
-     *    _payment_method_billing_info
1126
-     *
1127
-     * @access    private
1128
-     * @param    EE_Payment_Method $payment_method
1129
-     * @return EE_Form_Section_Proper
1130
-     * @throws EE_Error
1131
-     * @throws InvalidArgumentException
1132
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
-     */
1135
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
-    {
1137
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
-            ? true
1139
-            : false;
1140
-        // generate the billing form for payment method
1141
-        $billing_form                 = $currently_selected
1142
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1143
-            : new EE_Form_Section_HTML();
1144
-        $this->checkout->billing_form = $currently_selected
1145
-            ? $billing_form
1146
-            : $this->checkout->billing_form;
1147
-        // it's all in the details
1148
-        $info_html = EEH_HTML::h3(
1149
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1150
-            '',
1151
-            'spco-payment-method-hdr'
1152
-        );
1153
-        // add some info regarding the step, either from what's saved in the admin,
1154
-        // or a default string depending on whether the PM has a billing form or not
1155
-        if ($payment_method->description()) {
1156
-            $payment_method_info = $payment_method->description();
1157
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
-            $payment_method_info = sprintf(
1159
-                esc_html__(
1160
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
-                    'event_espresso'
1162
-                ),
1163
-                $this->submit_button_text()
1164
-            );
1165
-        } else {
1166
-            $payment_method_info = sprintf(
1167
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
-                $this->submit_button_text()
1169
-            );
1170
-        }
1171
-        $info_html .= EEH_HTML::p(
1172
-            apply_filters(
1173
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
-                $payment_method_info
1175
-            ),
1176
-            '',
1177
-            'spco-payment-method-desc ee-attention'
1178
-        );
1179
-        return new EE_Form_Section_Proper(
1180
-            array(
1181
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
-                'html_class'      => 'spco-payment-method-info-dv',
1183
-                // only display the selected or default PM
1184
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1185
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
-                'subsections'     => array(
1187
-                    'info'         => new EE_Form_Section_HTML($info_html),
1188
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
-                ),
1190
-            )
1191
-        );
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * get_billing_form_html_for_payment_method
1197
-     *
1198
-     * @access public
1199
-     * @return string
1200
-     * @throws EE_Error
1201
-     * @throws InvalidArgumentException
1202
-     * @throws ReflectionException
1203
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
-     */
1206
-    public function get_billing_form_html_for_payment_method()
1207
-    {
1208
-        // how have they chosen to pay?
1209
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
-        $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
-            return false;
1213
-        }
1214
-        if (apply_filters(
1215
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
-            false
1217
-        )) {
1218
-            EE_Error::add_success(
1219
-                apply_filters(
1220
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
-                    sprintf(
1222
-                        esc_html__(
1223
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
-                            'event_espresso'
1225
-                        ),
1226
-                        $this->checkout->payment_method->name()
1227
-                    )
1228
-                )
1229
-            );
1230
-        }
1231
-        // now generate billing form for selected method of payment
1232
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
-        // fill form with attendee info if applicable
1234
-        if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
-            && $this->checkout->transaction_has_primary_registrant()
1236
-        ) {
1237
-            $payment_method_billing_form->populate_from_attendee(
1238
-                $this->checkout->transaction->primary_registration()->attendee()
1239
-            );
1240
-        }
1241
-        // and debug content
1242
-        if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
-        ) {
1245
-            $payment_method_billing_form =
1246
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
-                    $payment_method_billing_form
1248
-                );
1249
-        }
1250
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
-            ? $payment_method_billing_form->get_html()
1252
-            : '';
1253
-        $this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
-        // localize validation rules for main form
1255
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1256
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
-        return true;
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * _get_billing_form_for_payment_method
1263
-     *
1264
-     * @access private
1265
-     * @param EE_Payment_Method $payment_method
1266
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
-     * @throws EE_Error
1268
-     * @throws InvalidArgumentException
1269
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
-     */
1272
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
-    {
1274
-        $billing_form = $payment_method->type_obj()->billing_form(
1275
-            $this->checkout->transaction,
1276
-            array('amount_owing' => $this->checkout->amount_owing)
1277
-        );
1278
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1279
-            if (apply_filters(
1280
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
-                false
1282
-            )
1283
-                && EE_Registry::instance()->REQ->is_set('payment_method')
1284
-            ) {
1285
-                EE_Error::add_success(
1286
-                    apply_filters(
1287
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
-                        sprintf(
1289
-                            esc_html__(
1290
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
-                                'event_espresso'
1292
-                            ),
1293
-                            $payment_method->name()
1294
-                        )
1295
-                    )
1296
-                );
1297
-            }
1298
-            return apply_filters(
1299
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
-                $billing_form,
1301
-                $payment_method
1302
-            );
1303
-        }
1304
-        // no actual billing form, so return empty HTML form section
1305
-        return new EE_Form_Section_HTML();
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _get_selected_method_of_payment
1311
-     *
1312
-     * @access private
1313
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
-     *                          is not found in the incoming request
1315
-     * @param string  $request_param
1316
-     * @return NULL|string
1317
-     * @throws EE_Error
1318
-     * @throws InvalidArgumentException
1319
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
-     */
1322
-    private function _get_selected_method_of_payment(
1323
-        $required = false,
1324
-        $request_param = 'selected_method_of_payment'
1325
-    ) {
1326
-        // is selected_method_of_payment set in the request ?
1327
-        $selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
-        if ($selected_method_of_payment) {
1329
-            // sanitize it
1330
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1331
-                ? array_shift($selected_method_of_payment)
1332
-                : $selected_method_of_payment;
1333
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
-            // store it in the session so that it's available for all subsequent requests including AJAX
1335
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1336
-        } else {
1337
-            // or is is set in the session ?
1338
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
-                'selected_method_of_payment'
1340
-            );
1341
-        }
1342
-        // do ya really really gotta have it?
1343
-        if (empty($selected_method_of_payment) && $required) {
1344
-            EE_Error::add_error(
1345
-                sprintf(
1346
-                    esc_html__(
1347
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
-                        'event_espresso'
1349
-                    ),
1350
-                    '<br/>',
1351
-                    '<br/>',
1352
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
-                ),
1354
-                __FILE__,
1355
-                __FUNCTION__,
1356
-                __LINE__
1357
-            );
1358
-            return null;
1359
-        }
1360
-        return $selected_method_of_payment;
1361
-    }
1362
-
1363
-
1364
-
1365
-
1366
-
1367
-
1368
-    /********************************************************************************************************/
1369
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
-    /********************************************************************************************************/
1371
-    /**
1372
-     * switch_payment_method
1373
-     *
1374
-     * @access public
1375
-     * @return string
1376
-     * @throws EE_Error
1377
-     * @throws InvalidArgumentException
1378
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
-     */
1381
-    public function switch_payment_method()
1382
-    {
1383
-        if (! $this->_verify_payment_method_is_set()) {
1384
-            return false;
1385
-        }
1386
-        if (apply_filters(
1387
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
-            false
1389
-        )) {
1390
-            EE_Error::add_success(
1391
-                apply_filters(
1392
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
-                    sprintf(
1394
-                        esc_html__(
1395
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
-                            'event_espresso'
1397
-                        ),
1398
-                        $this->checkout->payment_method->name()
1399
-                    )
1400
-                )
1401
-            );
1402
-        }
1403
-        // generate billing form for selected method of payment if it hasn't been done already
1404
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
-                $this->checkout->payment_method
1407
-            );
1408
-        }
1409
-        // fill form with attendee info if applicable
1410
-        if (apply_filters(
1411
-            'FHEE__populate_billing_form_fields_from_attendee',
1412
-            (
1413
-                $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
-                && $this->checkout->transaction_has_primary_registrant()
1415
-            ),
1416
-            $this->checkout->billing_form,
1417
-            $this->checkout->transaction
1418
-        )
1419
-        ) {
1420
-            $this->checkout->billing_form->populate_from_attendee(
1421
-                $this->checkout->transaction->primary_registration()->attendee()
1422
-            );
1423
-        }
1424
-        // and debug content
1425
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
-        ) {
1428
-            $this->checkout->billing_form =
1429
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
-                    $this->checkout->billing_form
1431
-                );
1432
-        }
1433
-        // get html and validation rules for form
1434
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
-            $this->checkout->json_response->set_return_data(
1436
-                array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
-            );
1438
-            // localize validation rules for main form
1439
-            $this->checkout->billing_form->localize_validation_rules(true);
1440
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
-        } else {
1442
-            $this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
-        }
1444
-        //prevents advancement to next step
1445
-        $this->checkout->continue_reg = false;
1446
-        return true;
1447
-    }
1448
-
1449
-
1450
-    /**
1451
-     * _verify_payment_method_is_set
1452
-     *
1453
-     * @return bool
1454
-     * @throws EE_Error
1455
-     * @throws InvalidArgumentException
1456
-     * @throws ReflectionException
1457
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
-     */
1460
-    protected function _verify_payment_method_is_set()
1461
-    {
1462
-        // generate billing form for selected method of payment if it hasn't been done already
1463
-        if (empty($this->checkout->selected_method_of_payment)) {
1464
-            // how have they chosen to pay?
1465
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
-        } else {
1467
-            // choose your own adventure based on method_of_payment
1468
-            switch ($this->checkout->selected_method_of_payment) {
1469
-                case 'events_sold_out' :
1470
-                    EE_Error::add_attention(
1471
-                        apply_filters(
1472
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
-                            esc_html__(
1474
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
-                                'event_espresso'
1476
-                            )
1477
-                        ),
1478
-                        __FILE__, __FUNCTION__, __LINE__
1479
-                    );
1480
-                    return false;
1481
-                    break;
1482
-                case 'payments_closed' :
1483
-                    EE_Error::add_attention(
1484
-                        apply_filters(
1485
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
-                            esc_html__(
1487
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
-                                'event_espresso'
1489
-                            )
1490
-                        ),
1491
-                        __FILE__, __FUNCTION__, __LINE__
1492
-                    );
1493
-                    return false;
1494
-                    break;
1495
-                case 'no_payment_required' :
1496
-                    EE_Error::add_attention(
1497
-                        apply_filters(
1498
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
-                            esc_html__(
1500
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
-                                'event_espresso'
1502
-                            )
1503
-                        ),
1504
-                        __FILE__, __FUNCTION__, __LINE__
1505
-                    );
1506
-                    return false;
1507
-                    break;
1508
-                default:
1509
-            }
1510
-        }
1511
-        // verify payment method
1512
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
-            // get payment method for selected method of payment
1514
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
-        }
1516
-        return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
-    }
1518
-
1519
-
1520
-
1521
-    /********************************************************************************************************/
1522
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1523
-    /********************************************************************************************************/
1524
-    /**
1525
-     * save_payer_details_via_ajax
1526
-     *
1527
-     * @return void
1528
-     * @throws EE_Error
1529
-     * @throws InvalidArgumentException
1530
-     * @throws ReflectionException
1531
-     * @throws RuntimeException
1532
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
-     */
1535
-    public function save_payer_details_via_ajax()
1536
-    {
1537
-        if (! $this->_verify_payment_method_is_set()) {
1538
-            return;
1539
-        }
1540
-        // generate billing form for selected method of payment if it hasn't been done already
1541
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
-                $this->checkout->payment_method
1544
-            );
1545
-        }
1546
-        // generate primary attendee from payer info if applicable
1547
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1548
-            $attendee = $this->_create_attendee_from_request_data();
1549
-            if ($attendee instanceof EE_Attendee) {
1550
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1551
-                    if ($registration->is_primary_registrant()) {
1552
-                        $this->checkout->primary_attendee_obj = $attendee;
1553
-                        $registration->_add_relation_to($attendee, 'Attendee');
1554
-                        $registration->set_attendee_id($attendee->ID());
1555
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1556
-                    }
1557
-                }
1558
-            }
1559
-        }
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * create_attendee_from_request_data
1565
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
-     *
1567
-     * @return EE_Attendee
1568
-     * @throws EE_Error
1569
-     * @throws InvalidArgumentException
1570
-     * @throws ReflectionException
1571
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
-     */
1574
-    protected function _create_attendee_from_request_data()
1575
-    {
1576
-        // get State ID
1577
-        $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
-        if (! empty($STA_ID)) {
1579
-            // can we get state object from name ?
1580
-            EE_Registry::instance()->load_model('State');
1581
-            $state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
-        }
1584
-        // get Country ISO
1585
-        $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
-        if (! empty($CNT_ISO)) {
1587
-            // can we get country object from name ?
1588
-            EE_Registry::instance()->load_model('Country');
1589
-            $country = EEM_Country::instance()->get_col(
1590
-                array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
-                'CNT_ISO'
1592
-            );
1593
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
-        }
1595
-        // grab attendee data
1596
-        $attendee_data = array(
1597
-            'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
-            'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
-            'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
-            'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
-            'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
-            'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
-            'STA_ID'       => $STA_ID,
1604
-            'CNT_ISO'      => $CNT_ISO,
1605
-            'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
-            'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
-        );
1608
-        // validate the email address since it is the most important piece of info
1609
-        if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
-            EE_Error::add_error(
1611
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
-                __FILE__,
1613
-                __FUNCTION__,
1614
-                __LINE__
1615
-            );
1616
-        }
1617
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
-        // AND email address
1619
-        if (! empty($attendee_data['ATT_fname'])
1620
-            && ! empty($attendee_data['ATT_lname'])
1621
-            && ! empty($attendee_data['ATT_email'])
1622
-        ) {
1623
-            $existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
-                array(
1625
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1626
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1627
-                    'ATT_email' => $attendee_data['ATT_email'],
1628
-                )
1629
-            );
1630
-            if ($existing_attendee instanceof EE_Attendee) {
1631
-                return $existing_attendee;
1632
-            }
1633
-        }
1634
-        // no existing attendee? kk let's create a new one
1635
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
-        // don't exist
1637
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
-            ? $attendee_data['ATT_fname']
1639
-            : $attendee_data['ATT_email'];
1640
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
-            ? $attendee_data['ATT_lname']
1642
-            : $attendee_data['ATT_email'];
1643
-        return EE_Attendee::new_instance($attendee_data);
1644
-    }
1645
-
1646
-
1647
-
1648
-    /********************************************************************************************************/
1649
-    /****************************************  PROCESS REG STEP  *****************************************/
1650
-    /********************************************************************************************************/
1651
-    /**
1652
-     * process_reg_step
1653
-     *
1654
-     * @return bool
1655
-     * @throws EE_Error
1656
-     * @throws InvalidArgumentException
1657
-     * @throws ReflectionException
1658
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
-     */
1663
-    public function process_reg_step()
1664
-    {
1665
-        // how have they chosen to pay?
1666
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
-            ? 'no_payment_required'
1668
-            : $this->_get_selected_method_of_payment(true);
1669
-        // choose your own adventure based on method_of_payment
1670
-        switch ($this->checkout->selected_method_of_payment) {
1671
-
1672
-            case 'events_sold_out' :
1673
-                $this->checkout->redirect     = true;
1674
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
-                // mark this reg step as completed
1677
-                $this->set_completed();
1678
-                return false;
1679
-                break;
1680
-
1681
-            case 'payments_closed' :
1682
-                if (apply_filters(
1683
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
-                    false
1685
-                )) {
1686
-                    EE_Error::add_success(
1687
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1688
-                        __FILE__,
1689
-                        __FUNCTION__,
1690
-                        __LINE__
1691
-                    );
1692
-                }
1693
-                // mark this reg step as completed
1694
-                $this->set_completed();
1695
-                return true;
1696
-                break;
1697
-
1698
-            case 'no_payment_required' :
1699
-                if (apply_filters(
1700
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
-                    false
1702
-                )) {
1703
-                    EE_Error::add_success(
1704
-                        esc_html__('no payment required.', 'event_espresso'),
1705
-                        __FILE__,
1706
-                        __FUNCTION__,
1707
-                        __LINE__
1708
-                    );
1709
-                }
1710
-                // mark this reg step as completed
1711
-                $this->set_completed();
1712
-                return true;
1713
-                break;
1714
-
1715
-            default:
1716
-                $registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
-                );
1719
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
-                    $registrations,
1721
-                    EE_Registry::instance()->SSN->checkout()->revisit
1722
-                );
1723
-                // calculate difference between the two arrays
1724
-                $registrations = array_diff($registrations, $ejected_registrations);
1725
-                if (empty($registrations)) {
1726
-                    $this->_redirect_because_event_sold_out();
1727
-                    return false;
1728
-                }
1729
-                $payment_successful = $this->_process_payment();
1730
-                if ($payment_successful) {
1731
-                    $this->checkout->continue_reg = true;
1732
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1733
-                } else {
1734
-                    $this->checkout->continue_reg = false;
1735
-                }
1736
-                return $payment_successful;
1737
-        }
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * _redirect_because_event_sold_out
1743
-     *
1744
-     * @access protected
1745
-     * @return void
1746
-     */
1747
-    protected function _redirect_because_event_sold_out()
1748
-    {
1749
-        $this->checkout->continue_reg = false;
1750
-        // set redirect URL
1751
-        $this->checkout->redirect_url = add_query_arg(
1752
-            array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
-            $this->checkout->current_step->reg_step_url()
1754
-        );
1755
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * _maybe_set_completed
1761
-     *
1762
-     * @access protected
1763
-     * @param \EE_Payment_Method $payment_method
1764
-     * @return void
1765
-     * @throws \EE_Error
1766
-     */
1767
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
-    {
1769
-        switch ($payment_method->type_obj()->payment_occurs()) {
1770
-            case EE_PMT_Base::offsite :
1771
-                break;
1772
-            case EE_PMT_Base::onsite :
1773
-            case EE_PMT_Base::offline :
1774
-                // mark this reg step as completed
1775
-                $this->set_completed();
1776
-                break;
1777
-        }
1778
-    }
1779
-
1780
-
1781
-    /**
1782
-     *    update_reg_step
1783
-     *    this is the final step after a user  revisits the site to retry a payment
1784
-     *
1785
-     * @return bool
1786
-     * @throws EE_Error
1787
-     * @throws InvalidArgumentException
1788
-     * @throws ReflectionException
1789
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
-     */
1794
-    public function update_reg_step()
1795
-    {
1796
-        $success = true;
1797
-        // if payment required
1798
-        if ($this->checkout->transaction->total() > 0) {
1799
-            do_action(
1800
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
-                $this->checkout->transaction
1802
-            );
1803
-            // attempt payment via payment method
1804
-            $success = $this->process_reg_step();
1805
-        }
1806
-        if ($success && ! $this->checkout->redirect) {
1807
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
-                $this->checkout->transaction->ID()
1809
-            );
1810
-            // set return URL
1811
-            $this->checkout->redirect_url = add_query_arg(
1812
-                array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
-                $this->checkout->thank_you_page_url
1814
-            );
1815
-        }
1816
-        return $success;
1817
-    }
1818
-
1819
-
1820
-    /**
1821
-     *    _process_payment
1822
-     *
1823
-     * @access private
1824
-     * @return bool
1825
-     * @throws EE_Error
1826
-     * @throws InvalidArgumentException
1827
-     * @throws ReflectionException
1828
-     * @throws RuntimeException
1829
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
-     */
1832
-    private function _process_payment()
1833
-    {
1834
-        // basically confirm that the event hasn't sold out since they hit the page
1835
-        if (! $this->_last_second_ticket_verifications()) {
1836
-            return false;
1837
-        }
1838
-        // ya gotta make a choice man
1839
-        if (empty($this->checkout->selected_method_of_payment)) {
1840
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1841
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
-            );
1843
-            return false;
1844
-        }
1845
-        // get EE_Payment_Method object
1846
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
-            return false;
1848
-        }
1849
-        // setup billing form
1850
-        if ($this->checkout->payment_method->is_on_site()) {
1851
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
-                $this->checkout->payment_method
1853
-            );
1854
-            // bad billing form ?
1855
-            if (! $this->_billing_form_is_valid()) {
1856
-                return false;
1857
-            }
1858
-        }
1859
-        // ensure primary registrant has been fully processed
1860
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
-            return false;
1862
-        }
1863
-        // if session is close to expiring (under 10 minutes by default)
1864
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
-            // add some time to session expiration so that payment can be completed
1866
-            EE_Registry::instance()->SSN->extend_expiration();
1867
-        }
1868
-        /** @type EE_Transaction_Processor $transaction_processor */
1869
-        //$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
-        // for events with a default reg status of Approved
1872
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
-        // );
1875
-        // attempt payment
1876
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1877
-        // process results
1878
-        $payment = $this->_validate_payment($payment);
1879
-        $payment = $this->_post_payment_processing($payment);
1880
-        // verify payment
1881
-        if ($payment instanceof EE_Payment) {
1882
-            // store that for later
1883
-            $this->checkout->payment = $payment;
1884
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
-            $this->checkout->transaction->toggle_failed_transaction_status();
1886
-            $payment_status = $payment->status();
1887
-            if (
1888
-                $payment_status === EEM_Payment::status_id_approved
1889
-                || $payment_status === EEM_Payment::status_id_pending
1890
-            ) {
1891
-                return true;
1892
-            } else {
1893
-                return false;
1894
-            }
1895
-        } else if ($payment === true) {
1896
-            // please note that offline payment methods will NOT make a payment,
1897
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
-            $this->checkout->payment = $payment;
1899
-            return true;
1900
-        }
1901
-        // where's my money?
1902
-        return false;
1903
-    }
1904
-
1905
-
1906
-    /**
1907
-     * _last_second_ticket_verifications
1908
-     *
1909
-     * @access public
1910
-     * @return bool
1911
-     * @throws EE_Error
1912
-     */
1913
-    protected function _last_second_ticket_verifications()
1914
-    {
1915
-        // don't bother re-validating if not a return visit
1916
-        if (! $this->checkout->revisit) {
1917
-            return true;
1918
-        }
1919
-        $registrations = $this->checkout->transaction->registrations();
1920
-        if (empty($registrations)) {
1921
-            return false;
1922
-        }
1923
-        foreach ($registrations as $registration) {
1924
-            if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1925
-                $event = $registration->event_obj();
1926
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
-                    EE_Error::add_error(
1928
-                        apply_filters(
1929
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
-                            sprintf(
1931
-                                esc_html__(
1932
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
-                                    'event_espresso'
1934
-                                ),
1935
-                                $event->name()
1936
-                            )
1937
-                        ),
1938
-                        __FILE__,
1939
-                        __FUNCTION__,
1940
-                        __LINE__
1941
-                    );
1942
-                    return false;
1943
-                }
1944
-            }
1945
-        }
1946
-        return true;
1947
-    }
1948
-
1949
-
1950
-    /**
1951
-     * redirect_form
1952
-     *
1953
-     * @access public
1954
-     * @return bool
1955
-     * @throws EE_Error
1956
-     * @throws InvalidArgumentException
1957
-     * @throws ReflectionException
1958
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
-     */
1961
-    public function redirect_form()
1962
-    {
1963
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1964
-            $this->_get_payment_method_for_selected_method_of_payment()
1965
-        );
1966
-        $html                        = $payment_method_billing_info->get_html();
1967
-        $html                        .= $this->checkout->redirect_form;
1968
-        EE_Registry::instance()->REQ->add_output($html);
1969
-        return true;
1970
-    }
1971
-
1972
-
1973
-    /**
1974
-     * _billing_form_is_valid
1975
-     *
1976
-     * @access private
1977
-     * @return bool
1978
-     * @throws \EE_Error
1979
-     */
1980
-    private function _billing_form_is_valid()
1981
-    {
1982
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
-            return true;
1984
-        }
1985
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
-            if ($this->checkout->billing_form->was_submitted()) {
1987
-                $this->checkout->billing_form->receive_form_submission();
1988
-                if ($this->checkout->billing_form->is_valid()) {
1989
-                    return true;
1990
-                }
1991
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
-                $error_strings     = array();
1993
-                foreach ($validation_errors as $validation_error) {
1994
-                    if ($validation_error instanceof EE_Validation_Error) {
1995
-                        $form_section = $validation_error->get_form_section();
1996
-                        if ($form_section instanceof EE_Form_Input_Base) {
1997
-                            $label = $form_section->html_label_text();
1998
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
1999
-                            $label = $form_section->name();
2000
-                        } else {
2001
-                            $label = esc_html__('Validation Error', 'event_espresso');
2002
-                        }
2003
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
-                    }
2005
-                }
2006
-                EE_Error::add_error(
2007
-                    sprintf(
2008
-                        esc_html__(
2009
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
-                            'event_espresso'
2011
-                        ),
2012
-                        '<br/>',
2013
-                        implode('<br/>', $error_strings)
2014
-                    ),
2015
-                    __FILE__,
2016
-                    __FUNCTION__,
2017
-                    __LINE__
2018
-                );
2019
-            } else {
2020
-                EE_Error::add_error(
2021
-                    esc_html__(
2022
-                        'The billing form was not submitted or something prevented it\'s submission.',
2023
-                        'event_espresso'
2024
-                    ),
2025
-                    __FILE__,
2026
-                    __FUNCTION__,
2027
-                    __LINE__
2028
-                );
2029
-            }
2030
-        } else {
2031
-            EE_Error::add_error(
2032
-                esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
-                __FILE__,
2034
-                __FUNCTION__,
2035
-                __LINE__
2036
-            );
2037
-        }
2038
-        return false;
2039
-    }
2040
-
2041
-
2042
-    /**
2043
-     * _setup_primary_registrant_prior_to_payment
2044
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
-     * yet)
2048
-     *
2049
-     * @access private
2050
-     * @return bool
2051
-     * @throws EE_Error
2052
-     * @throws InvalidArgumentException
2053
-     * @throws ReflectionException
2054
-     * @throws RuntimeException
2055
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
-     */
2058
-    private function _setup_primary_registrant_prior_to_payment()
2059
-    {
2060
-        // check if transaction has a primary registrant and that it has a related Attendee object
2061
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2062
-        if (
2063
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
-            && ! $this->checkout->transaction_has_primary_registrant()
2065
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2066
-        ) {
2067
-            return false;
2068
-        }
2069
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2070
-        // grab the primary_registration object
2071
-        $primary_registration = $this->checkout->transaction->primary_registration();
2072
-        // at this point we'll consider a TXN to not have been failed
2073
-        $this->checkout->transaction->toggle_failed_transaction_status();
2074
-        // save the TXN ( which clears cached copy of primary_registration)
2075
-        $this->checkout->transaction->save();
2076
-        // grab TXN ID and save it to the primary_registration
2077
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
-        // save what we have so far
2079
-        $primary_registration->save();
2080
-        return true;
2081
-    }
2082
-
2083
-
2084
-    /**
2085
-     * _capture_primary_registration_data_from_billing_form
2086
-     *
2087
-     * @access private
2088
-     * @return bool
2089
-     * @throws EE_Error
2090
-     * @throws InvalidArgumentException
2091
-     * @throws ReflectionException
2092
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
-     */
2095
-    private function _capture_primary_registration_data_from_billing_form()
2096
-    {
2097
-        // convert billing form data into an attendee
2098
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
-            EE_Error::add_error(
2101
-                sprintf(
2102
-                    esc_html__(
2103
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
-                        'event_espresso'
2105
-                    ),
2106
-                    '<br/>',
2107
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
-                ),
2109
-                __FILE__,
2110
-                __FUNCTION__,
2111
-                __LINE__
2112
-            );
2113
-            return false;
2114
-        }
2115
-        $primary_registration = $this->checkout->transaction->primary_registration();
2116
-        if (! $primary_registration instanceof EE_Registration) {
2117
-            EE_Error::add_error(
2118
-                sprintf(
2119
-                    esc_html__(
2120
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
-                        'event_espresso'
2122
-                    ),
2123
-                    '<br/>',
2124
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
-                ),
2126
-                __FILE__,
2127
-                __FUNCTION__,
2128
-                __LINE__
2129
-            );
2130
-            return false;
2131
-        }
2132
-        if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
-              instanceof
2134
-              EE_Attendee
2135
-        ) {
2136
-            EE_Error::add_error(
2137
-                sprintf(
2138
-                    esc_html__(
2139
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
-                        'event_espresso'
2141
-                    ),
2142
-                    '<br/>',
2143
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
-                ),
2145
-                __FILE__,
2146
-                __FUNCTION__,
2147
-                __LINE__
2148
-            );
2149
-            return false;
2150
-        }
2151
-        /** @type EE_Registration_Processor $registration_processor */
2152
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
-        return true;
2156
-    }
2157
-
2158
-
2159
-    /**
2160
-     * _get_payment_method_for_selected_method_of_payment
2161
-     * retrieves a valid payment method
2162
-     *
2163
-     * @access public
2164
-     * @return EE_Payment_Method
2165
-     * @throws EE_Error
2166
-     * @throws InvalidArgumentException
2167
-     * @throws ReflectionException
2168
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
-     */
2171
-    private function _get_payment_method_for_selected_method_of_payment()
2172
-    {
2173
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
-            $this->_redirect_because_event_sold_out();
2175
-            return null;
2176
-        }
2177
-        // get EE_Payment_Method object
2178
-        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
-            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
-        } else {
2181
-            // load EEM_Payment_Method
2182
-            EE_Registry::instance()->load_model('Payment_Method');
2183
-            /** @type EEM_Payment_Method $EEM_Payment_Method */
2184
-            $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
-            $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
-        }
2187
-        // verify $payment_method
2188
-        if (! $payment_method instanceof EE_Payment_Method) {
2189
-            // not a payment
2190
-            EE_Error::add_error(
2191
-                sprintf(
2192
-                    esc_html__(
2193
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
-                        'event_espresso'
2195
-                    ),
2196
-                    '<br/>',
2197
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
-                ),
2199
-                __FILE__,
2200
-                __FUNCTION__,
2201
-                __LINE__
2202
-            );
2203
-            return null;
2204
-        }
2205
-        // and verify it has a valid Payment_Method Type object
2206
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
-            // not a payment
2208
-            EE_Error::add_error(
2209
-                sprintf(
2210
-                    esc_html__(
2211
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
-                        'event_espresso'
2213
-                    ),
2214
-                    '<br/>',
2215
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
-                ),
2217
-                __FILE__,
2218
-                __FUNCTION__,
2219
-                __LINE__
2220
-            );
2221
-            return null;
2222
-        }
2223
-        return $payment_method;
2224
-    }
2225
-
2226
-
2227
-    /**
2228
-     *    _attempt_payment
2229
-     *
2230
-     * @access    private
2231
-     * @type    EE_Payment_Method $payment_method
2232
-     * @return mixed EE_Payment | boolean
2233
-     * @throws EE_Error
2234
-     * @throws InvalidArgumentException
2235
-     * @throws ReflectionException
2236
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
-     */
2239
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2240
-    {
2241
-        $payment = null;
2242
-        $this->checkout->transaction->save();
2243
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2245
-            return false;
2246
-        }
2247
-        try {
2248
-            $payment_processor->set_revisit($this->checkout->revisit);
2249
-            // generate payment object
2250
-            $payment = $payment_processor->process_payment(
2251
-                $payment_method,
2252
-                $this->checkout->transaction,
2253
-                $this->checkout->amount_owing,
2254
-                $this->checkout->billing_form,
2255
-                $this->_get_return_url($payment_method),
2256
-                'CART',
2257
-                $this->checkout->admin_request,
2258
-                true,
2259
-                $this->reg_step_url()
2260
-            );
2261
-        } catch (Exception $e) {
2262
-            $this->_handle_payment_processor_exception($e);
2263
-        }
2264
-        return $payment;
2265
-    }
2266
-
2267
-
2268
-    /**
2269
-     * _handle_payment_processor_exception
2270
-     *
2271
-     * @access protected
2272
-     * @param \Exception $e
2273
-     * @return void
2274
-     * @throws EE_Error
2275
-     * @throws InvalidArgumentException
2276
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
-     */
2279
-    protected function _handle_payment_processor_exception(Exception $e)
2280
-    {
2281
-        EE_Error::add_error(
2282
-            sprintf(
2283
-                esc_html__(
2284
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
-                    'event_espresso'
2286
-                ),
2287
-                '<br/>',
2288
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
-                $e->getMessage(),
2290
-                $e->getFile(),
2291
-                $e->getLine()
2292
-            ),
2293
-            __FILE__,
2294
-            __FUNCTION__,
2295
-            __LINE__
2296
-        );
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _get_return_url
2302
-     *
2303
-     * @access protected
2304
-     * @param \EE_Payment_Method $payment_method
2305
-     * @return string
2306
-     * @throws \EE_Error
2307
-     */
2308
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2309
-    {
2310
-        $return_url = '';
2311
-        switch ($payment_method->type_obj()->payment_occurs()) {
2312
-            case EE_PMT_Base::offsite :
2313
-                $return_url = add_query_arg(
2314
-                    array(
2315
-                        'action'                     => 'process_gateway_response',
2316
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2318
-                    ),
2319
-                    $this->reg_step_url()
2320
-                );
2321
-                break;
2322
-            case EE_PMT_Base::onsite :
2323
-            case EE_PMT_Base::offline :
2324
-                $return_url = $this->checkout->next_step->reg_step_url();
2325
-                break;
2326
-        }
2327
-        return $return_url;
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * _validate_payment
2333
-     *
2334
-     * @access private
2335
-     * @param EE_Payment $payment
2336
-     * @return EE_Payment|FALSE
2337
-     * @throws EE_Error
2338
-     * @throws InvalidArgumentException
2339
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
-     */
2342
-    private function _validate_payment($payment = null)
2343
-    {
2344
-        if ($this->checkout->payment_method->is_off_line()) {
2345
-            return true;
2346
-        }
2347
-        // verify payment object
2348
-        if (! $payment instanceof EE_Payment) {
2349
-            // not a payment
2350
-            EE_Error::add_error(
2351
-                sprintf(
2352
-                    esc_html__(
2353
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
-                        'event_espresso'
2355
-                    ),
2356
-                    '<br/>',
2357
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
-                ),
2359
-                __FILE__,
2360
-                __FUNCTION__,
2361
-                __LINE__
2362
-            );
2363
-            return false;
2364
-        }
2365
-        return $payment;
2366
-    }
2367
-
2368
-
2369
-    /**
2370
-     * _post_payment_processing
2371
-     *
2372
-     * @access private
2373
-     * @param EE_Payment|bool $payment
2374
-     * @return bool
2375
-     * @throws EE_Error
2376
-     * @throws InvalidArgumentException
2377
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
-     */
2380
-    private function _post_payment_processing($payment = null)
2381
-    {
2382
-        // Off-Line payment?
2383
-        if ($payment === true) {
2384
-            //$this->_setup_redirect_for_next_step();
2385
-            return true;
2386
-            // On-Site payment?
2387
-        } else if ($this->checkout->payment_method->is_on_site()) {
2388
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
-                //$this->_setup_redirect_for_next_step();
2390
-                $this->checkout->continue_reg = false;
2391
-            }
2392
-            // Off-Site payment?
2393
-        } else if ($this->checkout->payment_method->is_off_site()) {
2394
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
-                $this->checkout->redirect      = true;
2398
-                $this->checkout->redirect_form = $payment->redirect_form();
2399
-                $this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
-                // set JSON response
2401
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
-                // and lastly, let's bump the payment status to pending
2403
-                $payment->set_status(EEM_Payment::status_id_pending);
2404
-                $payment->save();
2405
-            } else {
2406
-                // not a payment
2407
-                $this->checkout->continue_reg = false;
2408
-                EE_Error::add_error(
2409
-                    sprintf(
2410
-                        esc_html__(
2411
-                            'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
-                            'event_espresso'
2413
-                        ),
2414
-                        '<br/>',
2415
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
-                    ),
2417
-                    __FILE__,
2418
-                    __FUNCTION__,
2419
-                    __LINE__
2420
-                );
2421
-            }
2422
-        } else {
2423
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
-            $this->checkout->continue_reg = false;
2425
-            return false;
2426
-        }
2427
-        return $payment;
2428
-    }
2429
-
2430
-
2431
-    /**
2432
-     *    _process_payment_status
2433
-     *
2434
-     * @access private
2435
-     * @type    EE_Payment $payment
2436
-     * @param string       $payment_occurs
2437
-     * @return bool
2438
-     * @throws EE_Error
2439
-     * @throws InvalidArgumentException
2440
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
-     */
2443
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
-    {
2445
-        // off-line payment? carry on
2446
-        if ($payment_occurs === EE_PMT_Base::offline) {
2447
-            return true;
2448
-        }
2449
-        // verify payment validity
2450
-        if ($payment instanceof EE_Payment) {
2451
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
-            $msg = $payment->gateway_response();
2453
-            // check results
2454
-            switch ($payment->status()) {
2455
-                // good payment
2456
-                case EEM_Payment::status_id_approved :
2457
-                    EE_Error::add_success(
2458
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
-                        __FILE__,
2460
-                        __FUNCTION__,
2461
-                        __LINE__
2462
-                    );
2463
-                    return true;
2464
-                    break;
2465
-                // slow payment
2466
-                case EEM_Payment::status_id_pending :
2467
-                    if (empty($msg)) {
2468
-                        $msg = esc_html__(
2469
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
-                            'event_espresso'
2471
-                        );
2472
-                    }
2473
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
-                    return true;
2475
-                    break;
2476
-                // don't wanna payment
2477
-                case EEM_Payment::status_id_cancelled :
2478
-                    if (empty($msg)) {
2479
-                        $msg = _n(
2480
-                            'Payment cancelled. Please try again.',
2481
-                            'Payment cancelled. Please try again or select another method of payment.',
2482
-                            count($this->checkout->available_payment_methods),
2483
-                            'event_espresso'
2484
-                        );
2485
-                    }
2486
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
-                    return false;
2488
-                    break;
2489
-                // not enough payment
2490
-                case EEM_Payment::status_id_declined :
2491
-                    if (empty($msg)) {
2492
-                        $msg = _n(
2493
-                            'We\'re sorry but your payment was declined. Please try again.',
2494
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
-                            count($this->checkout->available_payment_methods),
2496
-                            'event_espresso'
2497
-                        );
2498
-                    }
2499
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
-                    return false;
2501
-                    break;
2502
-                // bad payment
2503
-                case EEM_Payment::status_id_failed :
2504
-                    if (! empty($msg)) {
2505
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
-                        return false;
2507
-                    }
2508
-                    // default to error below
2509
-                    break;
2510
-            }
2511
-        }
2512
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2513
-        // the payment processing is just running slower than the registrant's request
2514
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2515
-            return true;
2516
-        }
2517
-        EE_Error::add_error(
2518
-            sprintf(
2519
-                esc_html__(
2520
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
-                    'event_espresso'
2522
-                ),
2523
-                '<br/>',
2524
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
-            ),
2526
-            __FILE__,
2527
-            __FUNCTION__,
2528
-            __LINE__
2529
-        );
2530
-        return false;
2531
-    }
2532
-
2533
-
2534
-
2535
-
2536
-
2537
-
2538
-    /********************************************************************************************************/
2539
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
-    /********************************************************************************************************/
2541
-    /**
2542
-     * process_gateway_response
2543
-     * this is the return point for Off-Site Payment Methods
2544
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
-     * otherwise, it will load up the last payment made for the TXN.
2546
-     * If the payment retrieved looks good, it will then either:
2547
-     *    complete the current step and allow advancement to the next reg step
2548
-     *        or present the payment options again
2549
-     *
2550
-     * @access private
2551
-     * @return EE_Payment|FALSE
2552
-     * @throws EE_Error
2553
-     * @throws InvalidArgumentException
2554
-     * @throws ReflectionException
2555
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
-     */
2559
-    public function process_gateway_response()
2560
-    {
2561
-        $payment = null;
2562
-        // how have they chosen to pay?
2563
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
-        // get EE_Payment_Method object
2565
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
-            $this->checkout->continue_reg = false;
2567
-            return false;
2568
-        }
2569
-        if (! $this->checkout->payment_method->is_off_site()) {
2570
-            return false;
2571
-        }
2572
-        $this->_validate_offsite_return();
2573
-        // DEBUG LOG
2574
-        //$this->checkout->log(
2575
-        //	__CLASS__, __FUNCTION__, __LINE__,
2576
-        //	array(
2577
-        //		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
-        //		'payment_method' => $this->checkout->payment_method,
2579
-        //	),
2580
-        //	true
2581
-        //);
2582
-        // verify TXN
2583
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2584
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2586
-                $this->checkout->continue_reg = false;
2587
-                return false;
2588
-            }
2589
-            $payment = $this->_process_off_site_payment($gateway);
2590
-            $payment = $this->_process_cancelled_payments($payment);
2591
-            $payment = $this->_validate_payment($payment);
2592
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2593
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
-                //$this->_setup_redirect_for_next_step();
2595
-                // store that for later
2596
-                $this->checkout->payment = $payment;
2597
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
-                // because we will complete this step during the IPN processing then
2599
-                if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
-                    $this->set_completed();
2601
-                }
2602
-                return true;
2603
-            }
2604
-        }
2605
-        // DEBUG LOG
2606
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
-        //	array( 'payment' => $payment )
2608
-        //);
2609
-        $this->checkout->continue_reg = false;
2610
-        return false;
2611
-    }
2612
-
2613
-
2614
-    /**
2615
-     * _validate_return
2616
-     *
2617
-     * @access private
2618
-     * @return void
2619
-     * @throws EE_Error
2620
-     * @throws InvalidArgumentException
2621
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
-     */
2625
-    private function _validate_offsite_return()
2626
-    {
2627
-        $TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
-            // Houston... we might have a problem
2630
-            $invalid_TXN = false;
2631
-            // first gather some info
2632
-            $valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2634
-                ? $valid_TXN->primary_registration()
2635
-                : null;
2636
-            // let's start by retrieving the cart for this TXN
2637
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
-            if ($cart instanceof EE_Cart) {
2639
-                // verify that the current cart has tickets
2640
-                $tickets = $cart->get_tickets();
2641
-                if (empty($tickets)) {
2642
-                    $invalid_TXN = true;
2643
-                }
2644
-            } else {
2645
-                $invalid_TXN = true;
2646
-            }
2647
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
-                ? $primary_registrant->session_ID()
2649
-                : null;
2650
-            // validate current Session ID and compare against valid TXN session ID
2651
-            if (
2652
-                $invalid_TXN // if this is already true, then skip other checks
2653
-                || EE_Session::instance()->id() === null
2654
-                || (
2655
-                    // WARNING !!!
2656
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2657
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2658
-                    // so now we need to determine if this current TXN looks valid or not
2659
-                    // and whether this reg step has even been started ?
2660
-                    EE_Session::instance()->id() === $valid_TXN_SID
2661
-                    // really? you're half way through this reg step, but you never started it ?
2662
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
-                )
2664
-            ) {
2665
-                $invalid_TXN = true;
2666
-            }
2667
-            if ($invalid_TXN) {
2668
-                // is the valid TXN completed ?
2669
-                if ($valid_TXN instanceof EE_Transaction) {
2670
-                    // has this step even been started ?
2671
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
-                        // so it **looks** like this is a double request from PayPal
2674
-                        // so let's try to pick up where we left off
2675
-                        $this->checkout->transaction = $valid_TXN;
2676
-                        $this->checkout->refresh_all_entities(true);
2677
-                        return;
2678
-                    }
2679
-                }
2680
-                // you appear to be lost?
2681
-                $this->_redirect_wayward_request($primary_registrant);
2682
-            }
2683
-        }
2684
-    }
2685
-
2686
-
2687
-    /**
2688
-     * _redirect_wayward_request
2689
-     *
2690
-     * @access private
2691
-     * @param \EE_Registration|null $primary_registrant
2692
-     * @return bool
2693
-     * @throws EE_Error
2694
-     * @throws InvalidArgumentException
2695
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
-     */
2698
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
-    {
2700
-        if (! $primary_registrant instanceof EE_Registration) {
2701
-            // try redirecting based on the current TXN
2702
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
-                ? $this->checkout->transaction->primary_registration()
2704
-                : null;
2705
-        }
2706
-        if (! $primary_registrant instanceof EE_Registration) {
2707
-            EE_Error::add_error(
2708
-                sprintf(
2709
-                    esc_html__(
2710
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
-                        'event_espresso'
2712
-                    ),
2713
-                    '<br/>',
2714
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
-                ),
2716
-                __FILE__,
2717
-                __FUNCTION__,
2718
-                __LINE__
2719
-            );
2720
-            return false;
2721
-        }
2722
-        // make sure transaction is not locked
2723
-        $this->checkout->transaction->unlock();
2724
-        wp_safe_redirect(
2725
-            add_query_arg(
2726
-                array(
2727
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
-                ),
2729
-                $this->checkout->thank_you_page_url
2730
-            )
2731
-        );
2732
-        exit();
2733
-    }
2734
-
2735
-
2736
-    /**
2737
-     * _process_off_site_payment
2738
-     *
2739
-     * @access private
2740
-     * @param \EE_Offsite_Gateway $gateway
2741
-     * @return EE_Payment
2742
-     * @throws EE_Error
2743
-     * @throws InvalidArgumentException
2744
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
-     */
2747
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
-    {
2749
-        try {
2750
-            $request_data = \EE_Registry::instance()->REQ->params();
2751
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
-            $this->set_handle_IPN_in_this_request(
2753
-                $gateway->handle_IPN_in_this_request($request_data, false)
2754
-            );
2755
-            if ($this->handle_IPN_in_this_request()) {
2756
-                // get payment details and process results
2757
-                /** @type EE_Payment_Processor $payment_processor */
2758
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
-                $payment           = $payment_processor->process_ipn(
2760
-                    $request_data,
2761
-                    $this->checkout->transaction,
2762
-                    $this->checkout->payment_method,
2763
-                    true,
2764
-                    false
2765
-                );
2766
-                //$payment_source = 'process_ipn';
2767
-            } else {
2768
-                $payment = $this->checkout->transaction->last_payment();
2769
-                //$payment_source = 'last_payment';
2770
-            }
2771
-        } catch (Exception $e) {
2772
-            // let's just eat the exception and try to move on using any previously set payment info
2773
-            $payment = $this->checkout->transaction->last_payment();
2774
-            //$payment_source = 'last_payment after Exception';
2775
-            // but if we STILL don't have a payment object
2776
-            if (! $payment instanceof EE_Payment) {
2777
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
-                $this->_handle_payment_processor_exception($e);
2779
-            }
2780
-        }
2781
-        // DEBUG LOG
2782
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
-        //	array(
2784
-        //		'process_ipn_payment' => $payment,
2785
-        //		'payment_source'      => $payment_source,
2786
-        //	)
2787
-        //);
2788
-        return $payment;
2789
-    }
2790
-
2791
-
2792
-    /**
2793
-     * _process_cancelled_payments
2794
-     * just makes sure that the payment status gets updated correctly
2795
-     * so tha tan error isn't generated during payment validation
2796
-     *
2797
-     * @access private
2798
-     * @param EE_Payment $payment
2799
-     * @return EE_Payment | FALSE
2800
-     * @throws \EE_Error
2801
-     */
2802
-    private function _process_cancelled_payments($payment = null)
2803
-    {
2804
-        if (
2805
-            $payment instanceof EE_Payment
2806
-            && isset($_REQUEST['ee_cancel_payment'])
2807
-            && $payment->status() === EEM_Payment::status_id_failed
2808
-        ) {
2809
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2810
-        }
2811
-        return $payment;
2812
-    }
2813
-
2814
-
2815
-    /**
2816
-     *    get_transaction_details_for_gateways
2817
-     *
2818
-     * @access    public
2819
-     * @return int
2820
-     * @throws EE_Error
2821
-     * @throws InvalidArgumentException
2822
-     * @throws ReflectionException
2823
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
-     */
2826
-    public function get_transaction_details_for_gateways()
2827
-    {
2828
-        $txn_details = array();
2829
-        // ya gotta make a choice man
2830
-        if (empty($this->checkout->selected_method_of_payment)) {
2831
-            $txn_details = array(
2832
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
-            );
2834
-        }
2835
-        // get EE_Payment_Method object
2836
-        if (
2837
-            empty($txn_details)
2838
-            &&
2839
-            ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
-        ) {
2841
-            $txn_details = array(
2842
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
-                'error'                      => esc_html__(
2844
-                    'A valid Payment Method could not be determined.',
2845
-                    'event_espresso'
2846
-                ),
2847
-            );
2848
-        }
2849
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
-            $return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
-            $txn_details = array(
2852
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2853
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
-                'TXN_total'      => $this->checkout->transaction->total(),
2855
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2856
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
-                'payment_amount' => $this->checkout->amount_owing,
2860
-                'return_url'     => $return_url,
2861
-                'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
-                    array(
2864
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
-                    )
2867
-                ),
2868
-            );
2869
-        }
2870
-        echo wp_json_encode($txn_details);
2871
-        exit();
2872
-    }
2873
-
2874
-
2875
-    /**
2876
-     *    __sleep
2877
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
-     * reg form, because if needed, it will be regenerated anyways
2880
-     *
2881
-     * @return array
2882
-     */
2883
-    public function __sleep()
2884
-    {
2885
-        // remove the reg form and the checkout
2886
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
-    }
18
+	/**
19
+	 * @access protected
20
+	 * @var EE_Line_Item_Display $Line_Item_Display
21
+	 */
22
+	protected $line_item_display;
23
+
24
+	/**
25
+	 * @access protected
26
+	 * @var boolean $handle_IPN_in_this_request
27
+	 */
28
+	protected $handle_IPN_in_this_request = false;
29
+
30
+
31
+	/**
32
+	 *    set_hooks - for hooking into EE Core, other modules, etc
33
+	 *
34
+	 * @access    public
35
+	 * @return    void
36
+	 */
37
+	public static function set_hooks()
38
+	{
39
+		add_filter(
40
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
+			array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
+		);
43
+		add_action(
44
+			'wp_ajax_switch_spco_billing_form',
45
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
+		);
47
+		add_action(
48
+			'wp_ajax_nopriv_switch_spco_billing_form',
49
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
+		);
51
+		add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
+		add_action(
53
+			'wp_ajax_nopriv_save_payer_details',
54
+			array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
+		);
56
+		add_action(
57
+			'wp_ajax_get_transaction_details_for_gateways',
58
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
+		);
60
+		add_action(
61
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
+		);
64
+		add_filter(
65
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
+			array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
+			10,
68
+			1
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 *    ajax switch_spco_billing_form
75
+	 *
76
+	 * @throws \EE_Error
77
+	 */
78
+	public static function switch_spco_billing_form()
79
+	{
80
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
+	}
82
+
83
+
84
+	/**
85
+	 *    ajax save_payer_details
86
+	 *
87
+	 * @throws \EE_Error
88
+	 */
89
+	public static function save_payer_details()
90
+	{
91
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
+	}
93
+
94
+
95
+	/**
96
+	 *    ajax get_transaction_details
97
+	 *
98
+	 * @throws \EE_Error
99
+	 */
100
+	public static function get_transaction_details()
101
+	{
102
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
+	}
104
+
105
+
106
+	/**
107
+	 * bypass_recaptcha_for_load_payment_method
108
+	 *
109
+	 * @access public
110
+	 * @return array
111
+	 * @throws InvalidArgumentException
112
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
+	 */
115
+	public static function bypass_recaptcha_for_load_payment_method()
116
+	{
117
+		return array(
118
+			'EESID'  => EE_Registry::instance()->SSN->id(),
119
+			'step'   => 'payment_options',
120
+			'action' => 'spco_billing_form',
121
+		);
122
+	}
123
+
124
+
125
+	/**
126
+	 *    class constructor
127
+	 *
128
+	 * @access    public
129
+	 * @param    EE_Checkout $checkout
130
+	 */
131
+	public function __construct(EE_Checkout $checkout)
132
+	{
133
+		$this->_slug     = 'payment_options';
134
+		$this->_name     = esc_html__('Payment Options', 'event_espresso');
135
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
+		$this->checkout  = $checkout;
137
+		$this->_reset_success_message();
138
+		$this->set_instructions(
139
+			esc_html__(
140
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
141
+				'event_espresso'
142
+			)
143
+		);
144
+	}
145
+
146
+
147
+	/**
148
+	 * @return null
149
+	 */
150
+	public function line_item_display()
151
+	{
152
+		return $this->line_item_display;
153
+	}
154
+
155
+
156
+	/**
157
+	 * @param null $line_item_display
158
+	 */
159
+	public function set_line_item_display($line_item_display)
160
+	{
161
+		$this->line_item_display = $line_item_display;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @return boolean
167
+	 */
168
+	public function handle_IPN_in_this_request()
169
+	{
170
+		return $this->handle_IPN_in_this_request;
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param boolean $handle_IPN_in_this_request
176
+	 */
177
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
+	{
179
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
+	}
181
+
182
+
183
+	/**
184
+	 * translate_js_strings
185
+	 *
186
+	 * @return void
187
+	 */
188
+	public function translate_js_strings()
189
+	{
190
+		EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
+			'Please select a method of payment in order to continue.',
192
+			'event_espresso'
193
+		);
194
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
196
+			'event_espresso'
197
+		);
198
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
+			'Forwarding to Secure Payment Provider.',
200
+			'event_espresso'
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * enqueue_styles_and_scripts
207
+	 *
208
+	 * @return void
209
+	 * @throws EE_Error
210
+	 * @throws InvalidArgumentException
211
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
+	 */
214
+	public function enqueue_styles_and_scripts()
215
+	{
216
+		$transaction = $this->checkout->transaction;
217
+		//if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
+			return;
220
+		}
221
+		foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
+			$type_obj = $payment_method->type_obj();
223
+			if ($type_obj instanceof EE_PMT_Base) {
224
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
225
+				if ($billing_form instanceof EE_Form_Section_Proper) {
226
+					$billing_form->enqueue_js();
227
+				}
228
+			}
229
+		}
230
+	}
231
+
232
+
233
+	/**
234
+	 * initialize_reg_step
235
+	 *
236
+	 * @return bool
237
+	 * @throws EE_Error
238
+	 * @throws InvalidArgumentException
239
+	 * @throws ReflectionException
240
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
+	 */
243
+	public function initialize_reg_step()
244
+	{
245
+		// TODO: if /when we implement donations, then this will need overriding
246
+		if (// don't need payment options for:
247
+			// 	registrations made via the admin
248
+			// 	completed transactions
249
+			// 	overpaid transactions
250
+			// 	$ 0.00 transactions (no payment required)
251
+			! $this->checkout->payment_required()
252
+			// but do NOT remove if current action being called belongs to this reg step
253
+			&& ! is_callable(array($this, $this->checkout->action))
254
+			&& ! $this->completed()
255
+		) {
256
+			// and if so, then we no longer need the Payment Options step
257
+			if ($this->is_current_step()) {
258
+				$this->checkout->generate_reg_form = false;
259
+			}
260
+			$this->checkout->remove_reg_step($this->_slug);
261
+			// DEBUG LOG
262
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
+			return false;
264
+		}
265
+		// load EEM_Payment_Method
266
+		EE_Registry::instance()->load_model('Payment_Method');
267
+		// get all active payment methods
268
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
+			$this->checkout->transaction,
270
+			EEM_Payment_Method::scope_cart
271
+		);
272
+		return true;
273
+	}
274
+
275
+
276
+	/**
277
+	 * @return EE_Form_Section_Proper
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws ReflectionException
281
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
+	 */
286
+	public function generate_reg_form()
287
+	{
288
+		// reset in case someone changes their mind
289
+		$this->_reset_selected_method_of_payment();
290
+		// set some defaults
291
+		$this->checkout->selected_method_of_payment = 'payments_closed';
292
+		$registrations_requiring_payment            = array();
293
+		$registrations_for_free_events              = array();
294
+		$registrations_requiring_pre_approval       = array();
295
+		$sold_out_events                            = array();
296
+		$insufficient_spaces_available              = array();
297
+		$no_payment_required                        = true;
298
+		// loop thru registrations to gather info
299
+		$registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
+			$registrations,
302
+			$this->checkout->revisit
303
+		);
304
+		foreach ($registrations as $REG_ID => $registration) {
305
+			/** @var $registration EE_Registration */
306
+			// has this registration lost it's space ?
307
+			if (isset($ejected_registrations[ $REG_ID ])) {
308
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
+				} else {
311
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
+				}
313
+				continue;
314
+			}
315
+			// event requires admin approval
316
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
+				// add event to list of events with pre-approval reg status
318
+				$registrations_requiring_pre_approval[$REG_ID] = $registration;
319
+				do_action(
320
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
+					$registration->event(),
322
+					$this
323
+				);
324
+				continue;
325
+			}
326
+			if ($this->checkout->revisit
327
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
328
+				&& (
329
+					$registration->event()->is_sold_out()
330
+					|| $registration->event()->is_sold_out(true)
331
+				)
332
+			) {
333
+				// add event to list of events that are sold out
334
+				$sold_out_events[$registration->event()->ID()] = $registration->event();
335
+				do_action(
336
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
+					$registration->event(),
338
+					$this
339
+				);
340
+				continue;
341
+			}
342
+			// are they allowed to pay now and is there monies owing?
343
+			if ($registration->owes_monies_and_can_pay()) {
344
+				$registrations_requiring_payment[$REG_ID] = $registration;
345
+				do_action(
346
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
+					$registration->event(),
348
+					$this
349
+				);
350
+			} elseif (! $this->checkout->revisit
351
+				&& $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
+				&& $registration->ticket()->is_free()
353
+			) {
354
+				$registrations_for_free_events[$registration->event()->ID()] = $registration;
355
+			}
356
+		}
357
+		$subsections = array();
358
+		// now decide which template to load
359
+		if (! empty($sold_out_events)) {
360
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
+		}
362
+		if (! empty($insufficient_spaces_available)) {
363
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
+				$insufficient_spaces_available
365
+			);
366
+		}
367
+		if (! empty($registrations_requiring_pre_approval)) {
368
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
+				$registrations_requiring_pre_approval
370
+			);
371
+		}
372
+		if (! empty($registrations_for_free_events)) {
373
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
+		}
375
+		if (! empty($registrations_requiring_payment)) {
376
+			if ($this->checkout->amount_owing > 0) {
377
+				// autoload Line_Item_Display classes
378
+				EEH_Autoloader::register_line_item_filter_autoloaders();
379
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
+					apply_filters(
381
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
+						new EE_Line_Item_Filter_Collection()
383
+					),
384
+					$this->checkout->cart->get_grand_total()
385
+				);
386
+				/** @var EE_Line_Item $filtered_line_item_tree */
387
+				$filtered_line_item_tree = $line_item_filter_processor->process();
388
+				EEH_Autoloader::register_line_item_display_autoloaders();
389
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
+				$subsections['payment_options'] = $this->_display_payment_options(
391
+					$this->line_item_display->display_line_item(
392
+						$filtered_line_item_tree,
393
+						array('registrations' => $registrations)
394
+					)
395
+				);
396
+				$this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
+				$this->_apply_registration_payments_to_amount_owing($registrations);
398
+			}
399
+			$no_payment_required = false;
400
+		} else {
401
+			$this->_hide_reg_step_submit_button_if_revisit();
402
+		}
403
+		$this->_save_selected_method_of_payment();
404
+
405
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
+		$subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
+
408
+		return new EE_Form_Section_Proper(
409
+			array(
410
+				'name'            => $this->reg_form_name(),
411
+				'html_id'         => $this->reg_form_name(),
412
+				'subsections'     => $subsections,
413
+				'layout_strategy' => new EE_No_Layout(),
414
+			)
415
+		);
416
+	}
417
+
418
+
419
+	/**
420
+	 * add line item filters required for this reg step
421
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
425
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
+	 *        filter collection by passing that instead of instantiating a new collection
427
+	 *
428
+	 * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
+	 * @return EE_Line_Item_Filter_Collection
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws ReflectionException
433
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
+	 */
438
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
+	{
440
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
+			return $line_item_filter_collection;
442
+		}
443
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
+			return $line_item_filter_collection;
445
+		}
446
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
+			return $line_item_filter_collection;
448
+		}
449
+		$line_item_filter_collection->add(
450
+			new EE_Billable_Line_Item_Filter(
451
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
+					)
455
+				)
456
+			)
457
+		);
458
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
+		return $line_item_filter_collection;
460
+	}
461
+
462
+
463
+	/**
464
+	 * remove_ejected_registrations
465
+	 * if a registrant has lost their potential space at an event due to lack of payment,
466
+	 * then this method removes them from the list of registrations being paid for during this request
467
+	 *
468
+	 * @param \EE_Registration[] $registrations
469
+	 * @return EE_Registration[]
470
+	 * @throws EE_Error
471
+	 * @throws InvalidArgumentException
472
+	 * @throws ReflectionException
473
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
+	 */
478
+	public static function remove_ejected_registrations(array $registrations)
479
+	{
480
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
+			$registrations,
482
+			EE_Registry::instance()->SSN->checkout()->revisit
483
+		);
484
+		foreach ($registrations as $REG_ID => $registration) {
485
+			// has this registration lost it's space ?
486
+			if (isset($ejected_registrations[$REG_ID])) {
487
+				unset($registrations[$REG_ID]);
488
+				continue;
489
+			}
490
+		}
491
+		return $registrations;
492
+	}
493
+
494
+
495
+	/**
496
+	 * find_registrations_that_lost_their_space
497
+	 * If a registrant chooses an offline payment method like Invoice,
498
+	 * then no space is reserved for them at the event until they fully pay fo that site
499
+	 * (unless the event's default reg status is set to APPROVED)
500
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
502
+	 *
503
+	 * @param \EE_Registration[] $registrations
504
+	 * @param bool               $revisit
505
+	 * @return array
506
+	 * @throws EE_Error
507
+	 * @throws InvalidArgumentException
508
+	 * @throws ReflectionException
509
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
+	 */
514
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
+	{
516
+		// registrations per event
517
+		$event_reg_count = array();
518
+		// spaces left per event
519
+		$event_spaces_remaining = array();
520
+		// tickets left sorted by ID
521
+		$tickets_remaining = array();
522
+		// registrations that have lost their space
523
+		$ejected_registrations = array();
524
+		foreach ($registrations as $REG_ID => $registration) {
525
+			if ($registration->status_ID() === EEM_Registration::status_id_approved
526
+				|| apply_filters(
527
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
+					false,
529
+					$registration,
530
+					$revisit
531
+				)
532
+			) {
533
+				continue;
534
+			}
535
+			$EVT_ID = $registration->event_ID();
536
+			$ticket = $registration->ticket();
537
+			if (! isset($tickets_remaining[$ticket->ID()])) {
538
+				$tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
+			}
540
+			if ($tickets_remaining[$ticket->ID()] > 0) {
541
+				if (! isset($event_reg_count[$EVT_ID])) {
542
+					$event_reg_count[$EVT_ID] = 0;
543
+				}
544
+				$event_reg_count[$EVT_ID]++;
545
+				if (! isset($event_spaces_remaining[$EVT_ID])) {
546
+					$event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
+				}
548
+			}
549
+			if ($revisit
550
+				&& ($tickets_remaining[$ticket->ID()] === 0
551
+					|| $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
+				)
553
+			) {
554
+				$ejected_registrations[$REG_ID] = $registration->event();
555
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
+					/** @type EE_Registration_Processor $registration_processor */
557
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
+					// at this point, we should have enough details about the registrant to consider the registration
559
+					// NOT incomplete
560
+					$registration_processor->manually_update_registration_status(
561
+						$registration,
562
+						EEM_Registration::status_id_wait_list
563
+					);
564
+				}
565
+			}
566
+		}
567
+		return $ejected_registrations;
568
+	}
569
+
570
+
571
+	/**
572
+	 * _hide_reg_step_submit_button
573
+	 * removes the html for the reg step submit button
574
+	 * by replacing it with an empty string via filter callback
575
+	 *
576
+	 * @return void
577
+	 */
578
+	protected function _adjust_registration_status_if_event_old_sold()
579
+	{
580
+	}
581
+
582
+
583
+	/**
584
+	 * _hide_reg_step_submit_button
585
+	 * removes the html for the reg step submit button
586
+	 * by replacing it with an empty string via filter callback
587
+	 *
588
+	 * @return void
589
+	 */
590
+	protected function _hide_reg_step_submit_button_if_revisit()
591
+	{
592
+		if ($this->checkout->revisit) {
593
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
+		}
595
+	}
596
+
597
+
598
+	/**
599
+	 * sold_out_events
600
+	 * displays notices regarding events that have sold out since hte registrant first signed up
601
+	 *
602
+	 * @param \EE_Event[] $sold_out_events_array
603
+	 * @return \EE_Form_Section_Proper
604
+	 * @throws \EE_Error
605
+	 */
606
+	private function _sold_out_events($sold_out_events_array = array())
607
+	{
608
+		// set some defaults
609
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
610
+		$sold_out_events                            = '';
611
+		foreach ($sold_out_events_array as $sold_out_event) {
612
+			$sold_out_events .= EEH_HTML::li(
613
+				EEH_HTML::span(
614
+					'  ' . $sold_out_event->name(),
615
+					'',
616
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
+				)
618
+			);
619
+		}
620
+		return new EE_Form_Section_Proper(
621
+			array(
622
+				'layout_strategy' => new EE_Template_Layout(
623
+					array(
624
+						'layout_template_file' => SPCO_REG_STEPS_PATH
625
+												  . $this->_slug
626
+												  . DS
627
+												  . 'sold_out_events.template.php',
628
+						'template_args'        => apply_filters(
629
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
+							array(
631
+								'sold_out_events'     => $sold_out_events,
632
+								'sold_out_events_msg' => apply_filters(
633
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
+									sprintf(
635
+										esc_html__(
636
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
+											'event_espresso'
638
+										),
639
+										'<strong>',
640
+										'</strong>',
641
+										'<br />'
642
+									)
643
+								),
644
+							)
645
+						),
646
+					)
647
+				),
648
+			)
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * _insufficient_spaces_available
655
+	 * displays notices regarding events that do not have enough remaining spaces
656
+	 * to satisfy the current number of registrations looking to pay
657
+	 *
658
+	 * @param \EE_Event[] $insufficient_spaces_events_array
659
+	 * @return \EE_Form_Section_Proper
660
+	 * @throws \EE_Error
661
+	 */
662
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
+	{
664
+		// set some defaults
665
+		$this->checkout->selected_method_of_payment = 'invoice';
666
+		$insufficient_space_events                  = '';
667
+		foreach ($insufficient_spaces_events_array as $event) {
668
+			if ($event instanceof EE_Event) {
669
+				$insufficient_space_events .= EEH_HTML::li(
670
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
+				);
672
+			}
673
+		}
674
+		return new EE_Form_Section_Proper(
675
+			array(
676
+				'subsections'     => array(
677
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
+				),
680
+				'layout_strategy' => new EE_Template_Layout(
681
+					array(
682
+						'layout_template_file' => SPCO_REG_STEPS_PATH
683
+												  . $this->_slug
684
+												  . DS
685
+												  . 'sold_out_events.template.php',
686
+						'template_args'        => apply_filters(
687
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
+							array(
689
+								'sold_out_events'     => $insufficient_space_events,
690
+								'sold_out_events_msg' => apply_filters(
691
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
+									esc_html__(
693
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
+										'event_espresso'
695
+									)
696
+								),
697
+							)
698
+						),
699
+					)
700
+				),
701
+			)
702
+		);
703
+	}
704
+
705
+
706
+	/**
707
+	 * registrations_requiring_pre_approval
708
+	 *
709
+	 * @param array $registrations_requiring_pre_approval
710
+	 * @return EE_Form_Section_Proper
711
+	 * @throws EE_Error
712
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
+	 */
714
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
+	{
716
+		$events_requiring_pre_approval = '';
717
+		foreach ($registrations_requiring_pre_approval as $registration) {
718
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
+				$events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
+					EEH_HTML::span(
721
+						'',
722
+						'',
723
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
+					)
725
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
+				);
727
+			}
728
+		}
729
+		return new EE_Form_Section_Proper(
730
+			array(
731
+				'layout_strategy' => new EE_Template_Layout(
732
+					array(
733
+						'layout_template_file' => SPCO_REG_STEPS_PATH
734
+												  . $this->_slug
735
+												  . DS
736
+												  . 'events_requiring_pre_approval.template.php', // layout_template
737
+						'template_args'        => apply_filters(
738
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
+							array(
740
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
+								'events_requiring_pre_approval_msg' => apply_filters(
742
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
+									esc_html__(
744
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
+										'event_espresso'
746
+									)
747
+								),
748
+							)
749
+						),
750
+					)
751
+				),
752
+			)
753
+		);
754
+	}
755
+
756
+
757
+	/**
758
+	 * _no_payment_required
759
+	 *
760
+	 * @param \EE_Event[] $registrations_for_free_events
761
+	 * @return \EE_Form_Section_Proper
762
+	 * @throws \EE_Error
763
+	 */
764
+	private function _no_payment_required($registrations_for_free_events = array())
765
+	{
766
+		// set some defaults
767
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
768
+		// generate no_payment_required form
769
+		return new EE_Form_Section_Proper(
770
+			array(
771
+				'layout_strategy' => new EE_Template_Layout(
772
+					array(
773
+						'layout_template_file' => SPCO_REG_STEPS_PATH
774
+												  . $this->_slug
775
+												  . DS
776
+												  . 'no_payment_required.template.php', // layout_template
777
+						'template_args'        => apply_filters(
778
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
+							array(
780
+								'revisit'                       => $this->checkout->revisit,
781
+								'registrations'                 => array(),
782
+								'ticket_count'                  => array(),
783
+								'registrations_for_free_events' => $registrations_for_free_events,
784
+								'no_payment_required_msg'       => EEH_HTML::p(
785
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
+								),
787
+							)
788
+						),
789
+					)
790
+				),
791
+			)
792
+		);
793
+	}
794
+
795
+
796
+	/**
797
+	 * _display_payment_options
798
+	 *
799
+	 * @param string $transaction_details
800
+	 * @return EE_Form_Section_Proper
801
+	 * @throws EE_Error
802
+	 * @throws InvalidArgumentException
803
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
+	 */
806
+	private function _display_payment_options($transaction_details = '')
807
+	{
808
+		// has method_of_payment been set by no-js user?
809
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
+		// build payment options form
811
+		return apply_filters(
812
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
+			new EE_Form_Section_Proper(
814
+				array(
815
+					'subsections'     => array(
816
+						'before_payment_options' => apply_filters(
817
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
+							new EE_Form_Section_Proper(
819
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
+							)
821
+						),
822
+						'payment_options'        => $this->_setup_payment_options(),
823
+						'after_payment_options'  => apply_filters(
824
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
+							new EE_Form_Section_Proper(
826
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
+							)
828
+						),
829
+					),
830
+					'layout_strategy' => new EE_Template_Layout(
831
+						array(
832
+							'layout_template_file' => $this->_template,
833
+							'template_args'        => apply_filters(
834
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
+								array(
836
+									'reg_count'                 => $this->line_item_display->total_items(),
837
+									'transaction_details'       => $transaction_details,
838
+									'available_payment_methods' => array(),
839
+								)
840
+							),
841
+						)
842
+					),
843
+				)
844
+			)
845
+		);
846
+	}
847
+
848
+
849
+	/**
850
+	 * _extra_hidden_inputs
851
+	 *
852
+	 * @param bool $no_payment_required
853
+	 * @return \EE_Form_Section_Proper
854
+	 * @throws \EE_Error
855
+	 */
856
+	private function _extra_hidden_inputs($no_payment_required = true)
857
+	{
858
+		return new EE_Form_Section_Proper(
859
+			array(
860
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
+				'subsections'     => array(
863
+					'spco_no_payment_required' => new EE_Hidden_Input(
864
+						array(
865
+							'normalization_strategy' => new EE_Boolean_Normalization(),
866
+							'html_name'              => 'spco_no_payment_required',
867
+							'html_id'                => 'spco-no-payment-required-payment_options',
868
+							'default'                => $no_payment_required,
869
+						)
870
+					),
871
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
+						array(
873
+							'normalization_strategy' => new EE_Int_Normalization(),
874
+							'html_name'              => 'spco_transaction_id',
875
+							'html_id'                => 'spco-transaction-id',
876
+							'default'                => $this->checkout->transaction->ID(),
877
+						)
878
+					),
879
+				),
880
+			)
881
+		);
882
+	}
883
+
884
+
885
+	/**
886
+	 *    _apply_registration_payments_to_amount_owing
887
+	 *
888
+	 * @access protected
889
+	 * @param array $registrations
890
+	 * @throws EE_Error
891
+	 */
892
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
+	{
894
+		$payments = array();
895
+		foreach ($registrations as $registration) {
896
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
+				$payments += $registration->registration_payments();
898
+			}
899
+		}
900
+		if (! empty($payments)) {
901
+			foreach ($payments as $payment) {
902
+				if ($payment instanceof EE_Registration_Payment) {
903
+					$this->checkout->amount_owing -= $payment->amount();
904
+				}
905
+			}
906
+		}
907
+	}
908
+
909
+
910
+	/**
911
+	 *    _reset_selected_method_of_payment
912
+	 *
913
+	 * @access    private
914
+	 * @param    bool $force_reset
915
+	 * @return void
916
+	 * @throws InvalidArgumentException
917
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
+	 */
920
+	private function _reset_selected_method_of_payment($force_reset = false)
921
+	{
922
+		$reset_payment_method = $force_reset
923
+			? true
924
+			: sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
+		if ($reset_payment_method) {
926
+			$this->checkout->selected_method_of_payment = null;
927
+			$this->checkout->payment_method             = null;
928
+			$this->checkout->billing_form               = null;
929
+			$this->_save_selected_method_of_payment();
930
+		}
931
+	}
932
+
933
+
934
+	/**
935
+	 * _save_selected_method_of_payment
936
+	 * stores the selected_method_of_payment in the session
937
+	 * so that it's available for all subsequent requests including AJAX
938
+	 *
939
+	 * @access        private
940
+	 * @param string $selected_method_of_payment
941
+	 * @return void
942
+	 * @throws InvalidArgumentException
943
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
+	 */
946
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
+	{
948
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
949
+			? $selected_method_of_payment
950
+			: $this->checkout->selected_method_of_payment;
951
+		EE_Registry::instance()->SSN->set_session_data(
952
+			array('selected_method_of_payment' => $selected_method_of_payment)
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * _setup_payment_options
959
+	 *
960
+	 * @return EE_Form_Section_Proper
961
+	 * @throws EE_Error
962
+	 * @throws InvalidArgumentException
963
+	 * @throws ReflectionException
964
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
+	 */
967
+	public function _setup_payment_options()
968
+	{
969
+		// load payment method classes
970
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
+		if (empty($this->checkout->available_payment_methods)) {
972
+			EE_Error::add_error(
973
+				apply_filters(
974
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
+					sprintf(
976
+						esc_html__(
977
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
+							'event_espresso'
979
+						),
980
+						'<br>',
981
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
982
+					)
983
+				),
984
+				__FILE__,
985
+				__FUNCTION__,
986
+				__LINE__
987
+			);
988
+		}
989
+		// switch up header depending on number of available payment methods
990
+		$payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
+			? apply_filters(
992
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
+			)
995
+			: apply_filters(
996
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
+				esc_html__('Method of Payment', 'event_espresso')
998
+			);
999
+		$available_payment_methods = array(
1000
+			// display the "Payment Method" header
1001
+			'payment_method_header' => new EE_Form_Section_HTML(
1002
+				EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
+			),
1004
+		);
1005
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
+		$available_payment_method_options = array();
1007
+		$default_payment_method_option    = array();
1008
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
+		$payment_methods_billing_info = array(
1010
+			new EE_Form_Section_HTML(
1011
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
+			),
1013
+		);
1014
+		// loop through payment methods
1015
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
+			if ($payment_method instanceof EE_Payment_Method) {
1017
+				$payment_method_button = EEH_HTML::img(
1018
+					$payment_method->button_url(),
1019
+					$payment_method->name(),
1020
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
+					'spco-payment-method-btn-img'
1022
+				);
1023
+				// check if any payment methods are set as default
1024
+				// if payment method is already selected OR nothing is selected and this payment method should be
1025
+				// open_by_default
1026
+				if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
+				) {
1029
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1030
+					$this->_save_selected_method_of_payment();
1031
+					$default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
+				} else {
1033
+					$available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
+				}
1035
+				$payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
+					$payment_method
1037
+				);
1038
+			}
1039
+		}
1040
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
+		// of PMs
1042
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
+		// now generate the actual form  inputs
1044
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
+			$available_payment_method_options
1046
+		);
1047
+		$available_payment_methods                              += $payment_methods_billing_info;
1048
+		// build the available payment methods form
1049
+		return new EE_Form_Section_Proper(
1050
+			array(
1051
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1052
+				'subsections'     => $available_payment_methods,
1053
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
+			)
1055
+		);
1056
+	}
1057
+
1058
+
1059
+	/**
1060
+	 * _get_available_payment_methods
1061
+	 *
1062
+	 * @return EE_Payment_Method[]
1063
+	 * @throws EE_Error
1064
+	 * @throws InvalidArgumentException
1065
+	 * @throws ReflectionException
1066
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
+	 */
1069
+	protected function _get_available_payment_methods()
1070
+	{
1071
+		if (! empty($this->checkout->available_payment_methods)) {
1072
+			return $this->checkout->available_payment_methods;
1073
+		}
1074
+		$available_payment_methods = array();
1075
+		// load EEM_Payment_Method
1076
+		EE_Registry::instance()->load_model('Payment_Method');
1077
+		/** @type EEM_Payment_Method $EEM_Payment_Method */
1078
+		$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
+		// get all active payment methods
1080
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
+			$this->checkout->transaction,
1082
+			EEM_Payment_Method::scope_cart
1083
+		);
1084
+		foreach ($payment_methods as $payment_method) {
1085
+			if ($payment_method instanceof EE_Payment_Method) {
1086
+				$available_payment_methods[$payment_method->slug()] = $payment_method;
1087
+			}
1088
+		}
1089
+		return $available_payment_methods;
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 *    _available_payment_method_inputs
1095
+	 *
1096
+	 * @access    private
1097
+	 * @param    array $available_payment_method_options
1098
+	 * @return    \EE_Form_Section_Proper
1099
+	 */
1100
+	private function _available_payment_method_inputs($available_payment_method_options = array())
1101
+	{
1102
+		// generate inputs
1103
+		return new EE_Form_Section_Proper(
1104
+			array(
1105
+				'html_id'         => 'ee-available-payment-method-inputs',
1106
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
+				'subsections'     => array(
1108
+					'' => new EE_Radio_Button_Input(
1109
+						$available_payment_method_options,
1110
+						array(
1111
+							'html_name'          => 'selected_method_of_payment',
1112
+							'html_class'         => 'spco-payment-method',
1113
+							'default'            => $this->checkout->selected_method_of_payment,
1114
+							'label_size'         => 11,
1115
+							'enforce_label_size' => true,
1116
+						)
1117
+					),
1118
+				),
1119
+			)
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	/**
1125
+	 *    _payment_method_billing_info
1126
+	 *
1127
+	 * @access    private
1128
+	 * @param    EE_Payment_Method $payment_method
1129
+	 * @return EE_Form_Section_Proper
1130
+	 * @throws EE_Error
1131
+	 * @throws InvalidArgumentException
1132
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
+	 */
1135
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
+	{
1137
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
+			? true
1139
+			: false;
1140
+		// generate the billing form for payment method
1141
+		$billing_form                 = $currently_selected
1142
+			? $this->_get_billing_form_for_payment_method($payment_method)
1143
+			: new EE_Form_Section_HTML();
1144
+		$this->checkout->billing_form = $currently_selected
1145
+			? $billing_form
1146
+			: $this->checkout->billing_form;
1147
+		// it's all in the details
1148
+		$info_html = EEH_HTML::h3(
1149
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1150
+			'',
1151
+			'spco-payment-method-hdr'
1152
+		);
1153
+		// add some info regarding the step, either from what's saved in the admin,
1154
+		// or a default string depending on whether the PM has a billing form or not
1155
+		if ($payment_method->description()) {
1156
+			$payment_method_info = $payment_method->description();
1157
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
+			$payment_method_info = sprintf(
1159
+				esc_html__(
1160
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
+					'event_espresso'
1162
+				),
1163
+				$this->submit_button_text()
1164
+			);
1165
+		} else {
1166
+			$payment_method_info = sprintf(
1167
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
+				$this->submit_button_text()
1169
+			);
1170
+		}
1171
+		$info_html .= EEH_HTML::p(
1172
+			apply_filters(
1173
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
+				$payment_method_info
1175
+			),
1176
+			'',
1177
+			'spco-payment-method-desc ee-attention'
1178
+		);
1179
+		return new EE_Form_Section_Proper(
1180
+			array(
1181
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
+				'html_class'      => 'spco-payment-method-info-dv',
1183
+				// only display the selected or default PM
1184
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1185
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
+				'subsections'     => array(
1187
+					'info'         => new EE_Form_Section_HTML($info_html),
1188
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
+				),
1190
+			)
1191
+		);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * get_billing_form_html_for_payment_method
1197
+	 *
1198
+	 * @access public
1199
+	 * @return string
1200
+	 * @throws EE_Error
1201
+	 * @throws InvalidArgumentException
1202
+	 * @throws ReflectionException
1203
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
+	 */
1206
+	public function get_billing_form_html_for_payment_method()
1207
+	{
1208
+		// how have they chosen to pay?
1209
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
+		$this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
+			return false;
1213
+		}
1214
+		if (apply_filters(
1215
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
+			false
1217
+		)) {
1218
+			EE_Error::add_success(
1219
+				apply_filters(
1220
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
+					sprintf(
1222
+						esc_html__(
1223
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
+							'event_espresso'
1225
+						),
1226
+						$this->checkout->payment_method->name()
1227
+					)
1228
+				)
1229
+			);
1230
+		}
1231
+		// now generate billing form for selected method of payment
1232
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
+		// fill form with attendee info if applicable
1234
+		if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
+			&& $this->checkout->transaction_has_primary_registrant()
1236
+		) {
1237
+			$payment_method_billing_form->populate_from_attendee(
1238
+				$this->checkout->transaction->primary_registration()->attendee()
1239
+			);
1240
+		}
1241
+		// and debug content
1242
+		if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
+		) {
1245
+			$payment_method_billing_form =
1246
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
+					$payment_method_billing_form
1248
+				);
1249
+		}
1250
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
+			? $payment_method_billing_form->get_html()
1252
+			: '';
1253
+		$this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
+		// localize validation rules for main form
1255
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1256
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
+		return true;
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * _get_billing_form_for_payment_method
1263
+	 *
1264
+	 * @access private
1265
+	 * @param EE_Payment_Method $payment_method
1266
+	 * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
+	 * @throws EE_Error
1268
+	 * @throws InvalidArgumentException
1269
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
+	 */
1272
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
+	{
1274
+		$billing_form = $payment_method->type_obj()->billing_form(
1275
+			$this->checkout->transaction,
1276
+			array('amount_owing' => $this->checkout->amount_owing)
1277
+		);
1278
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1279
+			if (apply_filters(
1280
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
+				false
1282
+			)
1283
+				&& EE_Registry::instance()->REQ->is_set('payment_method')
1284
+			) {
1285
+				EE_Error::add_success(
1286
+					apply_filters(
1287
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
+						sprintf(
1289
+							esc_html__(
1290
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
+								'event_espresso'
1292
+							),
1293
+							$payment_method->name()
1294
+						)
1295
+					)
1296
+				);
1297
+			}
1298
+			return apply_filters(
1299
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
+				$billing_form,
1301
+				$payment_method
1302
+			);
1303
+		}
1304
+		// no actual billing form, so return empty HTML form section
1305
+		return new EE_Form_Section_HTML();
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _get_selected_method_of_payment
1311
+	 *
1312
+	 * @access private
1313
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
+	 *                          is not found in the incoming request
1315
+	 * @param string  $request_param
1316
+	 * @return NULL|string
1317
+	 * @throws EE_Error
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
+	 */
1322
+	private function _get_selected_method_of_payment(
1323
+		$required = false,
1324
+		$request_param = 'selected_method_of_payment'
1325
+	) {
1326
+		// is selected_method_of_payment set in the request ?
1327
+		$selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
+		if ($selected_method_of_payment) {
1329
+			// sanitize it
1330
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1331
+				? array_shift($selected_method_of_payment)
1332
+				: $selected_method_of_payment;
1333
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
+			// store it in the session so that it's available for all subsequent requests including AJAX
1335
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1336
+		} else {
1337
+			// or is is set in the session ?
1338
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
+				'selected_method_of_payment'
1340
+			);
1341
+		}
1342
+		// do ya really really gotta have it?
1343
+		if (empty($selected_method_of_payment) && $required) {
1344
+			EE_Error::add_error(
1345
+				sprintf(
1346
+					esc_html__(
1347
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
+						'event_espresso'
1349
+					),
1350
+					'<br/>',
1351
+					'<br/>',
1352
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
+				),
1354
+				__FILE__,
1355
+				__FUNCTION__,
1356
+				__LINE__
1357
+			);
1358
+			return null;
1359
+		}
1360
+		return $selected_method_of_payment;
1361
+	}
1362
+
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+	/********************************************************************************************************/
1369
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
+	/********************************************************************************************************/
1371
+	/**
1372
+	 * switch_payment_method
1373
+	 *
1374
+	 * @access public
1375
+	 * @return string
1376
+	 * @throws EE_Error
1377
+	 * @throws InvalidArgumentException
1378
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
+	 */
1381
+	public function switch_payment_method()
1382
+	{
1383
+		if (! $this->_verify_payment_method_is_set()) {
1384
+			return false;
1385
+		}
1386
+		if (apply_filters(
1387
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
+			false
1389
+		)) {
1390
+			EE_Error::add_success(
1391
+				apply_filters(
1392
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
+					sprintf(
1394
+						esc_html__(
1395
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
+							'event_espresso'
1397
+						),
1398
+						$this->checkout->payment_method->name()
1399
+					)
1400
+				)
1401
+			);
1402
+		}
1403
+		// generate billing form for selected method of payment if it hasn't been done already
1404
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
+				$this->checkout->payment_method
1407
+			);
1408
+		}
1409
+		// fill form with attendee info if applicable
1410
+		if (apply_filters(
1411
+			'FHEE__populate_billing_form_fields_from_attendee',
1412
+			(
1413
+				$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
+				&& $this->checkout->transaction_has_primary_registrant()
1415
+			),
1416
+			$this->checkout->billing_form,
1417
+			$this->checkout->transaction
1418
+		)
1419
+		) {
1420
+			$this->checkout->billing_form->populate_from_attendee(
1421
+				$this->checkout->transaction->primary_registration()->attendee()
1422
+			);
1423
+		}
1424
+		// and debug content
1425
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
+		) {
1428
+			$this->checkout->billing_form =
1429
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
+					$this->checkout->billing_form
1431
+				);
1432
+		}
1433
+		// get html and validation rules for form
1434
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
+			$this->checkout->json_response->set_return_data(
1436
+				array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
+			);
1438
+			// localize validation rules for main form
1439
+			$this->checkout->billing_form->localize_validation_rules(true);
1440
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
+		} else {
1442
+			$this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
+		}
1444
+		//prevents advancement to next step
1445
+		$this->checkout->continue_reg = false;
1446
+		return true;
1447
+	}
1448
+
1449
+
1450
+	/**
1451
+	 * _verify_payment_method_is_set
1452
+	 *
1453
+	 * @return bool
1454
+	 * @throws EE_Error
1455
+	 * @throws InvalidArgumentException
1456
+	 * @throws ReflectionException
1457
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
+	 */
1460
+	protected function _verify_payment_method_is_set()
1461
+	{
1462
+		// generate billing form for selected method of payment if it hasn't been done already
1463
+		if (empty($this->checkout->selected_method_of_payment)) {
1464
+			// how have they chosen to pay?
1465
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
+		} else {
1467
+			// choose your own adventure based on method_of_payment
1468
+			switch ($this->checkout->selected_method_of_payment) {
1469
+				case 'events_sold_out' :
1470
+					EE_Error::add_attention(
1471
+						apply_filters(
1472
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
+							esc_html__(
1474
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
+								'event_espresso'
1476
+							)
1477
+						),
1478
+						__FILE__, __FUNCTION__, __LINE__
1479
+					);
1480
+					return false;
1481
+					break;
1482
+				case 'payments_closed' :
1483
+					EE_Error::add_attention(
1484
+						apply_filters(
1485
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
+							esc_html__(
1487
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
+								'event_espresso'
1489
+							)
1490
+						),
1491
+						__FILE__, __FUNCTION__, __LINE__
1492
+					);
1493
+					return false;
1494
+					break;
1495
+				case 'no_payment_required' :
1496
+					EE_Error::add_attention(
1497
+						apply_filters(
1498
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
+							esc_html__(
1500
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
+								'event_espresso'
1502
+							)
1503
+						),
1504
+						__FILE__, __FUNCTION__, __LINE__
1505
+					);
1506
+					return false;
1507
+					break;
1508
+				default:
1509
+			}
1510
+		}
1511
+		// verify payment method
1512
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
+			// get payment method for selected method of payment
1514
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
+		}
1516
+		return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
+	}
1518
+
1519
+
1520
+
1521
+	/********************************************************************************************************/
1522
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1523
+	/********************************************************************************************************/
1524
+	/**
1525
+	 * save_payer_details_via_ajax
1526
+	 *
1527
+	 * @return void
1528
+	 * @throws EE_Error
1529
+	 * @throws InvalidArgumentException
1530
+	 * @throws ReflectionException
1531
+	 * @throws RuntimeException
1532
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
+	 */
1535
+	public function save_payer_details_via_ajax()
1536
+	{
1537
+		if (! $this->_verify_payment_method_is_set()) {
1538
+			return;
1539
+		}
1540
+		// generate billing form for selected method of payment if it hasn't been done already
1541
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
+				$this->checkout->payment_method
1544
+			);
1545
+		}
1546
+		// generate primary attendee from payer info if applicable
1547
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1548
+			$attendee = $this->_create_attendee_from_request_data();
1549
+			if ($attendee instanceof EE_Attendee) {
1550
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1551
+					if ($registration->is_primary_registrant()) {
1552
+						$this->checkout->primary_attendee_obj = $attendee;
1553
+						$registration->_add_relation_to($attendee, 'Attendee');
1554
+						$registration->set_attendee_id($attendee->ID());
1555
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1556
+					}
1557
+				}
1558
+			}
1559
+		}
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * create_attendee_from_request_data
1565
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
+	 *
1567
+	 * @return EE_Attendee
1568
+	 * @throws EE_Error
1569
+	 * @throws InvalidArgumentException
1570
+	 * @throws ReflectionException
1571
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
+	 */
1574
+	protected function _create_attendee_from_request_data()
1575
+	{
1576
+		// get State ID
1577
+		$STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
+		if (! empty($STA_ID)) {
1579
+			// can we get state object from name ?
1580
+			EE_Registry::instance()->load_model('State');
1581
+			$state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
+		}
1584
+		// get Country ISO
1585
+		$CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
+		if (! empty($CNT_ISO)) {
1587
+			// can we get country object from name ?
1588
+			EE_Registry::instance()->load_model('Country');
1589
+			$country = EEM_Country::instance()->get_col(
1590
+				array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
+				'CNT_ISO'
1592
+			);
1593
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
+		}
1595
+		// grab attendee data
1596
+		$attendee_data = array(
1597
+			'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
+			'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
+			'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
+			'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
+			'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
+			'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
+			'STA_ID'       => $STA_ID,
1604
+			'CNT_ISO'      => $CNT_ISO,
1605
+			'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
+			'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
+		);
1608
+		// validate the email address since it is the most important piece of info
1609
+		if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
+			EE_Error::add_error(
1611
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
+				__FILE__,
1613
+				__FUNCTION__,
1614
+				__LINE__
1615
+			);
1616
+		}
1617
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
+		// AND email address
1619
+		if (! empty($attendee_data['ATT_fname'])
1620
+			&& ! empty($attendee_data['ATT_lname'])
1621
+			&& ! empty($attendee_data['ATT_email'])
1622
+		) {
1623
+			$existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
+				array(
1625
+					'ATT_fname' => $attendee_data['ATT_fname'],
1626
+					'ATT_lname' => $attendee_data['ATT_lname'],
1627
+					'ATT_email' => $attendee_data['ATT_email'],
1628
+				)
1629
+			);
1630
+			if ($existing_attendee instanceof EE_Attendee) {
1631
+				return $existing_attendee;
1632
+			}
1633
+		}
1634
+		// no existing attendee? kk let's create a new one
1635
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
+		// don't exist
1637
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
+			? $attendee_data['ATT_fname']
1639
+			: $attendee_data['ATT_email'];
1640
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
+			? $attendee_data['ATT_lname']
1642
+			: $attendee_data['ATT_email'];
1643
+		return EE_Attendee::new_instance($attendee_data);
1644
+	}
1645
+
1646
+
1647
+
1648
+	/********************************************************************************************************/
1649
+	/****************************************  PROCESS REG STEP  *****************************************/
1650
+	/********************************************************************************************************/
1651
+	/**
1652
+	 * process_reg_step
1653
+	 *
1654
+	 * @return bool
1655
+	 * @throws EE_Error
1656
+	 * @throws InvalidArgumentException
1657
+	 * @throws ReflectionException
1658
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
+	 */
1663
+	public function process_reg_step()
1664
+	{
1665
+		// how have they chosen to pay?
1666
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
+			? 'no_payment_required'
1668
+			: $this->_get_selected_method_of_payment(true);
1669
+		// choose your own adventure based on method_of_payment
1670
+		switch ($this->checkout->selected_method_of_payment) {
1671
+
1672
+			case 'events_sold_out' :
1673
+				$this->checkout->redirect     = true;
1674
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
+				// mark this reg step as completed
1677
+				$this->set_completed();
1678
+				return false;
1679
+				break;
1680
+
1681
+			case 'payments_closed' :
1682
+				if (apply_filters(
1683
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
+					false
1685
+				)) {
1686
+					EE_Error::add_success(
1687
+						esc_html__('no payment required at this time.', 'event_espresso'),
1688
+						__FILE__,
1689
+						__FUNCTION__,
1690
+						__LINE__
1691
+					);
1692
+				}
1693
+				// mark this reg step as completed
1694
+				$this->set_completed();
1695
+				return true;
1696
+				break;
1697
+
1698
+			case 'no_payment_required' :
1699
+				if (apply_filters(
1700
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
+					false
1702
+				)) {
1703
+					EE_Error::add_success(
1704
+						esc_html__('no payment required.', 'event_espresso'),
1705
+						__FILE__,
1706
+						__FUNCTION__,
1707
+						__LINE__
1708
+					);
1709
+				}
1710
+				// mark this reg step as completed
1711
+				$this->set_completed();
1712
+				return true;
1713
+				break;
1714
+
1715
+			default:
1716
+				$registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
+				);
1719
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
+					$registrations,
1721
+					EE_Registry::instance()->SSN->checkout()->revisit
1722
+				);
1723
+				// calculate difference between the two arrays
1724
+				$registrations = array_diff($registrations, $ejected_registrations);
1725
+				if (empty($registrations)) {
1726
+					$this->_redirect_because_event_sold_out();
1727
+					return false;
1728
+				}
1729
+				$payment_successful = $this->_process_payment();
1730
+				if ($payment_successful) {
1731
+					$this->checkout->continue_reg = true;
1732
+					$this->_maybe_set_completed($this->checkout->payment_method);
1733
+				} else {
1734
+					$this->checkout->continue_reg = false;
1735
+				}
1736
+				return $payment_successful;
1737
+		}
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * _redirect_because_event_sold_out
1743
+	 *
1744
+	 * @access protected
1745
+	 * @return void
1746
+	 */
1747
+	protected function _redirect_because_event_sold_out()
1748
+	{
1749
+		$this->checkout->continue_reg = false;
1750
+		// set redirect URL
1751
+		$this->checkout->redirect_url = add_query_arg(
1752
+			array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
+			$this->checkout->current_step->reg_step_url()
1754
+		);
1755
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * _maybe_set_completed
1761
+	 *
1762
+	 * @access protected
1763
+	 * @param \EE_Payment_Method $payment_method
1764
+	 * @return void
1765
+	 * @throws \EE_Error
1766
+	 */
1767
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
+	{
1769
+		switch ($payment_method->type_obj()->payment_occurs()) {
1770
+			case EE_PMT_Base::offsite :
1771
+				break;
1772
+			case EE_PMT_Base::onsite :
1773
+			case EE_PMT_Base::offline :
1774
+				// mark this reg step as completed
1775
+				$this->set_completed();
1776
+				break;
1777
+		}
1778
+	}
1779
+
1780
+
1781
+	/**
1782
+	 *    update_reg_step
1783
+	 *    this is the final step after a user  revisits the site to retry a payment
1784
+	 *
1785
+	 * @return bool
1786
+	 * @throws EE_Error
1787
+	 * @throws InvalidArgumentException
1788
+	 * @throws ReflectionException
1789
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
+	 */
1794
+	public function update_reg_step()
1795
+	{
1796
+		$success = true;
1797
+		// if payment required
1798
+		if ($this->checkout->transaction->total() > 0) {
1799
+			do_action(
1800
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
+				$this->checkout->transaction
1802
+			);
1803
+			// attempt payment via payment method
1804
+			$success = $this->process_reg_step();
1805
+		}
1806
+		if ($success && ! $this->checkout->redirect) {
1807
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
+				$this->checkout->transaction->ID()
1809
+			);
1810
+			// set return URL
1811
+			$this->checkout->redirect_url = add_query_arg(
1812
+				array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
+				$this->checkout->thank_you_page_url
1814
+			);
1815
+		}
1816
+		return $success;
1817
+	}
1818
+
1819
+
1820
+	/**
1821
+	 *    _process_payment
1822
+	 *
1823
+	 * @access private
1824
+	 * @return bool
1825
+	 * @throws EE_Error
1826
+	 * @throws InvalidArgumentException
1827
+	 * @throws ReflectionException
1828
+	 * @throws RuntimeException
1829
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
+	 */
1832
+	private function _process_payment()
1833
+	{
1834
+		// basically confirm that the event hasn't sold out since they hit the page
1835
+		if (! $this->_last_second_ticket_verifications()) {
1836
+			return false;
1837
+		}
1838
+		// ya gotta make a choice man
1839
+		if (empty($this->checkout->selected_method_of_payment)) {
1840
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1841
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
+			);
1843
+			return false;
1844
+		}
1845
+		// get EE_Payment_Method object
1846
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
+			return false;
1848
+		}
1849
+		// setup billing form
1850
+		if ($this->checkout->payment_method->is_on_site()) {
1851
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
+				$this->checkout->payment_method
1853
+			);
1854
+			// bad billing form ?
1855
+			if (! $this->_billing_form_is_valid()) {
1856
+				return false;
1857
+			}
1858
+		}
1859
+		// ensure primary registrant has been fully processed
1860
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
+			return false;
1862
+		}
1863
+		// if session is close to expiring (under 10 minutes by default)
1864
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
+			// add some time to session expiration so that payment can be completed
1866
+			EE_Registry::instance()->SSN->extend_expiration();
1867
+		}
1868
+		/** @type EE_Transaction_Processor $transaction_processor */
1869
+		//$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
+		// for events with a default reg status of Approved
1872
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
+		// );
1875
+		// attempt payment
1876
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1877
+		// process results
1878
+		$payment = $this->_validate_payment($payment);
1879
+		$payment = $this->_post_payment_processing($payment);
1880
+		// verify payment
1881
+		if ($payment instanceof EE_Payment) {
1882
+			// store that for later
1883
+			$this->checkout->payment = $payment;
1884
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
+			$this->checkout->transaction->toggle_failed_transaction_status();
1886
+			$payment_status = $payment->status();
1887
+			if (
1888
+				$payment_status === EEM_Payment::status_id_approved
1889
+				|| $payment_status === EEM_Payment::status_id_pending
1890
+			) {
1891
+				return true;
1892
+			} else {
1893
+				return false;
1894
+			}
1895
+		} else if ($payment === true) {
1896
+			// please note that offline payment methods will NOT make a payment,
1897
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
+			$this->checkout->payment = $payment;
1899
+			return true;
1900
+		}
1901
+		// where's my money?
1902
+		return false;
1903
+	}
1904
+
1905
+
1906
+	/**
1907
+	 * _last_second_ticket_verifications
1908
+	 *
1909
+	 * @access public
1910
+	 * @return bool
1911
+	 * @throws EE_Error
1912
+	 */
1913
+	protected function _last_second_ticket_verifications()
1914
+	{
1915
+		// don't bother re-validating if not a return visit
1916
+		if (! $this->checkout->revisit) {
1917
+			return true;
1918
+		}
1919
+		$registrations = $this->checkout->transaction->registrations();
1920
+		if (empty($registrations)) {
1921
+			return false;
1922
+		}
1923
+		foreach ($registrations as $registration) {
1924
+			if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1925
+				$event = $registration->event_obj();
1926
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
+					EE_Error::add_error(
1928
+						apply_filters(
1929
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
+							sprintf(
1931
+								esc_html__(
1932
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
+									'event_espresso'
1934
+								),
1935
+								$event->name()
1936
+							)
1937
+						),
1938
+						__FILE__,
1939
+						__FUNCTION__,
1940
+						__LINE__
1941
+					);
1942
+					return false;
1943
+				}
1944
+			}
1945
+		}
1946
+		return true;
1947
+	}
1948
+
1949
+
1950
+	/**
1951
+	 * redirect_form
1952
+	 *
1953
+	 * @access public
1954
+	 * @return bool
1955
+	 * @throws EE_Error
1956
+	 * @throws InvalidArgumentException
1957
+	 * @throws ReflectionException
1958
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
+	 */
1961
+	public function redirect_form()
1962
+	{
1963
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1964
+			$this->_get_payment_method_for_selected_method_of_payment()
1965
+		);
1966
+		$html                        = $payment_method_billing_info->get_html();
1967
+		$html                        .= $this->checkout->redirect_form;
1968
+		EE_Registry::instance()->REQ->add_output($html);
1969
+		return true;
1970
+	}
1971
+
1972
+
1973
+	/**
1974
+	 * _billing_form_is_valid
1975
+	 *
1976
+	 * @access private
1977
+	 * @return bool
1978
+	 * @throws \EE_Error
1979
+	 */
1980
+	private function _billing_form_is_valid()
1981
+	{
1982
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
+			return true;
1984
+		}
1985
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
+			if ($this->checkout->billing_form->was_submitted()) {
1987
+				$this->checkout->billing_form->receive_form_submission();
1988
+				if ($this->checkout->billing_form->is_valid()) {
1989
+					return true;
1990
+				}
1991
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
+				$error_strings     = array();
1993
+				foreach ($validation_errors as $validation_error) {
1994
+					if ($validation_error instanceof EE_Validation_Error) {
1995
+						$form_section = $validation_error->get_form_section();
1996
+						if ($form_section instanceof EE_Form_Input_Base) {
1997
+							$label = $form_section->html_label_text();
1998
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
1999
+							$label = $form_section->name();
2000
+						} else {
2001
+							$label = esc_html__('Validation Error', 'event_espresso');
2002
+						}
2003
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
+					}
2005
+				}
2006
+				EE_Error::add_error(
2007
+					sprintf(
2008
+						esc_html__(
2009
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
+							'event_espresso'
2011
+						),
2012
+						'<br/>',
2013
+						implode('<br/>', $error_strings)
2014
+					),
2015
+					__FILE__,
2016
+					__FUNCTION__,
2017
+					__LINE__
2018
+				);
2019
+			} else {
2020
+				EE_Error::add_error(
2021
+					esc_html__(
2022
+						'The billing form was not submitted or something prevented it\'s submission.',
2023
+						'event_espresso'
2024
+					),
2025
+					__FILE__,
2026
+					__FUNCTION__,
2027
+					__LINE__
2028
+				);
2029
+			}
2030
+		} else {
2031
+			EE_Error::add_error(
2032
+				esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
+				__FILE__,
2034
+				__FUNCTION__,
2035
+				__LINE__
2036
+			);
2037
+		}
2038
+		return false;
2039
+	}
2040
+
2041
+
2042
+	/**
2043
+	 * _setup_primary_registrant_prior_to_payment
2044
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
+	 * yet)
2048
+	 *
2049
+	 * @access private
2050
+	 * @return bool
2051
+	 * @throws EE_Error
2052
+	 * @throws InvalidArgumentException
2053
+	 * @throws ReflectionException
2054
+	 * @throws RuntimeException
2055
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
+	 */
2058
+	private function _setup_primary_registrant_prior_to_payment()
2059
+	{
2060
+		// check if transaction has a primary registrant and that it has a related Attendee object
2061
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2062
+		if (
2063
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
+			&& ! $this->checkout->transaction_has_primary_registrant()
2065
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2066
+		) {
2067
+			return false;
2068
+		}
2069
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2070
+		// grab the primary_registration object
2071
+		$primary_registration = $this->checkout->transaction->primary_registration();
2072
+		// at this point we'll consider a TXN to not have been failed
2073
+		$this->checkout->transaction->toggle_failed_transaction_status();
2074
+		// save the TXN ( which clears cached copy of primary_registration)
2075
+		$this->checkout->transaction->save();
2076
+		// grab TXN ID and save it to the primary_registration
2077
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
+		// save what we have so far
2079
+		$primary_registration->save();
2080
+		return true;
2081
+	}
2082
+
2083
+
2084
+	/**
2085
+	 * _capture_primary_registration_data_from_billing_form
2086
+	 *
2087
+	 * @access private
2088
+	 * @return bool
2089
+	 * @throws EE_Error
2090
+	 * @throws InvalidArgumentException
2091
+	 * @throws ReflectionException
2092
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
+	 */
2095
+	private function _capture_primary_registration_data_from_billing_form()
2096
+	{
2097
+		// convert billing form data into an attendee
2098
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
+			EE_Error::add_error(
2101
+				sprintf(
2102
+					esc_html__(
2103
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
+						'event_espresso'
2105
+					),
2106
+					'<br/>',
2107
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
+				),
2109
+				__FILE__,
2110
+				__FUNCTION__,
2111
+				__LINE__
2112
+			);
2113
+			return false;
2114
+		}
2115
+		$primary_registration = $this->checkout->transaction->primary_registration();
2116
+		if (! $primary_registration instanceof EE_Registration) {
2117
+			EE_Error::add_error(
2118
+				sprintf(
2119
+					esc_html__(
2120
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
+						'event_espresso'
2122
+					),
2123
+					'<br/>',
2124
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
+				),
2126
+				__FILE__,
2127
+				__FUNCTION__,
2128
+				__LINE__
2129
+			);
2130
+			return false;
2131
+		}
2132
+		if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
+			  instanceof
2134
+			  EE_Attendee
2135
+		) {
2136
+			EE_Error::add_error(
2137
+				sprintf(
2138
+					esc_html__(
2139
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
+						'event_espresso'
2141
+					),
2142
+					'<br/>',
2143
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
+				),
2145
+				__FILE__,
2146
+				__FUNCTION__,
2147
+				__LINE__
2148
+			);
2149
+			return false;
2150
+		}
2151
+		/** @type EE_Registration_Processor $registration_processor */
2152
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
+		return true;
2156
+	}
2157
+
2158
+
2159
+	/**
2160
+	 * _get_payment_method_for_selected_method_of_payment
2161
+	 * retrieves a valid payment method
2162
+	 *
2163
+	 * @access public
2164
+	 * @return EE_Payment_Method
2165
+	 * @throws EE_Error
2166
+	 * @throws InvalidArgumentException
2167
+	 * @throws ReflectionException
2168
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
+	 */
2171
+	private function _get_payment_method_for_selected_method_of_payment()
2172
+	{
2173
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
+			$this->_redirect_because_event_sold_out();
2175
+			return null;
2176
+		}
2177
+		// get EE_Payment_Method object
2178
+		if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
+			$payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
+		} else {
2181
+			// load EEM_Payment_Method
2182
+			EE_Registry::instance()->load_model('Payment_Method');
2183
+			/** @type EEM_Payment_Method $EEM_Payment_Method */
2184
+			$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
+			$payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
+		}
2187
+		// verify $payment_method
2188
+		if (! $payment_method instanceof EE_Payment_Method) {
2189
+			// not a payment
2190
+			EE_Error::add_error(
2191
+				sprintf(
2192
+					esc_html__(
2193
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
+						'event_espresso'
2195
+					),
2196
+					'<br/>',
2197
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
+				),
2199
+				__FILE__,
2200
+				__FUNCTION__,
2201
+				__LINE__
2202
+			);
2203
+			return null;
2204
+		}
2205
+		// and verify it has a valid Payment_Method Type object
2206
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
+			// not a payment
2208
+			EE_Error::add_error(
2209
+				sprintf(
2210
+					esc_html__(
2211
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
+						'event_espresso'
2213
+					),
2214
+					'<br/>',
2215
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
+				),
2217
+				__FILE__,
2218
+				__FUNCTION__,
2219
+				__LINE__
2220
+			);
2221
+			return null;
2222
+		}
2223
+		return $payment_method;
2224
+	}
2225
+
2226
+
2227
+	/**
2228
+	 *    _attempt_payment
2229
+	 *
2230
+	 * @access    private
2231
+	 * @type    EE_Payment_Method $payment_method
2232
+	 * @return mixed EE_Payment | boolean
2233
+	 * @throws EE_Error
2234
+	 * @throws InvalidArgumentException
2235
+	 * @throws ReflectionException
2236
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
+	 */
2239
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2240
+	{
2241
+		$payment = null;
2242
+		$this->checkout->transaction->save();
2243
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2245
+			return false;
2246
+		}
2247
+		try {
2248
+			$payment_processor->set_revisit($this->checkout->revisit);
2249
+			// generate payment object
2250
+			$payment = $payment_processor->process_payment(
2251
+				$payment_method,
2252
+				$this->checkout->transaction,
2253
+				$this->checkout->amount_owing,
2254
+				$this->checkout->billing_form,
2255
+				$this->_get_return_url($payment_method),
2256
+				'CART',
2257
+				$this->checkout->admin_request,
2258
+				true,
2259
+				$this->reg_step_url()
2260
+			);
2261
+		} catch (Exception $e) {
2262
+			$this->_handle_payment_processor_exception($e);
2263
+		}
2264
+		return $payment;
2265
+	}
2266
+
2267
+
2268
+	/**
2269
+	 * _handle_payment_processor_exception
2270
+	 *
2271
+	 * @access protected
2272
+	 * @param \Exception $e
2273
+	 * @return void
2274
+	 * @throws EE_Error
2275
+	 * @throws InvalidArgumentException
2276
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
+	 */
2279
+	protected function _handle_payment_processor_exception(Exception $e)
2280
+	{
2281
+		EE_Error::add_error(
2282
+			sprintf(
2283
+				esc_html__(
2284
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
+					'event_espresso'
2286
+				),
2287
+				'<br/>',
2288
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
+				$e->getMessage(),
2290
+				$e->getFile(),
2291
+				$e->getLine()
2292
+			),
2293
+			__FILE__,
2294
+			__FUNCTION__,
2295
+			__LINE__
2296
+		);
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _get_return_url
2302
+	 *
2303
+	 * @access protected
2304
+	 * @param \EE_Payment_Method $payment_method
2305
+	 * @return string
2306
+	 * @throws \EE_Error
2307
+	 */
2308
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2309
+	{
2310
+		$return_url = '';
2311
+		switch ($payment_method->type_obj()->payment_occurs()) {
2312
+			case EE_PMT_Base::offsite :
2313
+				$return_url = add_query_arg(
2314
+					array(
2315
+						'action'                     => 'process_gateway_response',
2316
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2318
+					),
2319
+					$this->reg_step_url()
2320
+				);
2321
+				break;
2322
+			case EE_PMT_Base::onsite :
2323
+			case EE_PMT_Base::offline :
2324
+				$return_url = $this->checkout->next_step->reg_step_url();
2325
+				break;
2326
+		}
2327
+		return $return_url;
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * _validate_payment
2333
+	 *
2334
+	 * @access private
2335
+	 * @param EE_Payment $payment
2336
+	 * @return EE_Payment|FALSE
2337
+	 * @throws EE_Error
2338
+	 * @throws InvalidArgumentException
2339
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
+	 */
2342
+	private function _validate_payment($payment = null)
2343
+	{
2344
+		if ($this->checkout->payment_method->is_off_line()) {
2345
+			return true;
2346
+		}
2347
+		// verify payment object
2348
+		if (! $payment instanceof EE_Payment) {
2349
+			// not a payment
2350
+			EE_Error::add_error(
2351
+				sprintf(
2352
+					esc_html__(
2353
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
+						'event_espresso'
2355
+					),
2356
+					'<br/>',
2357
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
+				),
2359
+				__FILE__,
2360
+				__FUNCTION__,
2361
+				__LINE__
2362
+			);
2363
+			return false;
2364
+		}
2365
+		return $payment;
2366
+	}
2367
+
2368
+
2369
+	/**
2370
+	 * _post_payment_processing
2371
+	 *
2372
+	 * @access private
2373
+	 * @param EE_Payment|bool $payment
2374
+	 * @return bool
2375
+	 * @throws EE_Error
2376
+	 * @throws InvalidArgumentException
2377
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
+	 */
2380
+	private function _post_payment_processing($payment = null)
2381
+	{
2382
+		// Off-Line payment?
2383
+		if ($payment === true) {
2384
+			//$this->_setup_redirect_for_next_step();
2385
+			return true;
2386
+			// On-Site payment?
2387
+		} else if ($this->checkout->payment_method->is_on_site()) {
2388
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
+				//$this->_setup_redirect_for_next_step();
2390
+				$this->checkout->continue_reg = false;
2391
+			}
2392
+			// Off-Site payment?
2393
+		} else if ($this->checkout->payment_method->is_off_site()) {
2394
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
+				$this->checkout->redirect      = true;
2398
+				$this->checkout->redirect_form = $payment->redirect_form();
2399
+				$this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
+				// set JSON response
2401
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
+				// and lastly, let's bump the payment status to pending
2403
+				$payment->set_status(EEM_Payment::status_id_pending);
2404
+				$payment->save();
2405
+			} else {
2406
+				// not a payment
2407
+				$this->checkout->continue_reg = false;
2408
+				EE_Error::add_error(
2409
+					sprintf(
2410
+						esc_html__(
2411
+							'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
+							'event_espresso'
2413
+						),
2414
+						'<br/>',
2415
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
+					),
2417
+					__FILE__,
2418
+					__FUNCTION__,
2419
+					__LINE__
2420
+				);
2421
+			}
2422
+		} else {
2423
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
+			$this->checkout->continue_reg = false;
2425
+			return false;
2426
+		}
2427
+		return $payment;
2428
+	}
2429
+
2430
+
2431
+	/**
2432
+	 *    _process_payment_status
2433
+	 *
2434
+	 * @access private
2435
+	 * @type    EE_Payment $payment
2436
+	 * @param string       $payment_occurs
2437
+	 * @return bool
2438
+	 * @throws EE_Error
2439
+	 * @throws InvalidArgumentException
2440
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
+	 */
2443
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
+	{
2445
+		// off-line payment? carry on
2446
+		if ($payment_occurs === EE_PMT_Base::offline) {
2447
+			return true;
2448
+		}
2449
+		// verify payment validity
2450
+		if ($payment instanceof EE_Payment) {
2451
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
+			$msg = $payment->gateway_response();
2453
+			// check results
2454
+			switch ($payment->status()) {
2455
+				// good payment
2456
+				case EEM_Payment::status_id_approved :
2457
+					EE_Error::add_success(
2458
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
+						__FILE__,
2460
+						__FUNCTION__,
2461
+						__LINE__
2462
+					);
2463
+					return true;
2464
+					break;
2465
+				// slow payment
2466
+				case EEM_Payment::status_id_pending :
2467
+					if (empty($msg)) {
2468
+						$msg = esc_html__(
2469
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
+							'event_espresso'
2471
+						);
2472
+					}
2473
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
+					return true;
2475
+					break;
2476
+				// don't wanna payment
2477
+				case EEM_Payment::status_id_cancelled :
2478
+					if (empty($msg)) {
2479
+						$msg = _n(
2480
+							'Payment cancelled. Please try again.',
2481
+							'Payment cancelled. Please try again or select another method of payment.',
2482
+							count($this->checkout->available_payment_methods),
2483
+							'event_espresso'
2484
+						);
2485
+					}
2486
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
+					return false;
2488
+					break;
2489
+				// not enough payment
2490
+				case EEM_Payment::status_id_declined :
2491
+					if (empty($msg)) {
2492
+						$msg = _n(
2493
+							'We\'re sorry but your payment was declined. Please try again.',
2494
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
+							count($this->checkout->available_payment_methods),
2496
+							'event_espresso'
2497
+						);
2498
+					}
2499
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
+					return false;
2501
+					break;
2502
+				// bad payment
2503
+				case EEM_Payment::status_id_failed :
2504
+					if (! empty($msg)) {
2505
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
+						return false;
2507
+					}
2508
+					// default to error below
2509
+					break;
2510
+			}
2511
+		}
2512
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2513
+		// the payment processing is just running slower than the registrant's request
2514
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2515
+			return true;
2516
+		}
2517
+		EE_Error::add_error(
2518
+			sprintf(
2519
+				esc_html__(
2520
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
+					'event_espresso'
2522
+				),
2523
+				'<br/>',
2524
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
+			),
2526
+			__FILE__,
2527
+			__FUNCTION__,
2528
+			__LINE__
2529
+		);
2530
+		return false;
2531
+	}
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+	/********************************************************************************************************/
2539
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
+	/********************************************************************************************************/
2541
+	/**
2542
+	 * process_gateway_response
2543
+	 * this is the return point for Off-Site Payment Methods
2544
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
+	 * otherwise, it will load up the last payment made for the TXN.
2546
+	 * If the payment retrieved looks good, it will then either:
2547
+	 *    complete the current step and allow advancement to the next reg step
2548
+	 *        or present the payment options again
2549
+	 *
2550
+	 * @access private
2551
+	 * @return EE_Payment|FALSE
2552
+	 * @throws EE_Error
2553
+	 * @throws InvalidArgumentException
2554
+	 * @throws ReflectionException
2555
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
+	 */
2559
+	public function process_gateway_response()
2560
+	{
2561
+		$payment = null;
2562
+		// how have they chosen to pay?
2563
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
+		// get EE_Payment_Method object
2565
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
+			$this->checkout->continue_reg = false;
2567
+			return false;
2568
+		}
2569
+		if (! $this->checkout->payment_method->is_off_site()) {
2570
+			return false;
2571
+		}
2572
+		$this->_validate_offsite_return();
2573
+		// DEBUG LOG
2574
+		//$this->checkout->log(
2575
+		//	__CLASS__, __FUNCTION__, __LINE__,
2576
+		//	array(
2577
+		//		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
+		//		'payment_method' => $this->checkout->payment_method,
2579
+		//	),
2580
+		//	true
2581
+		//);
2582
+		// verify TXN
2583
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2584
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2586
+				$this->checkout->continue_reg = false;
2587
+				return false;
2588
+			}
2589
+			$payment = $this->_process_off_site_payment($gateway);
2590
+			$payment = $this->_process_cancelled_payments($payment);
2591
+			$payment = $this->_validate_payment($payment);
2592
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2593
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
+				//$this->_setup_redirect_for_next_step();
2595
+				// store that for later
2596
+				$this->checkout->payment = $payment;
2597
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
+				// because we will complete this step during the IPN processing then
2599
+				if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
+					$this->set_completed();
2601
+				}
2602
+				return true;
2603
+			}
2604
+		}
2605
+		// DEBUG LOG
2606
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
+		//	array( 'payment' => $payment )
2608
+		//);
2609
+		$this->checkout->continue_reg = false;
2610
+		return false;
2611
+	}
2612
+
2613
+
2614
+	/**
2615
+	 * _validate_return
2616
+	 *
2617
+	 * @access private
2618
+	 * @return void
2619
+	 * @throws EE_Error
2620
+	 * @throws InvalidArgumentException
2621
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
+	 */
2625
+	private function _validate_offsite_return()
2626
+	{
2627
+		$TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
+			// Houston... we might have a problem
2630
+			$invalid_TXN = false;
2631
+			// first gather some info
2632
+			$valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2634
+				? $valid_TXN->primary_registration()
2635
+				: null;
2636
+			// let's start by retrieving the cart for this TXN
2637
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
+			if ($cart instanceof EE_Cart) {
2639
+				// verify that the current cart has tickets
2640
+				$tickets = $cart->get_tickets();
2641
+				if (empty($tickets)) {
2642
+					$invalid_TXN = true;
2643
+				}
2644
+			} else {
2645
+				$invalid_TXN = true;
2646
+			}
2647
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
+				? $primary_registrant->session_ID()
2649
+				: null;
2650
+			// validate current Session ID and compare against valid TXN session ID
2651
+			if (
2652
+				$invalid_TXN // if this is already true, then skip other checks
2653
+				|| EE_Session::instance()->id() === null
2654
+				|| (
2655
+					// WARNING !!!
2656
+					// this could be PayPal sending back duplicate requests (ya they do that)
2657
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2658
+					// so now we need to determine if this current TXN looks valid or not
2659
+					// and whether this reg step has even been started ?
2660
+					EE_Session::instance()->id() === $valid_TXN_SID
2661
+					// really? you're half way through this reg step, but you never started it ?
2662
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
+				)
2664
+			) {
2665
+				$invalid_TXN = true;
2666
+			}
2667
+			if ($invalid_TXN) {
2668
+				// is the valid TXN completed ?
2669
+				if ($valid_TXN instanceof EE_Transaction) {
2670
+					// has this step even been started ?
2671
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
+						// so it **looks** like this is a double request from PayPal
2674
+						// so let's try to pick up where we left off
2675
+						$this->checkout->transaction = $valid_TXN;
2676
+						$this->checkout->refresh_all_entities(true);
2677
+						return;
2678
+					}
2679
+				}
2680
+				// you appear to be lost?
2681
+				$this->_redirect_wayward_request($primary_registrant);
2682
+			}
2683
+		}
2684
+	}
2685
+
2686
+
2687
+	/**
2688
+	 * _redirect_wayward_request
2689
+	 *
2690
+	 * @access private
2691
+	 * @param \EE_Registration|null $primary_registrant
2692
+	 * @return bool
2693
+	 * @throws EE_Error
2694
+	 * @throws InvalidArgumentException
2695
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
+	 */
2698
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
+	{
2700
+		if (! $primary_registrant instanceof EE_Registration) {
2701
+			// try redirecting based on the current TXN
2702
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
+				? $this->checkout->transaction->primary_registration()
2704
+				: null;
2705
+		}
2706
+		if (! $primary_registrant instanceof EE_Registration) {
2707
+			EE_Error::add_error(
2708
+				sprintf(
2709
+					esc_html__(
2710
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
+						'event_espresso'
2712
+					),
2713
+					'<br/>',
2714
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
+				),
2716
+				__FILE__,
2717
+				__FUNCTION__,
2718
+				__LINE__
2719
+			);
2720
+			return false;
2721
+		}
2722
+		// make sure transaction is not locked
2723
+		$this->checkout->transaction->unlock();
2724
+		wp_safe_redirect(
2725
+			add_query_arg(
2726
+				array(
2727
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
+				),
2729
+				$this->checkout->thank_you_page_url
2730
+			)
2731
+		);
2732
+		exit();
2733
+	}
2734
+
2735
+
2736
+	/**
2737
+	 * _process_off_site_payment
2738
+	 *
2739
+	 * @access private
2740
+	 * @param \EE_Offsite_Gateway $gateway
2741
+	 * @return EE_Payment
2742
+	 * @throws EE_Error
2743
+	 * @throws InvalidArgumentException
2744
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
+	 */
2747
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
+	{
2749
+		try {
2750
+			$request_data = \EE_Registry::instance()->REQ->params();
2751
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
+			$this->set_handle_IPN_in_this_request(
2753
+				$gateway->handle_IPN_in_this_request($request_data, false)
2754
+			);
2755
+			if ($this->handle_IPN_in_this_request()) {
2756
+				// get payment details and process results
2757
+				/** @type EE_Payment_Processor $payment_processor */
2758
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
+				$payment           = $payment_processor->process_ipn(
2760
+					$request_data,
2761
+					$this->checkout->transaction,
2762
+					$this->checkout->payment_method,
2763
+					true,
2764
+					false
2765
+				);
2766
+				//$payment_source = 'process_ipn';
2767
+			} else {
2768
+				$payment = $this->checkout->transaction->last_payment();
2769
+				//$payment_source = 'last_payment';
2770
+			}
2771
+		} catch (Exception $e) {
2772
+			// let's just eat the exception and try to move on using any previously set payment info
2773
+			$payment = $this->checkout->transaction->last_payment();
2774
+			//$payment_source = 'last_payment after Exception';
2775
+			// but if we STILL don't have a payment object
2776
+			if (! $payment instanceof EE_Payment) {
2777
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
+				$this->_handle_payment_processor_exception($e);
2779
+			}
2780
+		}
2781
+		// DEBUG LOG
2782
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
+		//	array(
2784
+		//		'process_ipn_payment' => $payment,
2785
+		//		'payment_source'      => $payment_source,
2786
+		//	)
2787
+		//);
2788
+		return $payment;
2789
+	}
2790
+
2791
+
2792
+	/**
2793
+	 * _process_cancelled_payments
2794
+	 * just makes sure that the payment status gets updated correctly
2795
+	 * so tha tan error isn't generated during payment validation
2796
+	 *
2797
+	 * @access private
2798
+	 * @param EE_Payment $payment
2799
+	 * @return EE_Payment | FALSE
2800
+	 * @throws \EE_Error
2801
+	 */
2802
+	private function _process_cancelled_payments($payment = null)
2803
+	{
2804
+		if (
2805
+			$payment instanceof EE_Payment
2806
+			&& isset($_REQUEST['ee_cancel_payment'])
2807
+			&& $payment->status() === EEM_Payment::status_id_failed
2808
+		) {
2809
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2810
+		}
2811
+		return $payment;
2812
+	}
2813
+
2814
+
2815
+	/**
2816
+	 *    get_transaction_details_for_gateways
2817
+	 *
2818
+	 * @access    public
2819
+	 * @return int
2820
+	 * @throws EE_Error
2821
+	 * @throws InvalidArgumentException
2822
+	 * @throws ReflectionException
2823
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
+	 */
2826
+	public function get_transaction_details_for_gateways()
2827
+	{
2828
+		$txn_details = array();
2829
+		// ya gotta make a choice man
2830
+		if (empty($this->checkout->selected_method_of_payment)) {
2831
+			$txn_details = array(
2832
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
+			);
2834
+		}
2835
+		// get EE_Payment_Method object
2836
+		if (
2837
+			empty($txn_details)
2838
+			&&
2839
+			! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
+		) {
2841
+			$txn_details = array(
2842
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
+				'error'                      => esc_html__(
2844
+					'A valid Payment Method could not be determined.',
2845
+					'event_espresso'
2846
+				),
2847
+			);
2848
+		}
2849
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
+			$return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
+			$txn_details = array(
2852
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2853
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
+				'TXN_total'      => $this->checkout->transaction->total(),
2855
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2856
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
+				'payment_amount' => $this->checkout->amount_owing,
2860
+				'return_url'     => $return_url,
2861
+				'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
+					array(
2864
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
+					)
2867
+				),
2868
+			);
2869
+		}
2870
+		echo wp_json_encode($txn_details);
2871
+		exit();
2872
+	}
2873
+
2874
+
2875
+	/**
2876
+	 *    __sleep
2877
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
+	 * reg form, because if needed, it will be regenerated anyways
2880
+	 *
2881
+	 * @return array
2882
+	 */
2883
+	public function __sleep()
2884
+	{
2885
+		// remove the reg form and the checkout
2886
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
+	}
2888 2888
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 1 patch
Indentation   +4124 added lines, -4124 removed lines patch added patch discarded remove patch
@@ -21,4209 +21,4209 @@
 block discarded – undo
21 21
 {
22 22
 
23 23
 
24
-    //set in _init_page_props()
25
-    public $page_slug;
24
+	//set in _init_page_props()
25
+	public $page_slug;
26 26
 
27
-    public $page_label;
27
+	public $page_label;
28 28
 
29
-    public $page_folder;
29
+	public $page_folder;
30 30
 
31
-    //set in define_page_props()
32
-    protected $_admin_base_url;
31
+	//set in define_page_props()
32
+	protected $_admin_base_url;
33 33
 
34
-    protected $_admin_base_path;
34
+	protected $_admin_base_path;
35 35
 
36
-    protected $_admin_page_title;
36
+	protected $_admin_page_title;
37 37
 
38
-    protected $_labels;
38
+	protected $_labels;
39 39
 
40 40
 
41
-    //set early within EE_Admin_Init
42
-    protected $_wp_page_slug;
41
+	//set early within EE_Admin_Init
42
+	protected $_wp_page_slug;
43 43
 
44
-    //navtabs
45
-    protected $_nav_tabs;
44
+	//navtabs
45
+	protected $_nav_tabs;
46 46
 
47
-    protected $_default_nav_tab_name;
47
+	protected $_default_nav_tab_name;
48 48
 
49
-    /**
50
-     * @var array $_help_tour
51
-     */
52
-    protected $_help_tour = array();
49
+	/**
50
+	 * @var array $_help_tour
51
+	 */
52
+	protected $_help_tour = array();
53 53
 
54 54
 
55
-    //template variables (used by templates)
56
-    protected $_template_path;
55
+	//template variables (used by templates)
56
+	protected $_template_path;
57 57
 
58
-    protected $_column_template_path;
58
+	protected $_column_template_path;
59 59
 
60
-    /**
61
-     * @var array $_template_args
62
-     */
63
-    protected $_template_args = array();
60
+	/**
61
+	 * @var array $_template_args
62
+	 */
63
+	protected $_template_args = array();
64 64
 
65
-    /**
66
-     * this will hold the list table object for a given view.
67
-     *
68
-     * @var EE_Admin_List_Table $_list_table_object
69
-     */
70
-    protected $_list_table_object;
65
+	/**
66
+	 * this will hold the list table object for a given view.
67
+	 *
68
+	 * @var EE_Admin_List_Table $_list_table_object
69
+	 */
70
+	protected $_list_table_object;
71 71
 
72
-    //bools
73
-    protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
72
+	//bools
73
+	protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
74 74
 
75
-    protected $_routing;
75
+	protected $_routing;
76 76
 
77
-    //list table args
78
-    protected $_view;
77
+	//list table args
78
+	protected $_view;
79 79
 
80
-    protected $_views;
80
+	protected $_views;
81 81
 
82 82
 
83
-    //action => method pairs used for routing incoming requests
84
-    protected $_page_routes;
83
+	//action => method pairs used for routing incoming requests
84
+	protected $_page_routes;
85 85
 
86
-    /**
87
-     * @var array $_page_config
88
-     */
89
-    protected $_page_config;
86
+	/**
87
+	 * @var array $_page_config
88
+	 */
89
+	protected $_page_config;
90 90
 
91
-    /**
92
-     * the current page route and route config
93
-     *
94
-     * @var string $_route
95
-     */
96
-    protected $_route;
91
+	/**
92
+	 * the current page route and route config
93
+	 *
94
+	 * @var string $_route
95
+	 */
96
+	protected $_route;
97 97
 
98
-    /**
99
-     * @var string $_cpt_route
100
-     */
101
-    protected $_cpt_route;
98
+	/**
99
+	 * @var string $_cpt_route
100
+	 */
101
+	protected $_cpt_route;
102 102
 
103
-    /**
104
-     * @var array $_route_config
105
-     */
106
-    protected $_route_config;
103
+	/**
104
+	 * @var array $_route_config
105
+	 */
106
+	protected $_route_config;
107 107
 
108
-    /**
109
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
110
-     * actions.
111
-     *
112
-     * @since 4.6.x
113
-     * @var array.
114
-     */
115
-    protected $_default_route_query_args;
116
-
117
-    //set via request page and action args.
118
-    protected $_current_page;
108
+	/**
109
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
110
+	 * actions.
111
+	 *
112
+	 * @since 4.6.x
113
+	 * @var array.
114
+	 */
115
+	protected $_default_route_query_args;
116
+
117
+	//set via request page and action args.
118
+	protected $_current_page;
119 119
 
120
-    protected $_current_view;
120
+	protected $_current_view;
121 121
 
122
-    protected $_current_page_view_url;
122
+	protected $_current_page_view_url;
123 123
 
124
-    //sanitized request action (and nonce)
124
+	//sanitized request action (and nonce)
125 125
 
126
-    /**
127
-     * @var string $_req_action
128
-     */
129
-    protected $_req_action;
130
-
131
-    /**
132
-     * @var string $_req_nonce
133
-     */
134
-    protected $_req_nonce;
135
-
136
-    //search related
137
-    protected $_search_btn_label;
138
-
139
-    protected $_search_box_callback;
140
-
141
-    /**
142
-     * WP Current Screen object
143
-     *
144
-     * @var WP_Screen
145
-     */
146
-    protected $_current_screen;
147
-
148
-    //for holding EE_Admin_Hooks object when needed (set via set_hook_object())
149
-    protected $_hook_obj;
150
-
151
-    //for holding incoming request data
152
-    protected $_req_data;
153
-
154
-    // yes / no array for admin form fields
155
-    protected $_yes_no_values = array();
156
-
157
-    //some default things shared by all child classes
158
-    protected $_default_espresso_metaboxes;
159
-
160
-    /**
161
-     *    EE_Registry Object
162
-     *
163
-     * @var    EE_Registry
164
-     */
165
-    protected $EE = null;
166
-
167
-
168
-
169
-    /**
170
-     * This is just a property that flags whether the given route is a caffeinated route or not.
171
-     *
172
-     * @var boolean
173
-     */
174
-    protected $_is_caf = false;
175
-
176
-
177
-
178
-    /**
179
-     * @Constructor
180
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
181
-     * @throws EE_Error
182
-     * @throws InvalidArgumentException
183
-     * @throws ReflectionException
184
-     * @throws InvalidDataTypeException
185
-     * @throws InvalidInterfaceException
186
-     */
187
-    public function __construct($routing = true)
188
-    {
189
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
-            $this->_is_caf = true;
191
-        }
192
-        $this->_yes_no_values = array(
193
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
-        );
196
-        //set the _req_data property.
197
-        $this->_req_data = array_merge($_GET, $_POST);
198
-        //routing enabled?
199
-        $this->_routing = $routing;
200
-        //set initial page props (child method)
201
-        $this->_init_page_props();
202
-        //set global defaults
203
-        $this->_set_defaults();
204
-        //set early because incoming requests could be ajax related and we need to register those hooks.
205
-        $this->_global_ajax_hooks();
206
-        $this->_ajax_hooks();
207
-        //other_page_hooks have to be early too.
208
-        $this->_do_other_page_hooks();
209
-        //This just allows us to have extending classes do something specific
210
-        // before the parent constructor runs _page_setup().
211
-        if (method_exists($this, '_before_page_setup')) {
212
-            $this->_before_page_setup();
213
-        }
214
-        //set up page dependencies
215
-        $this->_page_setup();
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     * _init_page_props
222
-     * Child classes use to set at least the following properties:
223
-     * $page_slug.
224
-     * $page_label.
225
-     *
226
-     * @abstract
227
-     * @return void
228
-     */
229
-    abstract protected function _init_page_props();
230
-
231
-
232
-
233
-    /**
234
-     * _ajax_hooks
235
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
236
-     * Note: within the ajax callback methods.
237
-     *
238
-     * @abstract
239
-     * @return void
240
-     */
241
-    abstract protected function _ajax_hooks();
242
-
243
-
244
-
245
-    /**
246
-     * _define_page_props
247
-     * child classes define page properties in here.  Must include at least:
248
-     * $_admin_base_url = base_url for all admin pages
249
-     * $_admin_page_title = default admin_page_title for admin pages
250
-     * $_labels = array of default labels for various automatically generated elements:
251
-     *    array(
252
-     *        'buttons' => array(
253
-     *            'add' => esc_html__('label for add new button'),
254
-     *            'edit' => esc_html__('label for edit button'),
255
-     *            'delete' => esc_html__('label for delete button')
256
-     *            )
257
-     *        )
258
-     *
259
-     * @abstract
260
-     * @return void
261
-     */
262
-    abstract protected function _define_page_props();
263
-
264
-
265
-
266
-    /**
267
-     * _set_page_routes
268
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
269
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
270
-     * have a 'default' route. Here's the format
271
-     * $this->_page_routes = array(
272
-     *        'default' => array(
273
-     *            'func' => '_default_method_handling_route',
274
-     *            'args' => array('array','of','args'),
275
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
276
-     *            ajax request, backend processing)
277
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
278
-     *            headers route after.  The string you enter here should match the defined route reference for a
279
-     *            headers sent route.
280
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
281
-     *            this route.
282
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
283
-     *            checks).
284
-     *        ),
285
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
286
-     *        handling method.
287
-     *        )
288
-     * )
289
-     *
290
-     * @abstract
291
-     * @return void
292
-     */
293
-    abstract protected function _set_page_routes();
294
-
295
-
296
-
297
-    /**
298
-     * _set_page_config
299
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
300
-     * array corresponds to the page_route for the loaded page. Format:
301
-     * $this->_page_config = array(
302
-     *        'default' => array(
303
-     *            'labels' => array(
304
-     *                'buttons' => array(
305
-     *                    'add' => esc_html__('label for adding item'),
306
-     *                    'edit' => esc_html__('label for editing item'),
307
-     *                    'delete' => esc_html__('label for deleting item')
308
-     *                ),
309
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
310
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
311
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
312
-     *            _define_page_props() method
313
-     *            'nav' => array(
314
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
315
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
316
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
317
-     *                'order' => 10, //required to indicate tab position.
318
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
319
-     *                displayed then add this parameter.
320
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
321
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
322
-     *            metaboxes set for eventespresso admin pages.
323
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
324
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
325
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
326
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
327
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
328
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
329
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
330
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
331
-     *            want to display.
332
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
333
-     *                'tab_id' => array(
334
-     *                    'title' => 'tab_title',
335
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
336
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
337
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
338
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
339
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
340
-     *                    attempt to use the callback which should match the name of a method in the class
341
-     *                    ),
342
-     *                'tab2_id' => array(
343
-     *                    'title' => 'tab2 title',
344
-     *                    'filename' => 'file_name_2'
345
-     *                    'callback' => 'callback_method_for_content',
346
-     *                 ),
347
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
348
-     *            help tab area on an admin page. @link
349
-     *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
350
-     *            'help_tour' => array(
351
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
352
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
353
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
354
-     *            ),
355
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
356
-     *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
357
-     *            just set
358
-     *            'require_nonce' to FALSE
359
-     *            )
360
-     * )
361
-     *
362
-     * @abstract
363
-     * @return void
364
-     */
365
-    abstract protected function _set_page_config();
366
-
367
-
368
-
369
-
370
-
371
-    /** end sample help_tour methods **/
372
-    /**
373
-     * _add_screen_options
374
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
375
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
376
-     * to a particular view.
377
-     *
378
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
379
-     *         see also WP_Screen object documents...
380
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
381
-     * @abstract
382
-     * @return void
383
-     */
384
-    abstract protected function _add_screen_options();
385
-
386
-
387
-
388
-    /**
389
-     * _add_feature_pointers
390
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
391
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
392
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
393
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
394
-     * extended) also see:
395
-     *
396
-     * @link   http://eamann.com/tech/wordpress-portland/
397
-     * @abstract
398
-     * @return void
399
-     */
400
-    abstract protected function _add_feature_pointers();
401
-
402
-
403
-
404
-    /**
405
-     * load_scripts_styles
406
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
407
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
408
-     * scripts/styles per view by putting them in a dynamic function in this format
409
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
410
-     *
411
-     * @abstract
412
-     * @return void
413
-     */
414
-    abstract public function load_scripts_styles();
415
-
416
-
417
-
418
-    /**
419
-     * admin_init
420
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
421
-     * all pages/views loaded by child class.
422
-     *
423
-     * @abstract
424
-     * @return void
425
-     */
426
-    abstract public function admin_init();
427
-
428
-
429
-
430
-    /**
431
-     * admin_notices
432
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
433
-     * all pages/views loaded by child class.
434
-     *
435
-     * @abstract
436
-     * @return void
437
-     */
438
-    abstract public function admin_notices();
439
-
440
-
441
-
442
-    /**
443
-     * admin_footer_scripts
444
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
445
-     * will apply to all pages/views loaded by child class.
446
-     *
447
-     * @return void
448
-     */
449
-    abstract public function admin_footer_scripts();
450
-
451
-
452
-
453
-    /**
454
-     * admin_footer
455
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
456
-     * apply to all pages/views loaded by child class.
457
-     *
458
-     * @return void
459
-     */
460
-    public function admin_footer()
461
-    {
462
-    }
463
-
464
-
465
-
466
-    /**
467
-     * _global_ajax_hooks
468
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
469
-     * Note: within the ajax callback methods.
470
-     *
471
-     * @abstract
472
-     * @return void
473
-     */
474
-    protected function _global_ajax_hooks()
475
-    {
476
-        //for lazy loading of metabox content
477
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
478
-    }
479
-
480
-
481
-
482
-    public function ajax_metabox_content()
483
-    {
484
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
485
-        $url       = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
486
-        self::cached_rss_display($contentid, $url);
487
-        wp_die();
488
-    }
489
-
490
-
491
-
492
-    /**
493
-     * _page_setup
494
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
495
-     * doesn't match the object.
496
-     *
497
-     * @final
498
-     * @return void
499
-     * @throws EE_Error
500
-     * @throws InvalidArgumentException
501
-     * @throws ReflectionException
502
-     * @throws InvalidDataTypeException
503
-     * @throws InvalidInterfaceException
504
-     */
505
-    final protected function _page_setup()
506
-    {
507
-        //requires?
508
-        //admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
509
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
510
-        //next verify if we need to load anything...
511
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
512
-        $this->page_folder   = strtolower(
513
-            str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
514
-        );
515
-        global $ee_menu_slugs;
516
-        $ee_menu_slugs = (array)$ee_menu_slugs;
517
-        if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))) {
518
-            return;
519
-        }
520
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
521
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
522
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
523
-                ? $this->_req_data['action2']
524
-                : $this->_req_data['action'];
525
-        }
526
-        // then set blank or -1 action values to 'default'
527
-        $this->_req_action = isset($this->_req_data['action'])
528
-                             && ! empty($this->_req_data['action'])
529
-                             && $this->_req_data['action'] !== '-1'
530
-            ? sanitize_key($this->_req_data['action'])
531
-            : 'default';
532
-        // if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
533
-        //  This covers cases where we're coming in from a list table that isn't on the default route.
534
-        $this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
535
-            ? $this->_req_data['route'] : $this->_req_action;
536
-        //however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
537
-        $this->_req_action   = defined('DOING_AJAX') && isset($this->_req_data['route'])
538
-            ? $this->_req_data['route']
539
-            : $this->_req_action;
540
-        $this->_current_view = $this->_req_action;
541
-        $this->_req_nonce    = $this->_req_action . '_nonce';
542
-        $this->_define_page_props();
543
-        $this->_current_page_view_url = add_query_arg(
544
-            array('page' => $this->_current_page, 'action' => $this->_current_view),
545
-            $this->_admin_base_url
546
-        );
547
-        //default things
548
-        $this->_default_espresso_metaboxes = array(
549
-            '_espresso_news_post_box',
550
-            '_espresso_links_post_box',
551
-            '_espresso_ratings_request',
552
-            '_espresso_sponsors_post_box',
553
-        );
554
-        //set page configs
555
-        $this->_set_page_routes();
556
-        $this->_set_page_config();
557
-        //let's include any referrer data in our default_query_args for this route for "stickiness".
558
-        if (isset($this->_req_data['wp_referer'])) {
559
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
560
-        }
561
-        //for caffeinated and other extended functionality.
562
-        //  If there is a _extend_page_config method
563
-        // then let's run that to modify the all the various page configuration arrays
564
-        if (method_exists($this, '_extend_page_config')) {
565
-            $this->_extend_page_config();
566
-        }
567
-        //for CPT and other extended functionality.
568
-        // If there is an _extend_page_config_for_cpt
569
-        // then let's run that to modify all the various page configuration arrays.
570
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
571
-            $this->_extend_page_config_for_cpt();
572
-        }
573
-        //filter routes and page_config so addons can add their stuff. Filtering done per class
574
-        $this->_page_routes = apply_filters(
575
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
-            $this->_page_routes,
577
-            $this
578
-        );
579
-        $this->_page_config = apply_filters(
580
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
581
-            $this->_page_config,
582
-            $this
583
-        );
584
-        //if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
-        if (
587
-            method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)
588
-        ) {
589
-            add_action(
590
-                'AHEE__EE_Admin_Page__route_admin_request',
591
-                array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
592
-                10,
593
-                2
594
-            );
595
-        }
596
-        //next route only if routing enabled
597
-        if ($this->_routing && ! defined('DOING_AJAX')) {
598
-            $this->_verify_routes();
599
-            //next let's just check user_access and kill if no access
600
-            $this->check_user_access();
601
-            if ($this->_is_UI_request) {
602
-                //admin_init stuff - global, all views for this page class, specific view
603
-                add_action('admin_init', array($this, 'admin_init'), 10);
604
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
605
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
606
-                }
607
-            } else {
608
-                //hijack regular WP loading and route admin request immediately
609
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
610
-                $this->route_admin_request();
611
-            }
612
-        }
613
-    }
614
-
615
-
616
-
617
-    /**
618
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
619
-     *
620
-     * @return void
621
-     * @throws ReflectionException
622
-     * @throws EE_Error
623
-     */
624
-    private function _do_other_page_hooks()
625
-    {
626
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
627
-        foreach ($registered_pages as $page) {
628
-            //now let's setup the file name and class that should be present
629
-            $classname = str_replace('.class.php', '', $page);
630
-            //autoloaders should take care of loading file
631
-            if (! class_exists($classname)) {
632
-                $error_msg[] = sprintf(
633
-                    esc_html__(
634
-                        'Something went wrong with loading the %s admin hooks page.',
635
-                        'event_espresso'
636
-                    ),
637
-                    $page
638
-                );
639
-                $error_msg[] = $error_msg[0]
640
-                               . "\r\n"
641
-                               . sprintf(
642
-                                   esc_html__(
643
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
644
-                                       'event_espresso'
645
-                                   ),
646
-                                   $page,
647
-                                   '<br />',
648
-                                   '<strong>' . $classname . '</strong>'
649
-                               );
650
-                throw new EE_Error(implode('||', $error_msg));
651
-            }
652
-            $a = new ReflectionClass($classname);
653
-            //notice we are passing the instance of this class to the hook object.
654
-            $hookobj[] = $a->newInstance($this);
655
-        }
656
-    }
657
-
658
-
659
-
660
-    public function load_page_dependencies()
661
-    {
662
-        try {
663
-            $this->_load_page_dependencies();
664
-        } catch (EE_Error $e) {
665
-            $e->get_error();
666
-        }
667
-    }
668
-
669
-
670
-
671
-    /**
672
-     * load_page_dependencies
673
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
674
-     *
675
-     * @return void
676
-     * @throws DomainException
677
-     * @throws EE_Error
678
-     * @throws InvalidArgumentException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     * @throws ReflectionException
682
-     */
683
-    protected function _load_page_dependencies()
684
-    {
685
-        //let's set the current_screen and screen options to override what WP set
686
-        $this->_current_screen = get_current_screen();
687
-        //load admin_notices - global, page class, and view specific
688
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
689
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
690
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
691
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
692
-        }
693
-        //load network admin_notices - global, page class, and view specific
694
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
695
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
696
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
697
-        }
698
-        //this will save any per_page screen options if they are present
699
-        $this->_set_per_page_screen_options();
700
-        //setup list table properties
701
-        $this->_set_list_table();
702
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
703
-        // However in some cases the metaboxes will need to be added within a route handling callback.
704
-        $this->_add_registered_meta_boxes();
705
-        $this->_add_screen_columns();
706
-        //add screen options - global, page child class, and view specific
707
-        $this->_add_global_screen_options();
708
-        $this->_add_screen_options();
709
-        $add_screen_options  = "_add_screen_options_{$this->_current_view}";
710
-        if (method_exists($this, $add_screen_options )) {
711
-            $this->{$add_screen_options}();
712
-        }
713
-        //add help tab(s) and tours- set via page_config and qtips.
714
-        $this->_add_help_tour();
715
-        $this->_add_help_tabs();
716
-        $this->_add_qtips();
717
-        //add feature_pointers - global, page child class, and view specific
718
-        $this->_add_feature_pointers();
719
-        $this->_add_global_feature_pointers();
720
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
721
-        if (method_exists($this, $add_feature_pointer )) {
722
-            $this->{$add_feature_pointer}();
723
-        }
724
-        //enqueue scripts/styles - global, page class, and view specific
725
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
726
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
727
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
728
-            add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
729
-        }
730
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
731
-        // admin_print_footer_scripts - global, page child class, and view specific.
732
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
733
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
734
-        // is a good use case. Notice the late priority we're giving these
735
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
736
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
737
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
738
-            add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
739
-        }
740
-        //admin footer scripts
741
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
742
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
743
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
744
-            add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
745
-        }
746
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
747
-        //targeted hook
748
-        do_action(
749
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
750
-
751
-        );
752
-    }
753
-
754
-
755
-
756
-    /**
757
-     * _set_defaults
758
-     * This sets some global defaults for class properties.
759
-     */
760
-    private function _set_defaults()
761
-    {
762
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
763
-        $this->_event = $this->_template_path = $this->_column_template_path = null;
764
-        $this->_nav_tabs = $this->_views = $this->_page_routes = array();
765
-        $this->_page_config = $this->_default_route_query_args = array();
766
-        $this->_default_nav_tab_name = 'overview';
767
-        //init template args
768
-        $this->_template_args = array(
769
-            'admin_page_header'  => '',
770
-            'admin_page_content' => '',
771
-            'post_body_content'  => '',
772
-            'before_list_table'  => '',
773
-            'after_list_table'   => '',
774
-        );
775
-    }
776
-
777
-
778
-
779
-    /**
780
-     * route_admin_request
781
-     *
782
-     * @see    _route_admin_request()
783
-     * @return exception|void error
784
-     * @throws InvalidArgumentException
785
-     * @throws InvalidInterfaceException
786
-     * @throws InvalidDataTypeException
787
-     * @throws EE_Error
788
-     * @throws ReflectionException
789
-     */
790
-    public function route_admin_request()
791
-    {
792
-        try {
793
-            $this->_route_admin_request();
794
-        } catch (EE_Error $e) {
795
-            $e->get_error();
796
-        }
797
-    }
798
-
799
-
800
-
801
-    public function set_wp_page_slug($wp_page_slug)
802
-    {
803
-        $this->_wp_page_slug = $wp_page_slug;
804
-        //if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
805
-        if (is_network_admin()) {
806
-            $this->_wp_page_slug .= '-network';
807
-        }
808
-    }
809
-
810
-
811
-
812
-    /**
813
-     * _verify_routes
814
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
815
-     * we know if we need to drop out.
816
-     *
817
-     * @return bool
818
-     * @throws EE_Error
819
-     */
820
-    protected function _verify_routes()
821
-    {
822
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
823
-        if (! $this->_current_page && ! defined('DOING_AJAX')) {
824
-            return false;
825
-        }
826
-        $this->_route = false;
827
-        // check that the page_routes array is not empty
828
-        if (empty($this->_page_routes)) {
829
-            // user error msg
830
-            $error_msg = sprintf(
831
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
832
-                $this->_admin_page_title
833
-            );
834
-            // developer error msg
835
-            $error_msg .= '||' . $error_msg . esc_html__(
836
-                ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
837
-                'event_espresso'
838
-            );
839
-            throw new EE_Error($error_msg);
840
-        }
841
-        // and that the requested page route exists
842
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
843
-            $this->_route        = $this->_page_routes[$this->_req_action];
844
-            $this->_route_config = isset($this->_page_config[$this->_req_action])
845
-                ? $this->_page_config[$this->_req_action] : array();
846
-        } else {
847
-            // user error msg
848
-            $error_msg = sprintf(
849
-                esc_html__(
850
-                        'The requested page route does not exist for the %s admin page.',
851
-                        'event_espresso'
852
-                ),
853
-                $this->_admin_page_title
854
-            );
855
-            // developer error msg
856
-            $error_msg .= '||' . $error_msg . sprintf(
857
-                    esc_html__(
858
-                        ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
859
-                        'event_espresso'
860
-                    ),
861
-                    $this->_req_action
862
-                );
863
-            throw new EE_Error($error_msg);
864
-        }
865
-        // and that a default route exists
866
-        if (! array_key_exists('default', $this->_page_routes)) {
867
-            // user error msg
868
-            $error_msg = sprintf(
869
-                esc_html__(
870
-                        'A default page route has not been set for the % admin page.',
871
-                        'event_espresso'
872
-                ),
873
-                $this->_admin_page_title
874
-            );
875
-            // developer error msg
876
-            $error_msg .= '||' . $error_msg . esc_html__(
877
-                ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
878
-                'event_espresso'
879
-            );
880
-            throw new EE_Error($error_msg);
881
-        }
882
-        //first lets' catch if the UI request has EVER been set.
883
-        if ($this->_is_UI_request === null) {
884
-            //lets set if this is a UI request or not.
885
-            $this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
886
-            //wait a minute... we might have a noheader in the route array
887
-            $this->_is_UI_request = is_array($this->_route)
888
-                                    && isset($this->_route['noheader'])
889
-                                    && $this->_route['noheader'] ? false : $this->_is_UI_request;
890
-        }
891
-        $this->_set_current_labels();
892
-        return true;
893
-    }
894
-
895
-
896
-
897
-    /**
898
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
899
-     *
900
-     * @param  string $route the route name we're verifying
901
-     * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
902
-     * @throws EE_Error
903
-     */
904
-    protected function _verify_route($route)
905
-    {
906
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
907
-            return true;
908
-        }
909
-        // user error msg
910
-        $error_msg = sprintf(
911
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
912
-            $this->_admin_page_title
913
-        );
914
-        // developer error msg
915
-        $error_msg .= '||' . $error_msg . sprintf(
916
-                esc_html__(
917
-                    ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
918
-                    'event_espresso'
919
-                ),
920
-                $route
921
-            );
922
-        throw new EE_Error($error_msg);
923
-    }
924
-
925
-
926
-
927
-    /**
928
-     * perform nonce verification
929
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
930
-     * using this method (and save retyping!)
931
-     *
932
-     * @param  string $nonce     The nonce sent
933
-     * @param  string $nonce_ref The nonce reference string (name0)
934
-     * @return void
935
-     * @throws EE_Error
936
-     */
937
-    protected function _verify_nonce($nonce, $nonce_ref)
938
-    {
939
-        // verify nonce against expected value
940
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
941
-            // these are not the droids you are looking for !!!
942
-            $msg = sprintf(
943
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
944
-                '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
945
-                '</a>'
946
-            );
947
-            if (WP_DEBUG) {
948
-                $msg .= "\n  " . sprintf(
949
-                        esc_html__(
950
-                            'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
951
-                            'event_espresso'
952
-                        ),
953
-                        __CLASS__
954
-                    );
955
-            }
956
-            if (! defined('DOING_AJAX')) {
957
-                wp_die($msg);
958
-            } else {
959
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
960
-                $this->_return_json();
961
-            }
962
-        }
963
-    }
964
-
965
-
966
-
967
-    /**
968
-     * _route_admin_request()
969
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
970
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
971
-     * in the page routes and then will try to load the corresponding method.
972
-     *
973
-     * @return void
974
-     * @throws EE_Error
975
-     * @throws InvalidArgumentException
976
-     * @throws InvalidDataTypeException
977
-     * @throws InvalidInterfaceException
978
-     * @throws ReflectionException
979
-     */
980
-    protected function _route_admin_request()
981
-    {
982
-        if (! $this->_is_UI_request) {
983
-            $this->_verify_routes();
984
-        }
985
-        $nonce_check = isset($this->_route_config['require_nonce'])
986
-            ? $this->_route_config['require_nonce']
987
-            : true;
988
-        if ($this->_req_action !== 'default' && $nonce_check) {
989
-            // set nonce from post data
990
-            $nonce = isset($this->_req_data[$this->_req_nonce])
991
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce])
992
-                : '';
993
-            $this->_verify_nonce($nonce, $this->_req_nonce);
994
-        }
995
-        //set the nav_tabs array but ONLY if this is  UI_request
996
-        if ($this->_is_UI_request) {
997
-            $this->_set_nav_tabs();
998
-        }
999
-        // grab callback function
1000
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1001
-        // check if callback has args
1002
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1003
-        $error_msg = '';
1004
-        // action right before calling route
1005
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1006
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1007
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1008
-        }
1009
-        // right before calling the route, let's remove _wp_http_referer from the
1010
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1011
-        $_SERVER['REQUEST_URI'] = remove_query_arg(
1012
-                '_wp_http_referer',
1013
-                wp_unslash($_SERVER['REQUEST_URI'])
1014
-        );
1015
-        if (! empty($func)) {
1016
-            if (is_array($func)) {
1017
-                list($class, $method) = $func;
1018
-            } elseif (strpos($func, '::') !== false) {
1019
-                list($class, $method) = explode('::', $func);
1020
-            } else {
1021
-                $class  = $this;
1022
-                $method = $func;
1023
-            }
1024
-            if (! (is_object($class) && $class === $this)) {
1025
-                // send along this admin page object for access by addons.
1026
-                $args['admin_page_object'] = $this;
1027
-            }
1028
-            if (
1029
-                //is it a method on a class that doesn't work?
1030
-                (
1031
-                    (
1032
-                        method_exists($class, $method)
1033
-                        && call_user_func_array(array($class, $method), $args) === false
1034
-                    )
1035
-                    && (
1036
-                        //is it a standalone function that doesn't work?
1037
-                        function_exists($method)
1038
-                        && call_user_func_array(
1039
-                            $func,
1040
-                            array_merge(array('admin_page_object' => $this), $args)
1041
-                           ) === false
1042
-                    )
1043
-                )
1044
-                || (
1045
-                    //is it neither a class method NOR a standalone function?
1046
-                    ! method_exists($class, $method)
1047
-                    && ! function_exists($method)
1048
-                )
1049
-            ) {
1050
-                // user error msg
1051
-                $error_msg = esc_html__(
1052
-                    'An error occurred. The  requested page route could not be found.',
1053
-                    'event_espresso'
1054
-                );
1055
-                // developer error msg
1056
-                $error_msg .= '||';
1057
-                $error_msg .= sprintf(
1058
-                    esc_html__(
1059
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1060
-                        'event_espresso'
1061
-                    ),
1062
-                    $method
1063
-                );
1064
-            }
1065
-            if (! empty($error_msg)) {
1066
-                throw new EE_Error($error_msg);
1067
-            }
1068
-        }
1069
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1070
-        // then we need to reset the routing properties to the new route.
1071
-        //now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1072
-        if ($this->_is_UI_request === false
1073
-            && is_array($this->_route)
1074
-            && ! empty($this->_route['headers_sent_route'])
1075
-        ) {
1076
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1077
-        }
1078
-    }
1079
-
1080
-
1081
-
1082
-    /**
1083
-     * This method just allows the resetting of page properties in the case where a no headers
1084
-     * route redirects to a headers route in its route config.
1085
-     *
1086
-     * @since   4.3.0
1087
-     * @param  string $new_route New (non header) route to redirect to.
1088
-     * @return   void
1089
-     * @throws ReflectionException
1090
-     * @throws InvalidArgumentException
1091
-     * @throws InvalidInterfaceException
1092
-     * @throws InvalidDataTypeException
1093
-     * @throws EE_Error
1094
-     */
1095
-    protected function _reset_routing_properties($new_route)
1096
-    {
1097
-        $this->_is_UI_request = true;
1098
-        //now we set the current route to whatever the headers_sent_route is set at
1099
-        $this->_req_data['action'] = $new_route;
1100
-        //rerun page setup
1101
-        $this->_page_setup();
1102
-    }
1103
-
1104
-
1105
-
1106
-    /**
1107
-     * _add_query_arg
1108
-     * adds nonce to array of arguments then calls WP add_query_arg function
1109
-     *(internally just uses EEH_URL's function with the same name)
1110
-     *
1111
-     * @param array  $args
1112
-     * @param string $url
1113
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1114
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1115
-     *                                        Example usage: If the current page is:
1116
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1117
-     *                                        &action=default&event_id=20&month_range=March%202015
1118
-     *                                        &_wpnonce=5467821
1119
-     *                                        and you call:
1120
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1121
-     *                                        array(
1122
-     *                                        'action' => 'resend_something',
1123
-     *                                        'page=>espresso_registrations'
1124
-     *                                        ),
1125
-     *                                        $some_url,
1126
-     *                                        true
1127
-     *                                        );
1128
-     *                                        It will produce a url in this structure:
1129
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1130
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1131
-     *                                        month_range]=March%202015
1132
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1133
-     * @return string
1134
-     */
1135
-    public static function add_query_args_and_nonce(
1136
-        $args = array(),
1137
-        $url = false,
1138
-        $sticky = false,
1139
-        $exclude_nonce = false
1140
-    ) {
1141
-        //if there is a _wp_http_referer include the values from the request but only if sticky = true
1142
-        if ($sticky) {
1143
-            $request = $_REQUEST;
1144
-            unset($request['_wp_http_referer']);
1145
-            unset($request['wp_referer']);
1146
-            foreach ($request as $key => $value) {
1147
-                //do not add nonces
1148
-                if (strpos($key, 'nonce') !== false) {
1149
-                    continue;
1150
-                }
1151
-                $args['wp_referer[' . $key . ']'] = $value;
1152
-            }
1153
-        }
1154
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1155
-    }
1156
-
1157
-
1158
-
1159
-    /**
1160
-     * This returns a generated link that will load the related help tab.
1161
-     *
1162
-     * @param  string $help_tab_id the id for the connected help tab
1163
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1164
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1165
-     * @uses EEH_Template::get_help_tab_link()
1166
-     * @return string              generated link
1167
-     */
1168
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1169
-    {
1170
-        return EEH_Template::get_help_tab_link(
1171
-            $help_tab_id,
1172
-            $this->page_slug,
1173
-            $this->_req_action,
1174
-            $icon_style,
1175
-            $help_text
1176
-        );
1177
-    }
1178
-
1179
-
1180
-
1181
-    /**
1182
-     * _add_help_tabs
1183
-     * Note child classes define their help tabs within the page_config array.
1184
-     *
1185
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1186
-     * @return void
1187
-     * @throws DomainException
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _add_help_tabs()
1191
-    {
1192
-        $tour_buttons = '';
1193
-        if (isset($this->_page_config[$this->_req_action])) {
1194
-            $config = $this->_page_config[$this->_req_action];
1195
-            //is there a help tour for the current route?  if there is let's setup the tour buttons
1196
-            if (isset($this->_help_tour[$this->_req_action])) {
1197
-                $tb           = array();
1198
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1199
-                foreach ($this->_help_tour['tours'] as $tour) {
1200
-                    //if this is the end tour then we don't need to setup a button
1201
-                    if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1202
-                        continue;
1203
-                    }
1204
-                    $tb[] = '<button id="trigger-tour-'
1205
-                            . $tour->get_slug()
1206
-                            . '" class="button-primary trigger-ee-help-tour">'
1207
-                            . $tour->get_label()
1208
-                            . '</button>';
1209
-                }
1210
-                $tour_buttons .= implode('<br />', $tb);
1211
-                $tour_buttons .= '</div></div>';
1212
-            }
1213
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1214
-            if (is_array($config) && isset($config['help_sidebar'])) {
1215
-                //check that the callback given is valid
1216
-                if (! method_exists($this, $config['help_sidebar'])) {
1217
-                    throw new EE_Error(
1218
-                        sprintf(
1219
-                            esc_html__(
1220
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1221
-                                'event_espresso'
1222
-                            ),
1223
-                            $config['help_sidebar'],
1224
-                            get_class($this)
1225
-                        )
1226
-                    );
1227
-                }
1228
-                $content = apply_filters(
1229
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1230
-                    $this->{$config['help_sidebar']}()
1231
-                );
1232
-                $content .= $tour_buttons; //add help tour buttons.
1233
-                //do we have any help tours setup?  Cause if we do we want to add the buttons
1234
-                $this->_current_screen->set_help_sidebar($content);
1235
-            }
1236
-            //if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1237
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1238
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1239
-            }
1240
-            //handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1241
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1242
-                $_ht['id']      = $this->page_slug;
1243
-                $_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1244
-                $_ht['content'] = '<p>' . esc_html__(
1245
-                        'The buttons to the right allow you to start/restart any help tours available for this page',
1246
-                        'event_espresso'
1247
-                    ) . '</p>';
1248
-                $this->_current_screen->add_help_tab($_ht);
1249
-            }
1250
-            if (! isset($config['help_tabs'])) {
1251
-                return;
1252
-            } //no help tabs for this route
1253
-            foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1254
-                //we're here so there ARE help tabs!
1255
-                //make sure we've got what we need
1256
-                if (! isset($cfg['title'])) {
1257
-                    throw new EE_Error(
1258
-                        esc_html__(
1259
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1260
-                            'event_espresso'
1261
-                        )
1262
-                    );
1263
-                }
1264
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1265
-                    throw new EE_Error(
1266
-                        esc_html__(
1267
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1268
-                            'event_espresso'
1269
-                        )
1270
-                    );
1271
-                }
1272
-                //first priority goes to content.
1273
-                if (! empty($cfg['content'])) {
1274
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1275
-                    //second priority goes to filename
1276
-                } elseif (! empty($cfg['filename'])) {
1277
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1278
-                    //it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1279
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1280
-                                                             . basename($this->_get_dir())
1281
-                                                             . '/help_tabs/'
1282
-                                                             . $cfg['filename']
1283
-                                                             . '.help_tab.php' : $file_path;
1284
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1285
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1286
-                        EE_Error::add_error(
1287
-                            sprintf(
1288
-                                esc_html__(
1289
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1290
-                                    'event_espresso'
1291
-                                ),
1292
-                                $tab_id,
1293
-                                key($config),
1294
-                                $file_path
1295
-                            ),
1296
-                            __FILE__,
1297
-                            __FUNCTION__,
1298
-                            __LINE__
1299
-                        );
1300
-                        return;
1301
-                    }
1302
-                    $template_args['admin_page_obj'] = $this;
1303
-                    $content = EEH_Template::display_template(
1304
-                        $file_path,
1305
-                        $template_args,
1306
-                        true
1307
-                    );
1308
-                } else {
1309
-                    $content = '';
1310
-                }
1311
-                //check if callback is valid
1312
-                if (
1313
-                    empty($content) && (
1314
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1315
-                    )
1316
-                ) {
1317
-                    EE_Error::add_error(
1318
-                        sprintf(
1319
-                            esc_html__(
1320
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1321
-                                'event_espresso'
1322
-                            ),
1323
-                            $cfg['title']
1324
-                        ),
1325
-                        __FILE__,
1326
-                        __FUNCTION__,
1327
-                        __LINE__
1328
-                    );
1329
-                    return;
1330
-                }
1331
-                //setup config array for help tab method
1332
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1333
-                $_ht = array(
1334
-                    'id'       => $id,
1335
-                    'title'    => $cfg['title'],
1336
-                    'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1337
-                    'content'  => $content,
1338
-                );
1339
-                $this->_current_screen->add_help_tab($_ht);
1340
-            }
1341
-        }
1342
-    }
1343
-
1344
-
1345
-
1346
-    /**
1347
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1348
-     * an array with properties for setting up usage of the joyride plugin
1349
-     *
1350
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1351
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1352
-     *         _set_page_config() comments
1353
-     * @return void
1354
-     * @throws EE_Error
1355
-     * @throws InvalidArgumentException
1356
-     * @throws InvalidDataTypeException
1357
-     * @throws InvalidInterfaceException
1358
-     */
1359
-    protected function _add_help_tour()
1360
-    {
1361
-        $tours            = array();
1362
-        $this->_help_tour = array();
1363
-        //exit early if help tours are turned off globally
1364
-        if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1365
-            || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1366
-        ) {
1367
-            return;
1368
-        }
1369
-        //loop through _page_config to find any help_tour defined
1370
-        foreach ($this->_page_config as $route => $config) {
1371
-            //we're only going to set things up for this route
1372
-            if ($route !== $this->_req_action) {
1373
-                continue;
1374
-            }
1375
-            if (isset($config['help_tour'])) {
1376
-                foreach ($config['help_tour'] as $tour) {
1377
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1378
-                    // let's see if we can get that file...
1379
-                    // if not its possible this is a decaf route not set in caffeinated
1380
-                    // so lets try and get the caffeinated equivalent
1381
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1382
-                                                             . basename($this->_get_dir())
1383
-                                                             . '/help_tours/'
1384
-                                                             . $tour
1385
-                                                             . '.class.php' : $file_path;
1386
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1387
-                    if (! is_readable($file_path)) {
1388
-                        EE_Error::add_error(
1389
-                            sprintf(
1390
-                                esc_html__(
1391
-                                    'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1392
-                                    'event_espresso'
1393
-                                ),
1394
-                                $file_path,
1395
-                                $tour
1396
-                            ),
1397
-                            __FILE__,
1398
-                            __FUNCTION__,
1399
-                            __LINE__
1400
-                        );
1401
-                        return;
1402
-                    }
1403
-                    require_once $file_path;
1404
-                    if (! class_exists($tour)) {
1405
-                        $error_msg[] = sprintf(
1406
-                            esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1407
-                            $tour
1408
-                        );
1409
-                        $error_msg[] = $error_msg[0] . "\r\n" . sprintf(
1410
-                                esc_html__(
1411
-                                    'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1412
-                                    'event_espresso'
1413
-                                ),
1414
-                                $tour,
1415
-                                '<br />',
1416
-                                $tour,
1417
-                                $this->_req_action,
1418
-                                get_class($this)
1419
-                            );
1420
-                        throw new EE_Error(implode('||', $error_msg));
1421
-                    }
1422
-                    $tour_obj                   = new $tour($this->_is_caf);
1423
-                    $tours[]                    = $tour_obj;
1424
-                    $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1425
-                }
1426
-                //let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1427
-                $end_stop_tour              = new EE_Help_Tour_final_stop($this->_is_caf);
1428
-                $tours[]                    = $end_stop_tour;
1429
-                $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1430
-            }
1431
-        }
1432
-        if (! empty($tours)) {
1433
-            $this->_help_tour['tours'] = $tours;
1434
-        }
1435
-        // that's it!  Now that the $_help_tours property is set (or not)
1436
-        // the scripts and html should be taken care of automatically.
1437
-    }
1438
-
1439
-
1440
-
1441
-    /**
1442
-     * This simply sets up any qtips that have been defined in the page config
1443
-     *
1444
-     * @return void
1445
-     */
1446
-    protected function _add_qtips()
1447
-    {
1448
-        if (isset($this->_route_config['qtips'])) {
1449
-            $qtips = (array)$this->_route_config['qtips'];
1450
-            //load qtip loader
1451
-            $path = array(
1452
-                $this->_get_dir() . '/qtips/',
1453
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1454
-            );
1455
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1456
-        }
1457
-    }
1458
-
1459
-
1460
-
1461
-    /**
1462
-     * _set_nav_tabs
1463
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1464
-     * wish to add additional tabs or modify accordingly.
1465
-     *
1466
-     * @return void
1467
-     * @throws InvalidArgumentException
1468
-     * @throws InvalidInterfaceException
1469
-     * @throws InvalidDataTypeException
1470
-     */
1471
-    protected function _set_nav_tabs()
1472
-    {
1473
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1474
-        $i = 0;
1475
-        foreach ($this->_page_config as $slug => $config) {
1476
-            if (
1477
-                ! is_array($config)
1478
-                || (
1479
-                    is_array($config)
1480
-                    && (
1481
-                        (isset($config['nav']) && ! $config['nav'])
1482
-                        || ! isset($config['nav'])
1483
-                    )
1484
-                )
1485
-            ) {
1486
-                continue;
1487
-            }
1488
-            //no nav tab for this config
1489
-            //check for persistent flag
1490
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1491
-                // nav tab is only to appear when route requested.
1492
-                continue;
1493
-            }
1494
-            if (! $this->check_user_access($slug, true)) {
1495
-                // no nav tab because current user does not have access.
1496
-                continue;
1497
-            }
1498
-            $css_class              = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1499
-            $this->_nav_tabs[$slug] = array(
1500
-                'url'       => isset($config['nav']['url'])
1501
-                    ? $config['nav']['url']
1502
-                    : self::add_query_args_and_nonce(
1503
-                        array('action' => $slug),
1504
-                        $this->_admin_base_url
1505
-                    ),
1506
-                'link_text' => isset($config['nav']['label'])
1507
-                    ? $config['nav']['label']
1508
-                    : ucwords(
1509
-                        str_replace('_', ' ', $slug)
1510
-                    ),
1511
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1512
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1513
-            );
1514
-            $i++;
1515
-        }
1516
-        //if $this->_nav_tabs is empty then lets set the default
1517
-        if (empty($this->_nav_tabs)) {
1518
-            $this->_nav_tabs[$this->_default_nav_tab_name] = array(
1519
-                'url'       => $this->_admin_base_url,
1520
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1521
-                'css_class' => 'nav-tab-active',
1522
-                'order'     => 10,
1523
-            );
1524
-        }
1525
-        //now let's sort the tabs according to order
1526
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1527
-    }
1528
-
1529
-
1530
-
1531
-    /**
1532
-     * _set_current_labels
1533
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1534
-     * property array
1535
-     *
1536
-     * @return void
1537
-     */
1538
-    private function _set_current_labels()
1539
-    {
1540
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1541
-            foreach ($this->_route_config['labels'] as $label => $text) {
1542
-                if (is_array($text)) {
1543
-                    foreach ($text as $sublabel => $subtext) {
1544
-                        $this->_labels[$label][$sublabel] = $subtext;
1545
-                    }
1546
-                } else {
1547
-                    $this->_labels[$label] = $text;
1548
-                }
1549
-            }
1550
-        }
1551
-    }
1552
-
1553
-
1554
-
1555
-    /**
1556
-     *        verifies user access for this admin page
1557
-     *
1558
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1559
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1560
-     *                               return false if verify fail.
1561
-     * @return bool
1562
-     * @throws InvalidArgumentException
1563
-     * @throws InvalidDataTypeException
1564
-     * @throws InvalidInterfaceException
1565
-     */
1566
-    public function check_user_access($route_to_check = '', $verify_only = false)
1567
-    {
1568
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1569
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1570
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1571
-                          && is_array(
1572
-                              $this->_page_routes[$route_to_check]
1573
-                          )
1574
-                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1575
-            ? $this->_page_routes[$route_to_check]['capability'] : null;
1576
-        if (empty($capability) && empty($route_to_check)) {
1577
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1578
-                : $this->_route['capability'];
1579
-        } else {
1580
-            $capability = empty($capability) ? 'manage_options' : $capability;
1581
-        }
1582
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1583
-        if (
1584
-            ! defined('DOING_AJAX')
1585
-            && (
1586
-                ! function_exists('is_admin')
1587
-                || ! EE_Registry::instance()->CAP->current_user_can(
1588
-                    $capability,
1589
-                    $this->page_slug
1590
-                    . '_'
1591
-                    . $route_to_check,
1592
-                    $id
1593
-                )
1594
-            )
1595
-        ) {
1596
-            if ($verify_only) {
1597
-                return false;
1598
-            }
1599
-            if (is_user_logged_in()) {
1600
-                wp_die(__('You do not have access to this route.', 'event_espresso'));
1601
-            } else {
1602
-                return false;
1603
-            }
1604
-        }
1605
-        return true;
1606
-    }
1607
-
1608
-
1609
-
1610
-    /**
1611
-     * admin_init_global
1612
-     * This runs all the code that we want executed within the WP admin_init hook.
1613
-     * This method executes for ALL EE Admin pages.
1614
-     *
1615
-     * @return void
1616
-     */
1617
-    public function admin_init_global()
1618
-    {
1619
-    }
1620
-
1621
-
1622
-
1623
-    /**
1624
-     * wp_loaded_global
1625
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1626
-     * EE_Admin page and will execute on every EE Admin Page load
1627
-     *
1628
-     * @return void
1629
-     */
1630
-    public function wp_loaded()
1631
-    {
1632
-    }
1633
-
1634
-
1635
-
1636
-    /**
1637
-     * admin_notices
1638
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1639
-     * ALL EE_Admin pages.
1640
-     *
1641
-     * @return void
1642
-     */
1643
-    public function admin_notices_global()
1644
-    {
1645
-        $this->_display_no_javascript_warning();
1646
-        $this->_display_espresso_notices();
1647
-    }
1648
-
1649
-
1650
-
1651
-    public function network_admin_notices_global()
1652
-    {
1653
-        $this->_display_no_javascript_warning();
1654
-        $this->_display_espresso_notices();
1655
-    }
1656
-
1657
-
1658
-
1659
-    /**
1660
-     * admin_footer_scripts_global
1661
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1662
-     * will apply on ALL EE_Admin pages.
1663
-     *
1664
-     * @return void
1665
-     */
1666
-    public function admin_footer_scripts_global()
1667
-    {
1668
-        $this->_add_admin_page_ajax_loading_img();
1669
-        $this->_add_admin_page_overlay();
1670
-        //if metaboxes are present we need to add the nonce field
1671
-        if (
1672
-             isset($this->_route_config['metaboxes'])
1673
-             || isset($this->_route_config['list_table'])
1674
-             || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1675
-        ) {
1676
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1677
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1678
-        }
1679
-    }
1680
-
1681
-
1682
-
1683
-    /**
1684
-     * admin_footer_global
1685
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1686
-     * ALL EE_Admin Pages.
1687
-     *
1688
-     * @return void
1689
-     * @throws EE_Error
1690
-     */
1691
-    public function admin_footer_global()
1692
-    {
1693
-        //dialog container for dialog helper
1694
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1695
-        $d_cont .= '<div class="ee-notices"></div>';
1696
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1697
-        $d_cont .= '</div>';
1698
-        echo $d_cont;
1699
-        //help tour stuff?
1700
-        if (isset($this->_help_tour[$this->_req_action])) {
1701
-            echo implode('<br />', $this->_help_tour[$this->_req_action]);
1702
-        }
1703
-        //current set timezone for timezone js
1704
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1705
-    }
1706
-
1707
-
1708
-
1709
-    /**
1710
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1711
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1712
-     * help popups then in your templates or your content you set "triggers" for the content using the
1713
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1714
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1715
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1716
-     * for the
1717
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1718
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1719
-     *    'help_trigger_id' => array(
1720
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1721
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1722
-     *    )
1723
-     * );
1724
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1725
-     *
1726
-     * @param array $help_array
1727
-     * @param bool  $display
1728
-     * @return string content
1729
-     * @throws DomainException
1730
-     * @throws EE_Error
1731
-     */
1732
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1733
-    {
1734
-        $content       = '';
1735
-        $help_array    = empty($help_array) ? $this->_get_help_content() : $help_array;
1736
-        //loop through the array and setup content
1737
-        foreach ($help_array as $trigger => $help) {
1738
-            //make sure the array is setup properly
1739
-            if (! isset($help['title']) || ! isset($help['content'])) {
1740
-                throw new EE_Error(
1741
-                    esc_html__(
1742
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1743
-                        'event_espresso'
1744
-                    )
1745
-                );
1746
-            }
1747
-            //we're good so let'd setup the template vars and then assign parsed template content to our content.
1748
-            $template_args = array(
1749
-                'help_popup_id'      => $trigger,
1750
-                'help_popup_title'   => $help['title'],
1751
-                'help_popup_content' => $help['content'],
1752
-            );
1753
-            $content       .= EEH_Template::display_template(
1754
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1755
-                $template_args,
1756
-                true
1757
-            );
1758
-        }
1759
-        if ($display) {
1760
-            echo $content;
1761
-            return '';
1762
-        }
1763
-        return $content;
1764
-    }
1765
-
1766
-
1767
-
1768
-    /**
1769
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1770
-     *
1771
-     * @return array properly formatted array for help popup content
1772
-     * @throws EE_Error
1773
-     */
1774
-    private function _get_help_content()
1775
-    {
1776
-        //what is the method we're looking for?
1777
-        $method_name = '_help_popup_content_' . $this->_req_action;
1778
-        //if method doesn't exist let's get out.
1779
-        if (! method_exists($this, $method_name)) {
1780
-            return array();
1781
-        }
1782
-        //k we're good to go let's retrieve the help array
1783
-        $help_array = call_user_func(array($this, $method_name));
1784
-        //make sure we've got an array!
1785
-        if (! is_array($help_array)) {
1786
-            throw new EE_Error(
1787
-                esc_html__(
1788
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1789
-                    'event_espresso'
1790
-                )
1791
-            );
1792
-        }
1793
-        return $help_array;
1794
-    }
1795
-
1796
-
1797
-
1798
-    /**
1799
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1800
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1801
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1802
-     *
1803
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1804
-     * @param boolean $display    if false then we return the trigger string
1805
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1806
-     * @return string
1807
-     * @throws DomainException
1808
-     * @throws EE_Error
1809
-     */
1810
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1811
-    {
1812
-        if (defined('DOING_AJAX')) {
1813
-            return '';
1814
-        }
1815
-        //let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1816
-        $help_array   = $this->_get_help_content();
1817
-        $help_content = '';
1818
-        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1819
-            $help_array[$trigger_id] = array(
1820
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1821
-                'content' => esc_html__(
1822
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1823
-                    'event_espresso'
1824
-                ),
1825
-            );
1826
-            $help_content            = $this->_set_help_popup_content($help_array, false);
1827
-        }
1828
-        //let's setup the trigger
1829
-        $content = '<a class="ee-dialog" href="?height='
1830
-                   . $dimensions[0]
1831
-                   . '&width='
1832
-                   . $dimensions[1]
1833
-                   . '&inlineId='
1834
-                   . $trigger_id
1835
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1836
-        $content .= $help_content;
1837
-        if ($display) {
1838
-            echo $content;
1839
-            return  '';
1840
-        }
1841
-        return $content;
1842
-    }
1843
-
1844
-
1845
-
1846
-    /**
1847
-     * _add_global_screen_options
1848
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1849
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1850
-     *
1851
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1852
-     *         see also WP_Screen object documents...
1853
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1854
-     * @abstract
1855
-     * @return void
1856
-     */
1857
-    private function _add_global_screen_options()
1858
-    {
1859
-    }
1860
-
1861
-
1862
-
1863
-    /**
1864
-     * _add_global_feature_pointers
1865
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1868
-     *
1869
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
-     *         extended) also see:
1871
-     * @link   http://eamann.com/tech/wordpress-portland/
1872
-     * @abstract
1873
-     * @return void
1874
-     */
1875
-    private function _add_global_feature_pointers()
1876
-    {
1877
-    }
1878
-
1879
-
1880
-
1881
-    /**
1882
-     * load_global_scripts_styles
1883
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1884
-     *
1885
-     * @return void
1886
-     * @throws EE_Error
1887
-     */
1888
-    public function load_global_scripts_styles()
1889
-    {
1890
-        /** STYLES **/
1891
-        // add debugging styles
1892
-        if (WP_DEBUG) {
1893
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1894
-        }
1895
-        // register all styles
1896
-        wp_register_style(
1897
-            'espresso-ui-theme',
1898
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1899
-            array(),
1900
-            EVENT_ESPRESSO_VERSION
1901
-        );
1902
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1903
-        //helpers styles
1904
-        wp_register_style(
1905
-            'ee-text-links',
1906
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1907
-            array(),
1908
-            EVENT_ESPRESSO_VERSION
1909
-        );
1910
-        /** SCRIPTS **/
1911
-        //register all scripts
1912
-        wp_register_script(
1913
-            'ee-dialog',
1914
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1915
-            array('jquery', 'jquery-ui-draggable'),
1916
-            EVENT_ESPRESSO_VERSION,
1917
-            true
1918
-        );
1919
-        wp_register_script(
1920
-            'ee_admin_js',
1921
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1922
-            array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1923
-            EVENT_ESPRESSO_VERSION,
1924
-            true
1925
-        );
1926
-        wp_register_script(
1927
-            'jquery-ui-timepicker-addon',
1928
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1929
-            array('jquery-ui-datepicker', 'jquery-ui-slider'),
1930
-            EVENT_ESPRESSO_VERSION,
1931
-            true
1932
-        );
1933
-        add_filter('FHEE_load_joyride', '__return_true');
1934
-        //script for sorting tables
1935
-        wp_register_script(
1936
-            'espresso_ajax_table_sorting',
1937
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1938
-            array('ee_admin_js', 'jquery-ui-sortable'),
1939
-            EVENT_ESPRESSO_VERSION,
1940
-            true
1941
-        );
1942
-        //script for parsing uri's
1943
-        wp_register_script(
1944
-            'ee-parse-uri',
1945
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1946
-            array(),
1947
-            EVENT_ESPRESSO_VERSION,
1948
-            true
1949
-        );
1950
-        //and parsing associative serialized form elements
1951
-        wp_register_script(
1952
-            'ee-serialize-full-array',
1953
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1954
-            array('jquery'),
1955
-            EVENT_ESPRESSO_VERSION,
1956
-            true
1957
-        );
1958
-        //helpers scripts
1959
-        wp_register_script(
1960
-            'ee-text-links',
1961
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1962
-            array('jquery'),
1963
-            EVENT_ESPRESSO_VERSION,
1964
-            true
1965
-        );
1966
-        wp_register_script(
1967
-            'ee-moment-core',
1968
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1969
-            array(),
1970
-            EVENT_ESPRESSO_VERSION,
1971
-            true
1972
-        );
1973
-        wp_register_script(
1974
-            'ee-moment',
1975
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1976
-            array('ee-moment-core'),
1977
-            EVENT_ESPRESSO_VERSION,
1978
-            true
1979
-        );
1980
-        wp_register_script(
1981
-            'ee-datepicker',
1982
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1983
-            array('jquery-ui-timepicker-addon', 'ee-moment'),
1984
-            EVENT_ESPRESSO_VERSION,
1985
-            true
1986
-        );
1987
-        //google charts
1988
-        wp_register_script(
1989
-            'google-charts',
1990
-            'https://www.gstatic.com/charts/loader.js',
1991
-            array(),
1992
-            EVENT_ESPRESSO_VERSION,
1993
-            false
1994
-        );
1995
-        // ENQUEUE ALL BASICS BY DEFAULT
1996
-        wp_enqueue_style('ee-admin-css');
1997
-        wp_enqueue_script('ee_admin_js');
1998
-        wp_enqueue_script('ee-accounting');
1999
-        wp_enqueue_script('jquery-validate');
2000
-        //taking care of metaboxes
2001
-        if (
2002
-            empty($this->_cpt_route)
2003
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2004
-        ) {
2005
-            wp_enqueue_script('dashboard');
2006
-        }
2007
-        // LOCALIZED DATA
2008
-        //localize script for ajax lazy loading
2009
-        $lazy_loader_container_ids = apply_filters(
2010
-            'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2011
-            array('espresso_news_post_box_content')
2012
-        );
2013
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2014
-        /**
2015
-         * help tour stuff
2016
-         */
2017
-        if (! empty($this->_help_tour)) {
2018
-            //register the js for kicking things off
2019
-            wp_enqueue_script(
2020
-                'ee-help-tour',
2021
-                EE_ADMIN_URL . 'assets/ee-help-tour.js',
2022
-                array('jquery-joyride'),
2023
-                EVENT_ESPRESSO_VERSION,
2024
-                true
2025
-            );
2026
-            $tours = array();
2027
-            //setup tours for the js tour object
2028
-            foreach ($this->_help_tour['tours'] as $tour) {
2029
-                if ($tour instanceof EE_Help_Tour) {
2030
-                    $tours[] = array(
2031
-                        'id'      => $tour->get_slug(),
2032
-                        'options' => $tour->get_options(),
2033
-                    );
2034
-                }
2035
-            }
2036
-            wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2037
-            //admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2038
-        }
2039
-    }
2040
-
2041
-
2042
-
2043
-    /**
2044
-     *        admin_footer_scripts_eei18n_js_strings
2045
-     *
2046
-     * @return        void
2047
-     */
2048
-    public function admin_footer_scripts_eei18n_js_strings()
2049
-    {
2050
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2051
-        EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2052
-            'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2053
-            'event_espresso'
2054
-        );
2055
-        EE_Registry::$i18n_js_strings['January']        = esc_html__('January', 'event_espresso');
2056
-        EE_Registry::$i18n_js_strings['February']       = esc_html__('February', 'event_espresso');
2057
-        EE_Registry::$i18n_js_strings['March']          = esc_html__('March', 'event_espresso');
2058
-        EE_Registry::$i18n_js_strings['April']          = esc_html__('April', 'event_espresso');
2059
-        EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2060
-        EE_Registry::$i18n_js_strings['June']           = esc_html__('June', 'event_espresso');
2061
-        EE_Registry::$i18n_js_strings['July']           = esc_html__('July', 'event_espresso');
2062
-        EE_Registry::$i18n_js_strings['August']         = esc_html__('August', 'event_espresso');
2063
-        EE_Registry::$i18n_js_strings['September']      = esc_html__('September', 'event_espresso');
2064
-        EE_Registry::$i18n_js_strings['October']        = esc_html__('October', 'event_espresso');
2065
-        EE_Registry::$i18n_js_strings['November']       = esc_html__('November', 'event_espresso');
2066
-        EE_Registry::$i18n_js_strings['December']       = esc_html__('December', 'event_espresso');
2067
-        EE_Registry::$i18n_js_strings['Jan']            = esc_html__('Jan', 'event_espresso');
2068
-        EE_Registry::$i18n_js_strings['Feb']            = esc_html__('Feb', 'event_espresso');
2069
-        EE_Registry::$i18n_js_strings['Mar']            = esc_html__('Mar', 'event_espresso');
2070
-        EE_Registry::$i18n_js_strings['Apr']            = esc_html__('Apr', 'event_espresso');
2071
-        EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2072
-        EE_Registry::$i18n_js_strings['Jun']            = esc_html__('Jun', 'event_espresso');
2073
-        EE_Registry::$i18n_js_strings['Jul']            = esc_html__('Jul', 'event_espresso');
2074
-        EE_Registry::$i18n_js_strings['Aug']            = esc_html__('Aug', 'event_espresso');
2075
-        EE_Registry::$i18n_js_strings['Sep']            = esc_html__('Sep', 'event_espresso');
2076
-        EE_Registry::$i18n_js_strings['Oct']            = esc_html__('Oct', 'event_espresso');
2077
-        EE_Registry::$i18n_js_strings['Nov']            = esc_html__('Nov', 'event_espresso');
2078
-        EE_Registry::$i18n_js_strings['Dec']            = esc_html__('Dec', 'event_espresso');
2079
-        EE_Registry::$i18n_js_strings['Sunday']         = esc_html__('Sunday', 'event_espresso');
2080
-        EE_Registry::$i18n_js_strings['Monday']         = esc_html__('Monday', 'event_espresso');
2081
-        EE_Registry::$i18n_js_strings['Tuesday']        = esc_html__('Tuesday', 'event_espresso');
2082
-        EE_Registry::$i18n_js_strings['Wednesday']      = esc_html__('Wednesday', 'event_espresso');
2083
-        EE_Registry::$i18n_js_strings['Thursday']       = esc_html__('Thursday', 'event_espresso');
2084
-        EE_Registry::$i18n_js_strings['Friday']         = esc_html__('Friday', 'event_espresso');
2085
-        EE_Registry::$i18n_js_strings['Saturday']       = esc_html__('Saturday', 'event_espresso');
2086
-        EE_Registry::$i18n_js_strings['Sun']            = esc_html__('Sun', 'event_espresso');
2087
-        EE_Registry::$i18n_js_strings['Mon']            = esc_html__('Mon', 'event_espresso');
2088
-        EE_Registry::$i18n_js_strings['Tue']            = esc_html__('Tue', 'event_espresso');
2089
-        EE_Registry::$i18n_js_strings['Wed']            = esc_html__('Wed', 'event_espresso');
2090
-        EE_Registry::$i18n_js_strings['Thu']            = esc_html__('Thu', 'event_espresso');
2091
-        EE_Registry::$i18n_js_strings['Fri']            = esc_html__('Fri', 'event_espresso');
2092
-        EE_Registry::$i18n_js_strings['Sat']            = esc_html__('Sat', 'event_espresso');
2093
-    }
2094
-
2095
-
2096
-
2097
-    /**
2098
-     *        load enhanced xdebug styles for ppl with failing eyesight
2099
-     *
2100
-     * @return        void
2101
-     */
2102
-    public function add_xdebug_style()
2103
-    {
2104
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2105
-    }
2106
-
2107
-
2108
-    /************************/
2109
-    /** LIST TABLE METHODS **/
2110
-    /************************/
2111
-    /**
2112
-     * this sets up the list table if the current view requires it.
2113
-     *
2114
-     * @return void
2115
-     * @throws EE_Error
2116
-     */
2117
-    protected function _set_list_table()
2118
-    {
2119
-        //first is this a list_table view?
2120
-        if (! isset($this->_route_config['list_table'])) {
2121
-            return;
2122
-        } //not a list_table view so get out.
2123
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2124
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2125
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2126
-            //user error msg
2127
-            $error_msg = esc_html__(
2128
-                'An error occurred. The requested list table views could not be found.',
2129
-                'event_espresso'
2130
-            );
2131
-            //developer error msg
2132
-            $error_msg .= '||' . sprintf(
2133
-                    esc_html__(
2134
-                        'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2135
-                        'event_espresso'
2136
-                    ),
2137
-                    $this->_req_action,
2138
-                    $list_table_view
2139
-                );
2140
-            throw new EE_Error($error_msg);
2141
-        }
2142
-        //let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2143
-        $this->_views = apply_filters(
2144
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2145
-            $this->_views
2146
-        );
2147
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2148
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2149
-        $this->_set_list_table_view();
2150
-        $this->_set_list_table_object();
2151
-    }
2152
-
2153
-
2154
-
2155
-    /**
2156
-     * set current view for List Table
2157
-     *
2158
-     * @return void
2159
-     */
2160
-    protected function _set_list_table_view()
2161
-    {
2162
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2163
-        // looking at active items or dumpster diving ?
2164
-        if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2165
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2166
-        } else {
2167
-            $this->_view = sanitize_key($this->_req_data['status']);
2168
-        }
2169
-    }
2170
-
2171
-
2172
-    /**
2173
-     * _set_list_table_object
2174
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2175
-     *
2176
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2177
-     * @throws \InvalidArgumentException
2178
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2179
-     * @throws EE_Error
2180
-     * @throws InvalidInterfaceException
2181
-     */
2182
-    protected function _set_list_table_object()
2183
-    {
2184
-        if (isset($this->_route_config['list_table'])) {
2185
-            if (! class_exists($this->_route_config['list_table'])) {
2186
-                throw new EE_Error(
2187
-                    sprintf(
2188
-                        esc_html__(
2189
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2190
-                            'event_espresso'
2191
-                        ),
2192
-                        $this->_route_config['list_table'],
2193
-                        get_class($this)
2194
-                    )
2195
-                );
2196
-            }
2197
-            $this->_list_table_object = LoaderFactory::getLoader()->getShared(
2198
-                $this->_route_config['list_table'],
2199
-                array($this)
2200
-            );
2201
-        }
2202
-    }
2203
-
2204
-
2205
-
2206
-    /**
2207
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2208
-     *
2209
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2210
-     *                                                    urls.  The array should be indexed by the view it is being
2211
-     *                                                    added to.
2212
-     * @return array
2213
-     */
2214
-    public function get_list_table_view_RLs($extra_query_args = array())
2215
-    {
2216
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2217
-        if (empty($this->_views)) {
2218
-            $this->_views = array();
2219
-        }
2220
-        // cycle thru views
2221
-        foreach ($this->_views as $key => $view) {
2222
-            $query_args = array();
2223
-            // check for current view
2224
-            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2225
-            $query_args['action']                      = $this->_req_action;
2226
-            $query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2227
-            $query_args['status']                      = $view['slug'];
2228
-            //merge any other arguments sent in.
2229
-            if (isset($extra_query_args[$view['slug']])) {
2230
-                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2231
-            }
2232
-            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2233
-        }
2234
-        return $this->_views;
2235
-    }
2236
-
2237
-
2238
-
2239
-    /**
2240
-     * _entries_per_page_dropdown
2241
-     * generates a drop down box for selecting the number of visible rows in an admin page list table
2242
-     *
2243
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2244
-     *         WP does it.
2245
-     * @param int $max_entries total number of rows in the table
2246
-     * @return string
2247
-     */
2248
-    protected function _entries_per_page_dropdown($max_entries = 0)
2249
-    {
2250
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2251
-        $values   = array(10, 25, 50, 100);
2252
-        $per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2253
-        if ($max_entries) {
2254
-            $values[] = $max_entries;
2255
-            sort($values);
2256
-        }
2257
-        $entries_per_page_dropdown = '
126
+	/**
127
+	 * @var string $_req_action
128
+	 */
129
+	protected $_req_action;
130
+
131
+	/**
132
+	 * @var string $_req_nonce
133
+	 */
134
+	protected $_req_nonce;
135
+
136
+	//search related
137
+	protected $_search_btn_label;
138
+
139
+	protected $_search_box_callback;
140
+
141
+	/**
142
+	 * WP Current Screen object
143
+	 *
144
+	 * @var WP_Screen
145
+	 */
146
+	protected $_current_screen;
147
+
148
+	//for holding EE_Admin_Hooks object when needed (set via set_hook_object())
149
+	protected $_hook_obj;
150
+
151
+	//for holding incoming request data
152
+	protected $_req_data;
153
+
154
+	// yes / no array for admin form fields
155
+	protected $_yes_no_values = array();
156
+
157
+	//some default things shared by all child classes
158
+	protected $_default_espresso_metaboxes;
159
+
160
+	/**
161
+	 *    EE_Registry Object
162
+	 *
163
+	 * @var    EE_Registry
164
+	 */
165
+	protected $EE = null;
166
+
167
+
168
+
169
+	/**
170
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
171
+	 *
172
+	 * @var boolean
173
+	 */
174
+	protected $_is_caf = false;
175
+
176
+
177
+
178
+	/**
179
+	 * @Constructor
180
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
181
+	 * @throws EE_Error
182
+	 * @throws InvalidArgumentException
183
+	 * @throws ReflectionException
184
+	 * @throws InvalidDataTypeException
185
+	 * @throws InvalidInterfaceException
186
+	 */
187
+	public function __construct($routing = true)
188
+	{
189
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
+			$this->_is_caf = true;
191
+		}
192
+		$this->_yes_no_values = array(
193
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
+		);
196
+		//set the _req_data property.
197
+		$this->_req_data = array_merge($_GET, $_POST);
198
+		//routing enabled?
199
+		$this->_routing = $routing;
200
+		//set initial page props (child method)
201
+		$this->_init_page_props();
202
+		//set global defaults
203
+		$this->_set_defaults();
204
+		//set early because incoming requests could be ajax related and we need to register those hooks.
205
+		$this->_global_ajax_hooks();
206
+		$this->_ajax_hooks();
207
+		//other_page_hooks have to be early too.
208
+		$this->_do_other_page_hooks();
209
+		//This just allows us to have extending classes do something specific
210
+		// before the parent constructor runs _page_setup().
211
+		if (method_exists($this, '_before_page_setup')) {
212
+			$this->_before_page_setup();
213
+		}
214
+		//set up page dependencies
215
+		$this->_page_setup();
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 * _init_page_props
222
+	 * Child classes use to set at least the following properties:
223
+	 * $page_slug.
224
+	 * $page_label.
225
+	 *
226
+	 * @abstract
227
+	 * @return void
228
+	 */
229
+	abstract protected function _init_page_props();
230
+
231
+
232
+
233
+	/**
234
+	 * _ajax_hooks
235
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
236
+	 * Note: within the ajax callback methods.
237
+	 *
238
+	 * @abstract
239
+	 * @return void
240
+	 */
241
+	abstract protected function _ajax_hooks();
242
+
243
+
244
+
245
+	/**
246
+	 * _define_page_props
247
+	 * child classes define page properties in here.  Must include at least:
248
+	 * $_admin_base_url = base_url for all admin pages
249
+	 * $_admin_page_title = default admin_page_title for admin pages
250
+	 * $_labels = array of default labels for various automatically generated elements:
251
+	 *    array(
252
+	 *        'buttons' => array(
253
+	 *            'add' => esc_html__('label for add new button'),
254
+	 *            'edit' => esc_html__('label for edit button'),
255
+	 *            'delete' => esc_html__('label for delete button')
256
+	 *            )
257
+	 *        )
258
+	 *
259
+	 * @abstract
260
+	 * @return void
261
+	 */
262
+	abstract protected function _define_page_props();
263
+
264
+
265
+
266
+	/**
267
+	 * _set_page_routes
268
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
269
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
270
+	 * have a 'default' route. Here's the format
271
+	 * $this->_page_routes = array(
272
+	 *        'default' => array(
273
+	 *            'func' => '_default_method_handling_route',
274
+	 *            'args' => array('array','of','args'),
275
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
276
+	 *            ajax request, backend processing)
277
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
278
+	 *            headers route after.  The string you enter here should match the defined route reference for a
279
+	 *            headers sent route.
280
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
281
+	 *            this route.
282
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
283
+	 *            checks).
284
+	 *        ),
285
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
286
+	 *        handling method.
287
+	 *        )
288
+	 * )
289
+	 *
290
+	 * @abstract
291
+	 * @return void
292
+	 */
293
+	abstract protected function _set_page_routes();
294
+
295
+
296
+
297
+	/**
298
+	 * _set_page_config
299
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
300
+	 * array corresponds to the page_route for the loaded page. Format:
301
+	 * $this->_page_config = array(
302
+	 *        'default' => array(
303
+	 *            'labels' => array(
304
+	 *                'buttons' => array(
305
+	 *                    'add' => esc_html__('label for adding item'),
306
+	 *                    'edit' => esc_html__('label for editing item'),
307
+	 *                    'delete' => esc_html__('label for deleting item')
308
+	 *                ),
309
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
310
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
311
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
312
+	 *            _define_page_props() method
313
+	 *            'nav' => array(
314
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
315
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
316
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
317
+	 *                'order' => 10, //required to indicate tab position.
318
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
319
+	 *                displayed then add this parameter.
320
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
321
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
322
+	 *            metaboxes set for eventespresso admin pages.
323
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
324
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
325
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
326
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
327
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
328
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
329
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
330
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
331
+	 *            want to display.
332
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
333
+	 *                'tab_id' => array(
334
+	 *                    'title' => 'tab_title',
335
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
336
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
337
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
338
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
339
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
340
+	 *                    attempt to use the callback which should match the name of a method in the class
341
+	 *                    ),
342
+	 *                'tab2_id' => array(
343
+	 *                    'title' => 'tab2 title',
344
+	 *                    'filename' => 'file_name_2'
345
+	 *                    'callback' => 'callback_method_for_content',
346
+	 *                 ),
347
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
348
+	 *            help tab area on an admin page. @link
349
+	 *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
350
+	 *            'help_tour' => array(
351
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
352
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
353
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
354
+	 *            ),
355
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
356
+	 *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
357
+	 *            just set
358
+	 *            'require_nonce' to FALSE
359
+	 *            )
360
+	 * )
361
+	 *
362
+	 * @abstract
363
+	 * @return void
364
+	 */
365
+	abstract protected function _set_page_config();
366
+
367
+
368
+
369
+
370
+
371
+	/** end sample help_tour methods **/
372
+	/**
373
+	 * _add_screen_options
374
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
375
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
376
+	 * to a particular view.
377
+	 *
378
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
379
+	 *         see also WP_Screen object documents...
380
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
381
+	 * @abstract
382
+	 * @return void
383
+	 */
384
+	abstract protected function _add_screen_options();
385
+
386
+
387
+
388
+	/**
389
+	 * _add_feature_pointers
390
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
391
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
392
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
393
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
394
+	 * extended) also see:
395
+	 *
396
+	 * @link   http://eamann.com/tech/wordpress-portland/
397
+	 * @abstract
398
+	 * @return void
399
+	 */
400
+	abstract protected function _add_feature_pointers();
401
+
402
+
403
+
404
+	/**
405
+	 * load_scripts_styles
406
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
407
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
408
+	 * scripts/styles per view by putting them in a dynamic function in this format
409
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
410
+	 *
411
+	 * @abstract
412
+	 * @return void
413
+	 */
414
+	abstract public function load_scripts_styles();
415
+
416
+
417
+
418
+	/**
419
+	 * admin_init
420
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
421
+	 * all pages/views loaded by child class.
422
+	 *
423
+	 * @abstract
424
+	 * @return void
425
+	 */
426
+	abstract public function admin_init();
427
+
428
+
429
+
430
+	/**
431
+	 * admin_notices
432
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
433
+	 * all pages/views loaded by child class.
434
+	 *
435
+	 * @abstract
436
+	 * @return void
437
+	 */
438
+	abstract public function admin_notices();
439
+
440
+
441
+
442
+	/**
443
+	 * admin_footer_scripts
444
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
445
+	 * will apply to all pages/views loaded by child class.
446
+	 *
447
+	 * @return void
448
+	 */
449
+	abstract public function admin_footer_scripts();
450
+
451
+
452
+
453
+	/**
454
+	 * admin_footer
455
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
456
+	 * apply to all pages/views loaded by child class.
457
+	 *
458
+	 * @return void
459
+	 */
460
+	public function admin_footer()
461
+	{
462
+	}
463
+
464
+
465
+
466
+	/**
467
+	 * _global_ajax_hooks
468
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
469
+	 * Note: within the ajax callback methods.
470
+	 *
471
+	 * @abstract
472
+	 * @return void
473
+	 */
474
+	protected function _global_ajax_hooks()
475
+	{
476
+		//for lazy loading of metabox content
477
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
478
+	}
479
+
480
+
481
+
482
+	public function ajax_metabox_content()
483
+	{
484
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
485
+		$url       = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
486
+		self::cached_rss_display($contentid, $url);
487
+		wp_die();
488
+	}
489
+
490
+
491
+
492
+	/**
493
+	 * _page_setup
494
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
495
+	 * doesn't match the object.
496
+	 *
497
+	 * @final
498
+	 * @return void
499
+	 * @throws EE_Error
500
+	 * @throws InvalidArgumentException
501
+	 * @throws ReflectionException
502
+	 * @throws InvalidDataTypeException
503
+	 * @throws InvalidInterfaceException
504
+	 */
505
+	final protected function _page_setup()
506
+	{
507
+		//requires?
508
+		//admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
509
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
510
+		//next verify if we need to load anything...
511
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
512
+		$this->page_folder   = strtolower(
513
+			str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
514
+		);
515
+		global $ee_menu_slugs;
516
+		$ee_menu_slugs = (array)$ee_menu_slugs;
517
+		if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))) {
518
+			return;
519
+		}
520
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
521
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
522
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
523
+				? $this->_req_data['action2']
524
+				: $this->_req_data['action'];
525
+		}
526
+		// then set blank or -1 action values to 'default'
527
+		$this->_req_action = isset($this->_req_data['action'])
528
+							 && ! empty($this->_req_data['action'])
529
+							 && $this->_req_data['action'] !== '-1'
530
+			? sanitize_key($this->_req_data['action'])
531
+			: 'default';
532
+		// if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
533
+		//  This covers cases where we're coming in from a list table that isn't on the default route.
534
+		$this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
535
+			? $this->_req_data['route'] : $this->_req_action;
536
+		//however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
537
+		$this->_req_action   = defined('DOING_AJAX') && isset($this->_req_data['route'])
538
+			? $this->_req_data['route']
539
+			: $this->_req_action;
540
+		$this->_current_view = $this->_req_action;
541
+		$this->_req_nonce    = $this->_req_action . '_nonce';
542
+		$this->_define_page_props();
543
+		$this->_current_page_view_url = add_query_arg(
544
+			array('page' => $this->_current_page, 'action' => $this->_current_view),
545
+			$this->_admin_base_url
546
+		);
547
+		//default things
548
+		$this->_default_espresso_metaboxes = array(
549
+			'_espresso_news_post_box',
550
+			'_espresso_links_post_box',
551
+			'_espresso_ratings_request',
552
+			'_espresso_sponsors_post_box',
553
+		);
554
+		//set page configs
555
+		$this->_set_page_routes();
556
+		$this->_set_page_config();
557
+		//let's include any referrer data in our default_query_args for this route for "stickiness".
558
+		if (isset($this->_req_data['wp_referer'])) {
559
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
560
+		}
561
+		//for caffeinated and other extended functionality.
562
+		//  If there is a _extend_page_config method
563
+		// then let's run that to modify the all the various page configuration arrays
564
+		if (method_exists($this, '_extend_page_config')) {
565
+			$this->_extend_page_config();
566
+		}
567
+		//for CPT and other extended functionality.
568
+		// If there is an _extend_page_config_for_cpt
569
+		// then let's run that to modify all the various page configuration arrays.
570
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
571
+			$this->_extend_page_config_for_cpt();
572
+		}
573
+		//filter routes and page_config so addons can add their stuff. Filtering done per class
574
+		$this->_page_routes = apply_filters(
575
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
+			$this->_page_routes,
577
+			$this
578
+		);
579
+		$this->_page_config = apply_filters(
580
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
581
+			$this->_page_config,
582
+			$this
583
+		);
584
+		//if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
+		if (
587
+			method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)
588
+		) {
589
+			add_action(
590
+				'AHEE__EE_Admin_Page__route_admin_request',
591
+				array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
592
+				10,
593
+				2
594
+			);
595
+		}
596
+		//next route only if routing enabled
597
+		if ($this->_routing && ! defined('DOING_AJAX')) {
598
+			$this->_verify_routes();
599
+			//next let's just check user_access and kill if no access
600
+			$this->check_user_access();
601
+			if ($this->_is_UI_request) {
602
+				//admin_init stuff - global, all views for this page class, specific view
603
+				add_action('admin_init', array($this, 'admin_init'), 10);
604
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
605
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
606
+				}
607
+			} else {
608
+				//hijack regular WP loading and route admin request immediately
609
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
610
+				$this->route_admin_request();
611
+			}
612
+		}
613
+	}
614
+
615
+
616
+
617
+	/**
618
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
619
+	 *
620
+	 * @return void
621
+	 * @throws ReflectionException
622
+	 * @throws EE_Error
623
+	 */
624
+	private function _do_other_page_hooks()
625
+	{
626
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
627
+		foreach ($registered_pages as $page) {
628
+			//now let's setup the file name and class that should be present
629
+			$classname = str_replace('.class.php', '', $page);
630
+			//autoloaders should take care of loading file
631
+			if (! class_exists($classname)) {
632
+				$error_msg[] = sprintf(
633
+					esc_html__(
634
+						'Something went wrong with loading the %s admin hooks page.',
635
+						'event_espresso'
636
+					),
637
+					$page
638
+				);
639
+				$error_msg[] = $error_msg[0]
640
+							   . "\r\n"
641
+							   . sprintf(
642
+								   esc_html__(
643
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
644
+									   'event_espresso'
645
+								   ),
646
+								   $page,
647
+								   '<br />',
648
+								   '<strong>' . $classname . '</strong>'
649
+							   );
650
+				throw new EE_Error(implode('||', $error_msg));
651
+			}
652
+			$a = new ReflectionClass($classname);
653
+			//notice we are passing the instance of this class to the hook object.
654
+			$hookobj[] = $a->newInstance($this);
655
+		}
656
+	}
657
+
658
+
659
+
660
+	public function load_page_dependencies()
661
+	{
662
+		try {
663
+			$this->_load_page_dependencies();
664
+		} catch (EE_Error $e) {
665
+			$e->get_error();
666
+		}
667
+	}
668
+
669
+
670
+
671
+	/**
672
+	 * load_page_dependencies
673
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
674
+	 *
675
+	 * @return void
676
+	 * @throws DomainException
677
+	 * @throws EE_Error
678
+	 * @throws InvalidArgumentException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 * @throws ReflectionException
682
+	 */
683
+	protected function _load_page_dependencies()
684
+	{
685
+		//let's set the current_screen and screen options to override what WP set
686
+		$this->_current_screen = get_current_screen();
687
+		//load admin_notices - global, page class, and view specific
688
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
689
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
690
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
691
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
692
+		}
693
+		//load network admin_notices - global, page class, and view specific
694
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
695
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
696
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
697
+		}
698
+		//this will save any per_page screen options if they are present
699
+		$this->_set_per_page_screen_options();
700
+		//setup list table properties
701
+		$this->_set_list_table();
702
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
703
+		// However in some cases the metaboxes will need to be added within a route handling callback.
704
+		$this->_add_registered_meta_boxes();
705
+		$this->_add_screen_columns();
706
+		//add screen options - global, page child class, and view specific
707
+		$this->_add_global_screen_options();
708
+		$this->_add_screen_options();
709
+		$add_screen_options  = "_add_screen_options_{$this->_current_view}";
710
+		if (method_exists($this, $add_screen_options )) {
711
+			$this->{$add_screen_options}();
712
+		}
713
+		//add help tab(s) and tours- set via page_config and qtips.
714
+		$this->_add_help_tour();
715
+		$this->_add_help_tabs();
716
+		$this->_add_qtips();
717
+		//add feature_pointers - global, page child class, and view specific
718
+		$this->_add_feature_pointers();
719
+		$this->_add_global_feature_pointers();
720
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
721
+		if (method_exists($this, $add_feature_pointer )) {
722
+			$this->{$add_feature_pointer}();
723
+		}
724
+		//enqueue scripts/styles - global, page class, and view specific
725
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
726
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
727
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
728
+			add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
729
+		}
730
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
731
+		// admin_print_footer_scripts - global, page child class, and view specific.
732
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
733
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
734
+		// is a good use case. Notice the late priority we're giving these
735
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
736
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
737
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
738
+			add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
739
+		}
740
+		//admin footer scripts
741
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
742
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
743
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
744
+			add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
745
+		}
746
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
747
+		//targeted hook
748
+		do_action(
749
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
750
+
751
+		);
752
+	}
753
+
754
+
755
+
756
+	/**
757
+	 * _set_defaults
758
+	 * This sets some global defaults for class properties.
759
+	 */
760
+	private function _set_defaults()
761
+	{
762
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
763
+		$this->_event = $this->_template_path = $this->_column_template_path = null;
764
+		$this->_nav_tabs = $this->_views = $this->_page_routes = array();
765
+		$this->_page_config = $this->_default_route_query_args = array();
766
+		$this->_default_nav_tab_name = 'overview';
767
+		//init template args
768
+		$this->_template_args = array(
769
+			'admin_page_header'  => '',
770
+			'admin_page_content' => '',
771
+			'post_body_content'  => '',
772
+			'before_list_table'  => '',
773
+			'after_list_table'   => '',
774
+		);
775
+	}
776
+
777
+
778
+
779
+	/**
780
+	 * route_admin_request
781
+	 *
782
+	 * @see    _route_admin_request()
783
+	 * @return exception|void error
784
+	 * @throws InvalidArgumentException
785
+	 * @throws InvalidInterfaceException
786
+	 * @throws InvalidDataTypeException
787
+	 * @throws EE_Error
788
+	 * @throws ReflectionException
789
+	 */
790
+	public function route_admin_request()
791
+	{
792
+		try {
793
+			$this->_route_admin_request();
794
+		} catch (EE_Error $e) {
795
+			$e->get_error();
796
+		}
797
+	}
798
+
799
+
800
+
801
+	public function set_wp_page_slug($wp_page_slug)
802
+	{
803
+		$this->_wp_page_slug = $wp_page_slug;
804
+		//if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
805
+		if (is_network_admin()) {
806
+			$this->_wp_page_slug .= '-network';
807
+		}
808
+	}
809
+
810
+
811
+
812
+	/**
813
+	 * _verify_routes
814
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
815
+	 * we know if we need to drop out.
816
+	 *
817
+	 * @return bool
818
+	 * @throws EE_Error
819
+	 */
820
+	protected function _verify_routes()
821
+	{
822
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
823
+		if (! $this->_current_page && ! defined('DOING_AJAX')) {
824
+			return false;
825
+		}
826
+		$this->_route = false;
827
+		// check that the page_routes array is not empty
828
+		if (empty($this->_page_routes)) {
829
+			// user error msg
830
+			$error_msg = sprintf(
831
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
832
+				$this->_admin_page_title
833
+			);
834
+			// developer error msg
835
+			$error_msg .= '||' . $error_msg . esc_html__(
836
+				' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
837
+				'event_espresso'
838
+			);
839
+			throw new EE_Error($error_msg);
840
+		}
841
+		// and that the requested page route exists
842
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
843
+			$this->_route        = $this->_page_routes[$this->_req_action];
844
+			$this->_route_config = isset($this->_page_config[$this->_req_action])
845
+				? $this->_page_config[$this->_req_action] : array();
846
+		} else {
847
+			// user error msg
848
+			$error_msg = sprintf(
849
+				esc_html__(
850
+						'The requested page route does not exist for the %s admin page.',
851
+						'event_espresso'
852
+				),
853
+				$this->_admin_page_title
854
+			);
855
+			// developer error msg
856
+			$error_msg .= '||' . $error_msg . sprintf(
857
+					esc_html__(
858
+						' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
859
+						'event_espresso'
860
+					),
861
+					$this->_req_action
862
+				);
863
+			throw new EE_Error($error_msg);
864
+		}
865
+		// and that a default route exists
866
+		if (! array_key_exists('default', $this->_page_routes)) {
867
+			// user error msg
868
+			$error_msg = sprintf(
869
+				esc_html__(
870
+						'A default page route has not been set for the % admin page.',
871
+						'event_espresso'
872
+				),
873
+				$this->_admin_page_title
874
+			);
875
+			// developer error msg
876
+			$error_msg .= '||' . $error_msg . esc_html__(
877
+				' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
878
+				'event_espresso'
879
+			);
880
+			throw new EE_Error($error_msg);
881
+		}
882
+		//first lets' catch if the UI request has EVER been set.
883
+		if ($this->_is_UI_request === null) {
884
+			//lets set if this is a UI request or not.
885
+			$this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
886
+			//wait a minute... we might have a noheader in the route array
887
+			$this->_is_UI_request = is_array($this->_route)
888
+									&& isset($this->_route['noheader'])
889
+									&& $this->_route['noheader'] ? false : $this->_is_UI_request;
890
+		}
891
+		$this->_set_current_labels();
892
+		return true;
893
+	}
894
+
895
+
896
+
897
+	/**
898
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
899
+	 *
900
+	 * @param  string $route the route name we're verifying
901
+	 * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
902
+	 * @throws EE_Error
903
+	 */
904
+	protected function _verify_route($route)
905
+	{
906
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
907
+			return true;
908
+		}
909
+		// user error msg
910
+		$error_msg = sprintf(
911
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
912
+			$this->_admin_page_title
913
+		);
914
+		// developer error msg
915
+		$error_msg .= '||' . $error_msg . sprintf(
916
+				esc_html__(
917
+					' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
918
+					'event_espresso'
919
+				),
920
+				$route
921
+			);
922
+		throw new EE_Error($error_msg);
923
+	}
924
+
925
+
926
+
927
+	/**
928
+	 * perform nonce verification
929
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
930
+	 * using this method (and save retyping!)
931
+	 *
932
+	 * @param  string $nonce     The nonce sent
933
+	 * @param  string $nonce_ref The nonce reference string (name0)
934
+	 * @return void
935
+	 * @throws EE_Error
936
+	 */
937
+	protected function _verify_nonce($nonce, $nonce_ref)
938
+	{
939
+		// verify nonce against expected value
940
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
941
+			// these are not the droids you are looking for !!!
942
+			$msg = sprintf(
943
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
944
+				'<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
945
+				'</a>'
946
+			);
947
+			if (WP_DEBUG) {
948
+				$msg .= "\n  " . sprintf(
949
+						esc_html__(
950
+							'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
951
+							'event_espresso'
952
+						),
953
+						__CLASS__
954
+					);
955
+			}
956
+			if (! defined('DOING_AJAX')) {
957
+				wp_die($msg);
958
+			} else {
959
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
960
+				$this->_return_json();
961
+			}
962
+		}
963
+	}
964
+
965
+
966
+
967
+	/**
968
+	 * _route_admin_request()
969
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
970
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
971
+	 * in the page routes and then will try to load the corresponding method.
972
+	 *
973
+	 * @return void
974
+	 * @throws EE_Error
975
+	 * @throws InvalidArgumentException
976
+	 * @throws InvalidDataTypeException
977
+	 * @throws InvalidInterfaceException
978
+	 * @throws ReflectionException
979
+	 */
980
+	protected function _route_admin_request()
981
+	{
982
+		if (! $this->_is_UI_request) {
983
+			$this->_verify_routes();
984
+		}
985
+		$nonce_check = isset($this->_route_config['require_nonce'])
986
+			? $this->_route_config['require_nonce']
987
+			: true;
988
+		if ($this->_req_action !== 'default' && $nonce_check) {
989
+			// set nonce from post data
990
+			$nonce = isset($this->_req_data[$this->_req_nonce])
991
+				? sanitize_text_field($this->_req_data[$this->_req_nonce])
992
+				: '';
993
+			$this->_verify_nonce($nonce, $this->_req_nonce);
994
+		}
995
+		//set the nav_tabs array but ONLY if this is  UI_request
996
+		if ($this->_is_UI_request) {
997
+			$this->_set_nav_tabs();
998
+		}
999
+		// grab callback function
1000
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1001
+		// check if callback has args
1002
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1003
+		$error_msg = '';
1004
+		// action right before calling route
1005
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1006
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1007
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1008
+		}
1009
+		// right before calling the route, let's remove _wp_http_referer from the
1010
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1011
+		$_SERVER['REQUEST_URI'] = remove_query_arg(
1012
+				'_wp_http_referer',
1013
+				wp_unslash($_SERVER['REQUEST_URI'])
1014
+		);
1015
+		if (! empty($func)) {
1016
+			if (is_array($func)) {
1017
+				list($class, $method) = $func;
1018
+			} elseif (strpos($func, '::') !== false) {
1019
+				list($class, $method) = explode('::', $func);
1020
+			} else {
1021
+				$class  = $this;
1022
+				$method = $func;
1023
+			}
1024
+			if (! (is_object($class) && $class === $this)) {
1025
+				// send along this admin page object for access by addons.
1026
+				$args['admin_page_object'] = $this;
1027
+			}
1028
+			if (
1029
+				//is it a method on a class that doesn't work?
1030
+				(
1031
+					(
1032
+						method_exists($class, $method)
1033
+						&& call_user_func_array(array($class, $method), $args) === false
1034
+					)
1035
+					&& (
1036
+						//is it a standalone function that doesn't work?
1037
+						function_exists($method)
1038
+						&& call_user_func_array(
1039
+							$func,
1040
+							array_merge(array('admin_page_object' => $this), $args)
1041
+						   ) === false
1042
+					)
1043
+				)
1044
+				|| (
1045
+					//is it neither a class method NOR a standalone function?
1046
+					! method_exists($class, $method)
1047
+					&& ! function_exists($method)
1048
+				)
1049
+			) {
1050
+				// user error msg
1051
+				$error_msg = esc_html__(
1052
+					'An error occurred. The  requested page route could not be found.',
1053
+					'event_espresso'
1054
+				);
1055
+				// developer error msg
1056
+				$error_msg .= '||';
1057
+				$error_msg .= sprintf(
1058
+					esc_html__(
1059
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1060
+						'event_espresso'
1061
+					),
1062
+					$method
1063
+				);
1064
+			}
1065
+			if (! empty($error_msg)) {
1066
+				throw new EE_Error($error_msg);
1067
+			}
1068
+		}
1069
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1070
+		// then we need to reset the routing properties to the new route.
1071
+		//now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1072
+		if ($this->_is_UI_request === false
1073
+			&& is_array($this->_route)
1074
+			&& ! empty($this->_route['headers_sent_route'])
1075
+		) {
1076
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1077
+		}
1078
+	}
1079
+
1080
+
1081
+
1082
+	/**
1083
+	 * This method just allows the resetting of page properties in the case where a no headers
1084
+	 * route redirects to a headers route in its route config.
1085
+	 *
1086
+	 * @since   4.3.0
1087
+	 * @param  string $new_route New (non header) route to redirect to.
1088
+	 * @return   void
1089
+	 * @throws ReflectionException
1090
+	 * @throws InvalidArgumentException
1091
+	 * @throws InvalidInterfaceException
1092
+	 * @throws InvalidDataTypeException
1093
+	 * @throws EE_Error
1094
+	 */
1095
+	protected function _reset_routing_properties($new_route)
1096
+	{
1097
+		$this->_is_UI_request = true;
1098
+		//now we set the current route to whatever the headers_sent_route is set at
1099
+		$this->_req_data['action'] = $new_route;
1100
+		//rerun page setup
1101
+		$this->_page_setup();
1102
+	}
1103
+
1104
+
1105
+
1106
+	/**
1107
+	 * _add_query_arg
1108
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1109
+	 *(internally just uses EEH_URL's function with the same name)
1110
+	 *
1111
+	 * @param array  $args
1112
+	 * @param string $url
1113
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1114
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1115
+	 *                                        Example usage: If the current page is:
1116
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1117
+	 *                                        &action=default&event_id=20&month_range=March%202015
1118
+	 *                                        &_wpnonce=5467821
1119
+	 *                                        and you call:
1120
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1121
+	 *                                        array(
1122
+	 *                                        'action' => 'resend_something',
1123
+	 *                                        'page=>espresso_registrations'
1124
+	 *                                        ),
1125
+	 *                                        $some_url,
1126
+	 *                                        true
1127
+	 *                                        );
1128
+	 *                                        It will produce a url in this structure:
1129
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1130
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1131
+	 *                                        month_range]=March%202015
1132
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1133
+	 * @return string
1134
+	 */
1135
+	public static function add_query_args_and_nonce(
1136
+		$args = array(),
1137
+		$url = false,
1138
+		$sticky = false,
1139
+		$exclude_nonce = false
1140
+	) {
1141
+		//if there is a _wp_http_referer include the values from the request but only if sticky = true
1142
+		if ($sticky) {
1143
+			$request = $_REQUEST;
1144
+			unset($request['_wp_http_referer']);
1145
+			unset($request['wp_referer']);
1146
+			foreach ($request as $key => $value) {
1147
+				//do not add nonces
1148
+				if (strpos($key, 'nonce') !== false) {
1149
+					continue;
1150
+				}
1151
+				$args['wp_referer[' . $key . ']'] = $value;
1152
+			}
1153
+		}
1154
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1155
+	}
1156
+
1157
+
1158
+
1159
+	/**
1160
+	 * This returns a generated link that will load the related help tab.
1161
+	 *
1162
+	 * @param  string $help_tab_id the id for the connected help tab
1163
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1164
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1165
+	 * @uses EEH_Template::get_help_tab_link()
1166
+	 * @return string              generated link
1167
+	 */
1168
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1169
+	{
1170
+		return EEH_Template::get_help_tab_link(
1171
+			$help_tab_id,
1172
+			$this->page_slug,
1173
+			$this->_req_action,
1174
+			$icon_style,
1175
+			$help_text
1176
+		);
1177
+	}
1178
+
1179
+
1180
+
1181
+	/**
1182
+	 * _add_help_tabs
1183
+	 * Note child classes define their help tabs within the page_config array.
1184
+	 *
1185
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1186
+	 * @return void
1187
+	 * @throws DomainException
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _add_help_tabs()
1191
+	{
1192
+		$tour_buttons = '';
1193
+		if (isset($this->_page_config[$this->_req_action])) {
1194
+			$config = $this->_page_config[$this->_req_action];
1195
+			//is there a help tour for the current route?  if there is let's setup the tour buttons
1196
+			if (isset($this->_help_tour[$this->_req_action])) {
1197
+				$tb           = array();
1198
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1199
+				foreach ($this->_help_tour['tours'] as $tour) {
1200
+					//if this is the end tour then we don't need to setup a button
1201
+					if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1202
+						continue;
1203
+					}
1204
+					$tb[] = '<button id="trigger-tour-'
1205
+							. $tour->get_slug()
1206
+							. '" class="button-primary trigger-ee-help-tour">'
1207
+							. $tour->get_label()
1208
+							. '</button>';
1209
+				}
1210
+				$tour_buttons .= implode('<br />', $tb);
1211
+				$tour_buttons .= '</div></div>';
1212
+			}
1213
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1214
+			if (is_array($config) && isset($config['help_sidebar'])) {
1215
+				//check that the callback given is valid
1216
+				if (! method_exists($this, $config['help_sidebar'])) {
1217
+					throw new EE_Error(
1218
+						sprintf(
1219
+							esc_html__(
1220
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1221
+								'event_espresso'
1222
+							),
1223
+							$config['help_sidebar'],
1224
+							get_class($this)
1225
+						)
1226
+					);
1227
+				}
1228
+				$content = apply_filters(
1229
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1230
+					$this->{$config['help_sidebar']}()
1231
+				);
1232
+				$content .= $tour_buttons; //add help tour buttons.
1233
+				//do we have any help tours setup?  Cause if we do we want to add the buttons
1234
+				$this->_current_screen->set_help_sidebar($content);
1235
+			}
1236
+			//if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1237
+			if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1238
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1239
+			}
1240
+			//handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1241
+			if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1242
+				$_ht['id']      = $this->page_slug;
1243
+				$_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1244
+				$_ht['content'] = '<p>' . esc_html__(
1245
+						'The buttons to the right allow you to start/restart any help tours available for this page',
1246
+						'event_espresso'
1247
+					) . '</p>';
1248
+				$this->_current_screen->add_help_tab($_ht);
1249
+			}
1250
+			if (! isset($config['help_tabs'])) {
1251
+				return;
1252
+			} //no help tabs for this route
1253
+			foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1254
+				//we're here so there ARE help tabs!
1255
+				//make sure we've got what we need
1256
+				if (! isset($cfg['title'])) {
1257
+					throw new EE_Error(
1258
+						esc_html__(
1259
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1260
+							'event_espresso'
1261
+						)
1262
+					);
1263
+				}
1264
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1265
+					throw new EE_Error(
1266
+						esc_html__(
1267
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1268
+							'event_espresso'
1269
+						)
1270
+					);
1271
+				}
1272
+				//first priority goes to content.
1273
+				if (! empty($cfg['content'])) {
1274
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1275
+					//second priority goes to filename
1276
+				} elseif (! empty($cfg['filename'])) {
1277
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1278
+					//it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1279
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1280
+															 . basename($this->_get_dir())
1281
+															 . '/help_tabs/'
1282
+															 . $cfg['filename']
1283
+															 . '.help_tab.php' : $file_path;
1284
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1285
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1286
+						EE_Error::add_error(
1287
+							sprintf(
1288
+								esc_html__(
1289
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1290
+									'event_espresso'
1291
+								),
1292
+								$tab_id,
1293
+								key($config),
1294
+								$file_path
1295
+							),
1296
+							__FILE__,
1297
+							__FUNCTION__,
1298
+							__LINE__
1299
+						);
1300
+						return;
1301
+					}
1302
+					$template_args['admin_page_obj'] = $this;
1303
+					$content = EEH_Template::display_template(
1304
+						$file_path,
1305
+						$template_args,
1306
+						true
1307
+					);
1308
+				} else {
1309
+					$content = '';
1310
+				}
1311
+				//check if callback is valid
1312
+				if (
1313
+					empty($content) && (
1314
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1315
+					)
1316
+				) {
1317
+					EE_Error::add_error(
1318
+						sprintf(
1319
+							esc_html__(
1320
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1321
+								'event_espresso'
1322
+							),
1323
+							$cfg['title']
1324
+						),
1325
+						__FILE__,
1326
+						__FUNCTION__,
1327
+						__LINE__
1328
+					);
1329
+					return;
1330
+				}
1331
+				//setup config array for help tab method
1332
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1333
+				$_ht = array(
1334
+					'id'       => $id,
1335
+					'title'    => $cfg['title'],
1336
+					'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1337
+					'content'  => $content,
1338
+				);
1339
+				$this->_current_screen->add_help_tab($_ht);
1340
+			}
1341
+		}
1342
+	}
1343
+
1344
+
1345
+
1346
+	/**
1347
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1348
+	 * an array with properties for setting up usage of the joyride plugin
1349
+	 *
1350
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1351
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1352
+	 *         _set_page_config() comments
1353
+	 * @return void
1354
+	 * @throws EE_Error
1355
+	 * @throws InvalidArgumentException
1356
+	 * @throws InvalidDataTypeException
1357
+	 * @throws InvalidInterfaceException
1358
+	 */
1359
+	protected function _add_help_tour()
1360
+	{
1361
+		$tours            = array();
1362
+		$this->_help_tour = array();
1363
+		//exit early if help tours are turned off globally
1364
+		if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1365
+			|| ! EE_Registry::instance()->CFG->admin->help_tour_activation
1366
+		) {
1367
+			return;
1368
+		}
1369
+		//loop through _page_config to find any help_tour defined
1370
+		foreach ($this->_page_config as $route => $config) {
1371
+			//we're only going to set things up for this route
1372
+			if ($route !== $this->_req_action) {
1373
+				continue;
1374
+			}
1375
+			if (isset($config['help_tour'])) {
1376
+				foreach ($config['help_tour'] as $tour) {
1377
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1378
+					// let's see if we can get that file...
1379
+					// if not its possible this is a decaf route not set in caffeinated
1380
+					// so lets try and get the caffeinated equivalent
1381
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1382
+															 . basename($this->_get_dir())
1383
+															 . '/help_tours/'
1384
+															 . $tour
1385
+															 . '.class.php' : $file_path;
1386
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1387
+					if (! is_readable($file_path)) {
1388
+						EE_Error::add_error(
1389
+							sprintf(
1390
+								esc_html__(
1391
+									'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1392
+									'event_espresso'
1393
+								),
1394
+								$file_path,
1395
+								$tour
1396
+							),
1397
+							__FILE__,
1398
+							__FUNCTION__,
1399
+							__LINE__
1400
+						);
1401
+						return;
1402
+					}
1403
+					require_once $file_path;
1404
+					if (! class_exists($tour)) {
1405
+						$error_msg[] = sprintf(
1406
+							esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1407
+							$tour
1408
+						);
1409
+						$error_msg[] = $error_msg[0] . "\r\n" . sprintf(
1410
+								esc_html__(
1411
+									'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1412
+									'event_espresso'
1413
+								),
1414
+								$tour,
1415
+								'<br />',
1416
+								$tour,
1417
+								$this->_req_action,
1418
+								get_class($this)
1419
+							);
1420
+						throw new EE_Error(implode('||', $error_msg));
1421
+					}
1422
+					$tour_obj                   = new $tour($this->_is_caf);
1423
+					$tours[]                    = $tour_obj;
1424
+					$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1425
+				}
1426
+				//let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1427
+				$end_stop_tour              = new EE_Help_Tour_final_stop($this->_is_caf);
1428
+				$tours[]                    = $end_stop_tour;
1429
+				$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1430
+			}
1431
+		}
1432
+		if (! empty($tours)) {
1433
+			$this->_help_tour['tours'] = $tours;
1434
+		}
1435
+		// that's it!  Now that the $_help_tours property is set (or not)
1436
+		// the scripts and html should be taken care of automatically.
1437
+	}
1438
+
1439
+
1440
+
1441
+	/**
1442
+	 * This simply sets up any qtips that have been defined in the page config
1443
+	 *
1444
+	 * @return void
1445
+	 */
1446
+	protected function _add_qtips()
1447
+	{
1448
+		if (isset($this->_route_config['qtips'])) {
1449
+			$qtips = (array)$this->_route_config['qtips'];
1450
+			//load qtip loader
1451
+			$path = array(
1452
+				$this->_get_dir() . '/qtips/',
1453
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1454
+			);
1455
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1456
+		}
1457
+	}
1458
+
1459
+
1460
+
1461
+	/**
1462
+	 * _set_nav_tabs
1463
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1464
+	 * wish to add additional tabs or modify accordingly.
1465
+	 *
1466
+	 * @return void
1467
+	 * @throws InvalidArgumentException
1468
+	 * @throws InvalidInterfaceException
1469
+	 * @throws InvalidDataTypeException
1470
+	 */
1471
+	protected function _set_nav_tabs()
1472
+	{
1473
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1474
+		$i = 0;
1475
+		foreach ($this->_page_config as $slug => $config) {
1476
+			if (
1477
+				! is_array($config)
1478
+				|| (
1479
+					is_array($config)
1480
+					&& (
1481
+						(isset($config['nav']) && ! $config['nav'])
1482
+						|| ! isset($config['nav'])
1483
+					)
1484
+				)
1485
+			) {
1486
+				continue;
1487
+			}
1488
+			//no nav tab for this config
1489
+			//check for persistent flag
1490
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1491
+				// nav tab is only to appear when route requested.
1492
+				continue;
1493
+			}
1494
+			if (! $this->check_user_access($slug, true)) {
1495
+				// no nav tab because current user does not have access.
1496
+				continue;
1497
+			}
1498
+			$css_class              = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1499
+			$this->_nav_tabs[$slug] = array(
1500
+				'url'       => isset($config['nav']['url'])
1501
+					? $config['nav']['url']
1502
+					: self::add_query_args_and_nonce(
1503
+						array('action' => $slug),
1504
+						$this->_admin_base_url
1505
+					),
1506
+				'link_text' => isset($config['nav']['label'])
1507
+					? $config['nav']['label']
1508
+					: ucwords(
1509
+						str_replace('_', ' ', $slug)
1510
+					),
1511
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1512
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1513
+			);
1514
+			$i++;
1515
+		}
1516
+		//if $this->_nav_tabs is empty then lets set the default
1517
+		if (empty($this->_nav_tabs)) {
1518
+			$this->_nav_tabs[$this->_default_nav_tab_name] = array(
1519
+				'url'       => $this->_admin_base_url,
1520
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1521
+				'css_class' => 'nav-tab-active',
1522
+				'order'     => 10,
1523
+			);
1524
+		}
1525
+		//now let's sort the tabs according to order
1526
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1527
+	}
1528
+
1529
+
1530
+
1531
+	/**
1532
+	 * _set_current_labels
1533
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1534
+	 * property array
1535
+	 *
1536
+	 * @return void
1537
+	 */
1538
+	private function _set_current_labels()
1539
+	{
1540
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1541
+			foreach ($this->_route_config['labels'] as $label => $text) {
1542
+				if (is_array($text)) {
1543
+					foreach ($text as $sublabel => $subtext) {
1544
+						$this->_labels[$label][$sublabel] = $subtext;
1545
+					}
1546
+				} else {
1547
+					$this->_labels[$label] = $text;
1548
+				}
1549
+			}
1550
+		}
1551
+	}
1552
+
1553
+
1554
+
1555
+	/**
1556
+	 *        verifies user access for this admin page
1557
+	 *
1558
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1559
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1560
+	 *                               return false if verify fail.
1561
+	 * @return bool
1562
+	 * @throws InvalidArgumentException
1563
+	 * @throws InvalidDataTypeException
1564
+	 * @throws InvalidInterfaceException
1565
+	 */
1566
+	public function check_user_access($route_to_check = '', $verify_only = false)
1567
+	{
1568
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1569
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1570
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1571
+						  && is_array(
1572
+							  $this->_page_routes[$route_to_check]
1573
+						  )
1574
+						  && ! empty($this->_page_routes[$route_to_check]['capability'])
1575
+			? $this->_page_routes[$route_to_check]['capability'] : null;
1576
+		if (empty($capability) && empty($route_to_check)) {
1577
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1578
+				: $this->_route['capability'];
1579
+		} else {
1580
+			$capability = empty($capability) ? 'manage_options' : $capability;
1581
+		}
1582
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1583
+		if (
1584
+			! defined('DOING_AJAX')
1585
+			&& (
1586
+				! function_exists('is_admin')
1587
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1588
+					$capability,
1589
+					$this->page_slug
1590
+					. '_'
1591
+					. $route_to_check,
1592
+					$id
1593
+				)
1594
+			)
1595
+		) {
1596
+			if ($verify_only) {
1597
+				return false;
1598
+			}
1599
+			if (is_user_logged_in()) {
1600
+				wp_die(__('You do not have access to this route.', 'event_espresso'));
1601
+			} else {
1602
+				return false;
1603
+			}
1604
+		}
1605
+		return true;
1606
+	}
1607
+
1608
+
1609
+
1610
+	/**
1611
+	 * admin_init_global
1612
+	 * This runs all the code that we want executed within the WP admin_init hook.
1613
+	 * This method executes for ALL EE Admin pages.
1614
+	 *
1615
+	 * @return void
1616
+	 */
1617
+	public function admin_init_global()
1618
+	{
1619
+	}
1620
+
1621
+
1622
+
1623
+	/**
1624
+	 * wp_loaded_global
1625
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1626
+	 * EE_Admin page and will execute on every EE Admin Page load
1627
+	 *
1628
+	 * @return void
1629
+	 */
1630
+	public function wp_loaded()
1631
+	{
1632
+	}
1633
+
1634
+
1635
+
1636
+	/**
1637
+	 * admin_notices
1638
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1639
+	 * ALL EE_Admin pages.
1640
+	 *
1641
+	 * @return void
1642
+	 */
1643
+	public function admin_notices_global()
1644
+	{
1645
+		$this->_display_no_javascript_warning();
1646
+		$this->_display_espresso_notices();
1647
+	}
1648
+
1649
+
1650
+
1651
+	public function network_admin_notices_global()
1652
+	{
1653
+		$this->_display_no_javascript_warning();
1654
+		$this->_display_espresso_notices();
1655
+	}
1656
+
1657
+
1658
+
1659
+	/**
1660
+	 * admin_footer_scripts_global
1661
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1662
+	 * will apply on ALL EE_Admin pages.
1663
+	 *
1664
+	 * @return void
1665
+	 */
1666
+	public function admin_footer_scripts_global()
1667
+	{
1668
+		$this->_add_admin_page_ajax_loading_img();
1669
+		$this->_add_admin_page_overlay();
1670
+		//if metaboxes are present we need to add the nonce field
1671
+		if (
1672
+			 isset($this->_route_config['metaboxes'])
1673
+			 || isset($this->_route_config['list_table'])
1674
+			 || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1675
+		) {
1676
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1677
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1678
+		}
1679
+	}
1680
+
1681
+
1682
+
1683
+	/**
1684
+	 * admin_footer_global
1685
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1686
+	 * ALL EE_Admin Pages.
1687
+	 *
1688
+	 * @return void
1689
+	 * @throws EE_Error
1690
+	 */
1691
+	public function admin_footer_global()
1692
+	{
1693
+		//dialog container for dialog helper
1694
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1695
+		$d_cont .= '<div class="ee-notices"></div>';
1696
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1697
+		$d_cont .= '</div>';
1698
+		echo $d_cont;
1699
+		//help tour stuff?
1700
+		if (isset($this->_help_tour[$this->_req_action])) {
1701
+			echo implode('<br />', $this->_help_tour[$this->_req_action]);
1702
+		}
1703
+		//current set timezone for timezone js
1704
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1705
+	}
1706
+
1707
+
1708
+
1709
+	/**
1710
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1711
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1712
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1713
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1714
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1715
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1716
+	 * for the
1717
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1718
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1719
+	 *    'help_trigger_id' => array(
1720
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1721
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1722
+	 *    )
1723
+	 * );
1724
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1725
+	 *
1726
+	 * @param array $help_array
1727
+	 * @param bool  $display
1728
+	 * @return string content
1729
+	 * @throws DomainException
1730
+	 * @throws EE_Error
1731
+	 */
1732
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1733
+	{
1734
+		$content       = '';
1735
+		$help_array    = empty($help_array) ? $this->_get_help_content() : $help_array;
1736
+		//loop through the array and setup content
1737
+		foreach ($help_array as $trigger => $help) {
1738
+			//make sure the array is setup properly
1739
+			if (! isset($help['title']) || ! isset($help['content'])) {
1740
+				throw new EE_Error(
1741
+					esc_html__(
1742
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1743
+						'event_espresso'
1744
+					)
1745
+				);
1746
+			}
1747
+			//we're good so let'd setup the template vars and then assign parsed template content to our content.
1748
+			$template_args = array(
1749
+				'help_popup_id'      => $trigger,
1750
+				'help_popup_title'   => $help['title'],
1751
+				'help_popup_content' => $help['content'],
1752
+			);
1753
+			$content       .= EEH_Template::display_template(
1754
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1755
+				$template_args,
1756
+				true
1757
+			);
1758
+		}
1759
+		if ($display) {
1760
+			echo $content;
1761
+			return '';
1762
+		}
1763
+		return $content;
1764
+	}
1765
+
1766
+
1767
+
1768
+	/**
1769
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1770
+	 *
1771
+	 * @return array properly formatted array for help popup content
1772
+	 * @throws EE_Error
1773
+	 */
1774
+	private function _get_help_content()
1775
+	{
1776
+		//what is the method we're looking for?
1777
+		$method_name = '_help_popup_content_' . $this->_req_action;
1778
+		//if method doesn't exist let's get out.
1779
+		if (! method_exists($this, $method_name)) {
1780
+			return array();
1781
+		}
1782
+		//k we're good to go let's retrieve the help array
1783
+		$help_array = call_user_func(array($this, $method_name));
1784
+		//make sure we've got an array!
1785
+		if (! is_array($help_array)) {
1786
+			throw new EE_Error(
1787
+				esc_html__(
1788
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1789
+					'event_espresso'
1790
+				)
1791
+			);
1792
+		}
1793
+		return $help_array;
1794
+	}
1795
+
1796
+
1797
+
1798
+	/**
1799
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1800
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1801
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1802
+	 *
1803
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1804
+	 * @param boolean $display    if false then we return the trigger string
1805
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1806
+	 * @return string
1807
+	 * @throws DomainException
1808
+	 * @throws EE_Error
1809
+	 */
1810
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1811
+	{
1812
+		if (defined('DOING_AJAX')) {
1813
+			return '';
1814
+		}
1815
+		//let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1816
+		$help_array   = $this->_get_help_content();
1817
+		$help_content = '';
1818
+		if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1819
+			$help_array[$trigger_id] = array(
1820
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1821
+				'content' => esc_html__(
1822
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1823
+					'event_espresso'
1824
+				),
1825
+			);
1826
+			$help_content            = $this->_set_help_popup_content($help_array, false);
1827
+		}
1828
+		//let's setup the trigger
1829
+		$content = '<a class="ee-dialog" href="?height='
1830
+				   . $dimensions[0]
1831
+				   . '&width='
1832
+				   . $dimensions[1]
1833
+				   . '&inlineId='
1834
+				   . $trigger_id
1835
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1836
+		$content .= $help_content;
1837
+		if ($display) {
1838
+			echo $content;
1839
+			return  '';
1840
+		}
1841
+		return $content;
1842
+	}
1843
+
1844
+
1845
+
1846
+	/**
1847
+	 * _add_global_screen_options
1848
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1849
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1850
+	 *
1851
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1852
+	 *         see also WP_Screen object documents...
1853
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1854
+	 * @abstract
1855
+	 * @return void
1856
+	 */
1857
+	private function _add_global_screen_options()
1858
+	{
1859
+	}
1860
+
1861
+
1862
+
1863
+	/**
1864
+	 * _add_global_feature_pointers
1865
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1868
+	 *
1869
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
+	 *         extended) also see:
1871
+	 * @link   http://eamann.com/tech/wordpress-portland/
1872
+	 * @abstract
1873
+	 * @return void
1874
+	 */
1875
+	private function _add_global_feature_pointers()
1876
+	{
1877
+	}
1878
+
1879
+
1880
+
1881
+	/**
1882
+	 * load_global_scripts_styles
1883
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1884
+	 *
1885
+	 * @return void
1886
+	 * @throws EE_Error
1887
+	 */
1888
+	public function load_global_scripts_styles()
1889
+	{
1890
+		/** STYLES **/
1891
+		// add debugging styles
1892
+		if (WP_DEBUG) {
1893
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1894
+		}
1895
+		// register all styles
1896
+		wp_register_style(
1897
+			'espresso-ui-theme',
1898
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1899
+			array(),
1900
+			EVENT_ESPRESSO_VERSION
1901
+		);
1902
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1903
+		//helpers styles
1904
+		wp_register_style(
1905
+			'ee-text-links',
1906
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1907
+			array(),
1908
+			EVENT_ESPRESSO_VERSION
1909
+		);
1910
+		/** SCRIPTS **/
1911
+		//register all scripts
1912
+		wp_register_script(
1913
+			'ee-dialog',
1914
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1915
+			array('jquery', 'jquery-ui-draggable'),
1916
+			EVENT_ESPRESSO_VERSION,
1917
+			true
1918
+		);
1919
+		wp_register_script(
1920
+			'ee_admin_js',
1921
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
1922
+			array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1923
+			EVENT_ESPRESSO_VERSION,
1924
+			true
1925
+		);
1926
+		wp_register_script(
1927
+			'jquery-ui-timepicker-addon',
1928
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1929
+			array('jquery-ui-datepicker', 'jquery-ui-slider'),
1930
+			EVENT_ESPRESSO_VERSION,
1931
+			true
1932
+		);
1933
+		add_filter('FHEE_load_joyride', '__return_true');
1934
+		//script for sorting tables
1935
+		wp_register_script(
1936
+			'espresso_ajax_table_sorting',
1937
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1938
+			array('ee_admin_js', 'jquery-ui-sortable'),
1939
+			EVENT_ESPRESSO_VERSION,
1940
+			true
1941
+		);
1942
+		//script for parsing uri's
1943
+		wp_register_script(
1944
+			'ee-parse-uri',
1945
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1946
+			array(),
1947
+			EVENT_ESPRESSO_VERSION,
1948
+			true
1949
+		);
1950
+		//and parsing associative serialized form elements
1951
+		wp_register_script(
1952
+			'ee-serialize-full-array',
1953
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1954
+			array('jquery'),
1955
+			EVENT_ESPRESSO_VERSION,
1956
+			true
1957
+		);
1958
+		//helpers scripts
1959
+		wp_register_script(
1960
+			'ee-text-links',
1961
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1962
+			array('jquery'),
1963
+			EVENT_ESPRESSO_VERSION,
1964
+			true
1965
+		);
1966
+		wp_register_script(
1967
+			'ee-moment-core',
1968
+			EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1969
+			array(),
1970
+			EVENT_ESPRESSO_VERSION,
1971
+			true
1972
+		);
1973
+		wp_register_script(
1974
+			'ee-moment',
1975
+			EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1976
+			array('ee-moment-core'),
1977
+			EVENT_ESPRESSO_VERSION,
1978
+			true
1979
+		);
1980
+		wp_register_script(
1981
+			'ee-datepicker',
1982
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
1983
+			array('jquery-ui-timepicker-addon', 'ee-moment'),
1984
+			EVENT_ESPRESSO_VERSION,
1985
+			true
1986
+		);
1987
+		//google charts
1988
+		wp_register_script(
1989
+			'google-charts',
1990
+			'https://www.gstatic.com/charts/loader.js',
1991
+			array(),
1992
+			EVENT_ESPRESSO_VERSION,
1993
+			false
1994
+		);
1995
+		// ENQUEUE ALL BASICS BY DEFAULT
1996
+		wp_enqueue_style('ee-admin-css');
1997
+		wp_enqueue_script('ee_admin_js');
1998
+		wp_enqueue_script('ee-accounting');
1999
+		wp_enqueue_script('jquery-validate');
2000
+		//taking care of metaboxes
2001
+		if (
2002
+			empty($this->_cpt_route)
2003
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2004
+		) {
2005
+			wp_enqueue_script('dashboard');
2006
+		}
2007
+		// LOCALIZED DATA
2008
+		//localize script for ajax lazy loading
2009
+		$lazy_loader_container_ids = apply_filters(
2010
+			'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2011
+			array('espresso_news_post_box_content')
2012
+		);
2013
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2014
+		/**
2015
+		 * help tour stuff
2016
+		 */
2017
+		if (! empty($this->_help_tour)) {
2018
+			//register the js for kicking things off
2019
+			wp_enqueue_script(
2020
+				'ee-help-tour',
2021
+				EE_ADMIN_URL . 'assets/ee-help-tour.js',
2022
+				array('jquery-joyride'),
2023
+				EVENT_ESPRESSO_VERSION,
2024
+				true
2025
+			);
2026
+			$tours = array();
2027
+			//setup tours for the js tour object
2028
+			foreach ($this->_help_tour['tours'] as $tour) {
2029
+				if ($tour instanceof EE_Help_Tour) {
2030
+					$tours[] = array(
2031
+						'id'      => $tour->get_slug(),
2032
+						'options' => $tour->get_options(),
2033
+					);
2034
+				}
2035
+			}
2036
+			wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2037
+			//admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2038
+		}
2039
+	}
2040
+
2041
+
2042
+
2043
+	/**
2044
+	 *        admin_footer_scripts_eei18n_js_strings
2045
+	 *
2046
+	 * @return        void
2047
+	 */
2048
+	public function admin_footer_scripts_eei18n_js_strings()
2049
+	{
2050
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2051
+		EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2052
+			'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2053
+			'event_espresso'
2054
+		);
2055
+		EE_Registry::$i18n_js_strings['January']        = esc_html__('January', 'event_espresso');
2056
+		EE_Registry::$i18n_js_strings['February']       = esc_html__('February', 'event_espresso');
2057
+		EE_Registry::$i18n_js_strings['March']          = esc_html__('March', 'event_espresso');
2058
+		EE_Registry::$i18n_js_strings['April']          = esc_html__('April', 'event_espresso');
2059
+		EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2060
+		EE_Registry::$i18n_js_strings['June']           = esc_html__('June', 'event_espresso');
2061
+		EE_Registry::$i18n_js_strings['July']           = esc_html__('July', 'event_espresso');
2062
+		EE_Registry::$i18n_js_strings['August']         = esc_html__('August', 'event_espresso');
2063
+		EE_Registry::$i18n_js_strings['September']      = esc_html__('September', 'event_espresso');
2064
+		EE_Registry::$i18n_js_strings['October']        = esc_html__('October', 'event_espresso');
2065
+		EE_Registry::$i18n_js_strings['November']       = esc_html__('November', 'event_espresso');
2066
+		EE_Registry::$i18n_js_strings['December']       = esc_html__('December', 'event_espresso');
2067
+		EE_Registry::$i18n_js_strings['Jan']            = esc_html__('Jan', 'event_espresso');
2068
+		EE_Registry::$i18n_js_strings['Feb']            = esc_html__('Feb', 'event_espresso');
2069
+		EE_Registry::$i18n_js_strings['Mar']            = esc_html__('Mar', 'event_espresso');
2070
+		EE_Registry::$i18n_js_strings['Apr']            = esc_html__('Apr', 'event_espresso');
2071
+		EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2072
+		EE_Registry::$i18n_js_strings['Jun']            = esc_html__('Jun', 'event_espresso');
2073
+		EE_Registry::$i18n_js_strings['Jul']            = esc_html__('Jul', 'event_espresso');
2074
+		EE_Registry::$i18n_js_strings['Aug']            = esc_html__('Aug', 'event_espresso');
2075
+		EE_Registry::$i18n_js_strings['Sep']            = esc_html__('Sep', 'event_espresso');
2076
+		EE_Registry::$i18n_js_strings['Oct']            = esc_html__('Oct', 'event_espresso');
2077
+		EE_Registry::$i18n_js_strings['Nov']            = esc_html__('Nov', 'event_espresso');
2078
+		EE_Registry::$i18n_js_strings['Dec']            = esc_html__('Dec', 'event_espresso');
2079
+		EE_Registry::$i18n_js_strings['Sunday']         = esc_html__('Sunday', 'event_espresso');
2080
+		EE_Registry::$i18n_js_strings['Monday']         = esc_html__('Monday', 'event_espresso');
2081
+		EE_Registry::$i18n_js_strings['Tuesday']        = esc_html__('Tuesday', 'event_espresso');
2082
+		EE_Registry::$i18n_js_strings['Wednesday']      = esc_html__('Wednesday', 'event_espresso');
2083
+		EE_Registry::$i18n_js_strings['Thursday']       = esc_html__('Thursday', 'event_espresso');
2084
+		EE_Registry::$i18n_js_strings['Friday']         = esc_html__('Friday', 'event_espresso');
2085
+		EE_Registry::$i18n_js_strings['Saturday']       = esc_html__('Saturday', 'event_espresso');
2086
+		EE_Registry::$i18n_js_strings['Sun']            = esc_html__('Sun', 'event_espresso');
2087
+		EE_Registry::$i18n_js_strings['Mon']            = esc_html__('Mon', 'event_espresso');
2088
+		EE_Registry::$i18n_js_strings['Tue']            = esc_html__('Tue', 'event_espresso');
2089
+		EE_Registry::$i18n_js_strings['Wed']            = esc_html__('Wed', 'event_espresso');
2090
+		EE_Registry::$i18n_js_strings['Thu']            = esc_html__('Thu', 'event_espresso');
2091
+		EE_Registry::$i18n_js_strings['Fri']            = esc_html__('Fri', 'event_espresso');
2092
+		EE_Registry::$i18n_js_strings['Sat']            = esc_html__('Sat', 'event_espresso');
2093
+	}
2094
+
2095
+
2096
+
2097
+	/**
2098
+	 *        load enhanced xdebug styles for ppl with failing eyesight
2099
+	 *
2100
+	 * @return        void
2101
+	 */
2102
+	public function add_xdebug_style()
2103
+	{
2104
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2105
+	}
2106
+
2107
+
2108
+	/************************/
2109
+	/** LIST TABLE METHODS **/
2110
+	/************************/
2111
+	/**
2112
+	 * this sets up the list table if the current view requires it.
2113
+	 *
2114
+	 * @return void
2115
+	 * @throws EE_Error
2116
+	 */
2117
+	protected function _set_list_table()
2118
+	{
2119
+		//first is this a list_table view?
2120
+		if (! isset($this->_route_config['list_table'])) {
2121
+			return;
2122
+		} //not a list_table view so get out.
2123
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2124
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2125
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2126
+			//user error msg
2127
+			$error_msg = esc_html__(
2128
+				'An error occurred. The requested list table views could not be found.',
2129
+				'event_espresso'
2130
+			);
2131
+			//developer error msg
2132
+			$error_msg .= '||' . sprintf(
2133
+					esc_html__(
2134
+						'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2135
+						'event_espresso'
2136
+					),
2137
+					$this->_req_action,
2138
+					$list_table_view
2139
+				);
2140
+			throw new EE_Error($error_msg);
2141
+		}
2142
+		//let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2143
+		$this->_views = apply_filters(
2144
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2145
+			$this->_views
2146
+		);
2147
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2148
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2149
+		$this->_set_list_table_view();
2150
+		$this->_set_list_table_object();
2151
+	}
2152
+
2153
+
2154
+
2155
+	/**
2156
+	 * set current view for List Table
2157
+	 *
2158
+	 * @return void
2159
+	 */
2160
+	protected function _set_list_table_view()
2161
+	{
2162
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2163
+		// looking at active items or dumpster diving ?
2164
+		if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2165
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2166
+		} else {
2167
+			$this->_view = sanitize_key($this->_req_data['status']);
2168
+		}
2169
+	}
2170
+
2171
+
2172
+	/**
2173
+	 * _set_list_table_object
2174
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2175
+	 *
2176
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2177
+	 * @throws \InvalidArgumentException
2178
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2179
+	 * @throws EE_Error
2180
+	 * @throws InvalidInterfaceException
2181
+	 */
2182
+	protected function _set_list_table_object()
2183
+	{
2184
+		if (isset($this->_route_config['list_table'])) {
2185
+			if (! class_exists($this->_route_config['list_table'])) {
2186
+				throw new EE_Error(
2187
+					sprintf(
2188
+						esc_html__(
2189
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2190
+							'event_espresso'
2191
+						),
2192
+						$this->_route_config['list_table'],
2193
+						get_class($this)
2194
+					)
2195
+				);
2196
+			}
2197
+			$this->_list_table_object = LoaderFactory::getLoader()->getShared(
2198
+				$this->_route_config['list_table'],
2199
+				array($this)
2200
+			);
2201
+		}
2202
+	}
2203
+
2204
+
2205
+
2206
+	/**
2207
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2208
+	 *
2209
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2210
+	 *                                                    urls.  The array should be indexed by the view it is being
2211
+	 *                                                    added to.
2212
+	 * @return array
2213
+	 */
2214
+	public function get_list_table_view_RLs($extra_query_args = array())
2215
+	{
2216
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2217
+		if (empty($this->_views)) {
2218
+			$this->_views = array();
2219
+		}
2220
+		// cycle thru views
2221
+		foreach ($this->_views as $key => $view) {
2222
+			$query_args = array();
2223
+			// check for current view
2224
+			$this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2225
+			$query_args['action']                      = $this->_req_action;
2226
+			$query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2227
+			$query_args['status']                      = $view['slug'];
2228
+			//merge any other arguments sent in.
2229
+			if (isset($extra_query_args[$view['slug']])) {
2230
+				$query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2231
+			}
2232
+			$this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2233
+		}
2234
+		return $this->_views;
2235
+	}
2236
+
2237
+
2238
+
2239
+	/**
2240
+	 * _entries_per_page_dropdown
2241
+	 * generates a drop down box for selecting the number of visible rows in an admin page list table
2242
+	 *
2243
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2244
+	 *         WP does it.
2245
+	 * @param int $max_entries total number of rows in the table
2246
+	 * @return string
2247
+	 */
2248
+	protected function _entries_per_page_dropdown($max_entries = 0)
2249
+	{
2250
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2251
+		$values   = array(10, 25, 50, 100);
2252
+		$per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2253
+		if ($max_entries) {
2254
+			$values[] = $max_entries;
2255
+			sort($values);
2256
+		}
2257
+		$entries_per_page_dropdown = '
2258 2258
 			<div id="entries-per-page-dv" class="alignleft actions">
2259 2259
 				<label class="hide-if-no-js">
2260 2260
 					Show
2261 2261
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2262
-        foreach ($values as $value) {
2263
-            if ($value < $max_entries) {
2264
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2265
-                $entries_per_page_dropdown .= '
2262
+		foreach ($values as $value) {
2263
+			if ($value < $max_entries) {
2264
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2265
+				$entries_per_page_dropdown .= '
2266 2266
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2267
-            }
2268
-        }
2269
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2270
-        $entries_per_page_dropdown .= '
2267
+			}
2268
+		}
2269
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2270
+		$entries_per_page_dropdown .= '
2271 2271
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2272
-        $entries_per_page_dropdown .= '
2272
+		$entries_per_page_dropdown .= '
2273 2273
 					</select>
2274 2274
 					entries
2275 2275
 				</label>
2276 2276
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2277 2277
 			</div>
2278 2278
 		';
2279
-        return $entries_per_page_dropdown;
2280
-    }
2281
-
2282
-
2283
-
2284
-    /**
2285
-     *        _set_search_attributes
2286
-     *
2287
-     * @return        void
2288
-     */
2289
-    public function _set_search_attributes()
2290
-    {
2291
-        $this->_template_args['search']['btn_label'] = sprintf(
2292
-            esc_html__('Search %s', 'event_espresso'),
2293
-            empty($this->_search_btn_label) ? $this->page_label
2294
-                : $this->_search_btn_label
2295
-        );
2296
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2297
-    }
2298
-
2299
-
2300
-
2301
-    /*** END LIST TABLE METHODS **/
2302
-
2303
-
2304
-
2305
-    /**
2306
-     * _add_registered_metaboxes
2307
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2308
-     *
2309
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2310
-     * @return void
2311
-     * @throws EE_Error
2312
-     */
2313
-    private function _add_registered_meta_boxes()
2314
-    {
2315
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2316
-        //we only add meta boxes if the page_route calls for it
2317
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2318
-            && is_array(
2319
-                $this->_route_config['metaboxes']
2320
-            )
2321
-        ) {
2322
-            // this simply loops through the callbacks provided
2323
-            // and checks if there is a corresponding callback registered by the child
2324
-            // if there is then we go ahead and process the metabox loader.
2325
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2326
-                // first check for Closures
2327
-                if ($metabox_callback instanceof Closure) {
2328
-                    $result = $metabox_callback();
2329
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2330
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2331
-                } else {
2332
-                    $result = call_user_func(array($this, &$metabox_callback));
2333
-                }
2334
-                if ($result === false) {
2335
-                    // user error msg
2336
-                    $error_msg = esc_html__(
2337
-                            'An error occurred. The  requested metabox could not be found.',
2338
-                            'event_espresso'
2339
-                    );
2340
-                    // developer error msg
2341
-                    $error_msg .= '||' . sprintf(
2342
-                            esc_html__(
2343
-                                'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2344
-                                'event_espresso'
2345
-                            ),
2346
-                            $metabox_callback
2347
-                        );
2348
-                    throw new EE_Error($error_msg);
2349
-                }
2350
-            }
2351
-        }
2352
-    }
2353
-
2354
-
2355
-
2356
-    /**
2357
-     * _add_screen_columns
2358
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2359
-     * the dynamic column template and we'll setup the column options for the page.
2360
-     *
2361
-     * @return void
2362
-     */
2363
-    private function _add_screen_columns()
2364
-    {
2365
-        if (
2366
-            is_array($this->_route_config)
2367
-            && isset($this->_route_config['columns'])
2368
-            && is_array($this->_route_config['columns'])
2369
-            && count($this->_route_config['columns']) === 2
2370
-        ) {
2371
-            add_screen_option(
2372
-                'layout_columns',
2373
-                array(
2374
-                    'max'     => (int)$this->_route_config['columns'][0],
2375
-                    'default' => (int)$this->_route_config['columns'][1],
2376
-                )
2377
-            );
2378
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2379
-            $screen_id                                           = $this->_current_screen->id;
2380
-            $screen_columns                                      = (int)get_user_option("screen_layout_{$screen_id}");
2381
-            $total_columns                                       = ! empty($screen_columns)
2382
-                ? $screen_columns
2383
-                : $this->_route_config['columns'][1];
2384
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2385
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2386
-            $this->_template_args['screen']                      = $this->_current_screen;
2387
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2388
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2389
-            // finally if we don't have has_metaboxes set in the route config
2390
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2391
-            $this->_route_config['has_metaboxes'] = true;
2392
-        }
2393
-    }
2394
-
2395
-
2396
-
2397
-    /** GLOBALLY AVAILABLE METABOXES **/
2398
-
2399
-
2400
-    /**
2401
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2402
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2403
-     * these get loaded on.
2404
-     */
2405
-    private function _espresso_news_post_box()
2406
-    {
2407
-        $news_box_title = apply_filters(
2408
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2409
-            esc_html__('New @ Event Espresso', 'event_espresso')
2410
-        );
2411
-        add_meta_box(
2412
-            'espresso_news_post_box',
2413
-            $news_box_title,
2414
-            array(
2415
-                $this,
2416
-                'espresso_news_post_box',
2417
-            ),
2418
-            $this->_wp_page_slug,
2419
-            'side'
2420
-        );
2421
-    }
2422
-
2423
-
2424
-
2425
-    /**
2426
-     * Code for setting up espresso ratings request metabox.
2427
-     */
2428
-    protected function _espresso_ratings_request()
2429
-    {
2430
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2431
-            return;
2432
-        }
2433
-        $ratings_box_title = apply_filters(
2434
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2435
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2436
-        );
2437
-        add_meta_box(
2438
-            'espresso_ratings_request',
2439
-            $ratings_box_title,
2440
-            array(
2441
-                $this,
2442
-                'espresso_ratings_request',
2443
-            ),
2444
-            $this->_wp_page_slug,
2445
-            'side'
2446
-        );
2447
-    }
2448
-
2449
-
2450
-
2451
-    /**
2452
-     * Code for setting up espresso ratings request metabox content.
2453
-     *
2454
-     * @throws DomainException
2455
-     */
2456
-    public function espresso_ratings_request()
2457
-    {
2458
-        EEH_Template::display_template(
2459
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2460
-                array()
2461
-        );
2462
-    }
2463
-
2464
-
2465
-
2466
-    public static function cached_rss_display($rss_id, $url)
2467
-    {
2468
-        $loading    = '<p class="widget-loading hide-if-no-js">'
2469
-                      . __('Loading&#8230;')
2470
-                      . '</p><p class="hide-if-js">'
2471
-                      . esc_html__('This widget requires JavaScript.')
2472
-                      . '</p>';
2473
-        $pre        = '<div class="espresso-rss-display">' . "\n\t";
2474
-        $pre        .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2475
-        $post       = '</div>' . "\n";
2476
-        $cache_key  = 'ee_rss_' . md5($rss_id);
2477
-        $output = get_transient($cache_key);
2478
-        if ($output !== false) {
2479
-            echo $pre . $output . $post;
2480
-            return true;
2481
-        }
2482
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2483
-            echo $pre . $loading . $post;
2484
-            return false;
2485
-        }
2486
-        ob_start();
2487
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2488
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2489
-        return true;
2490
-    }
2491
-
2492
-
2493
-
2494
-    public function espresso_news_post_box()
2495
-    {
2496
-        ?>
2279
+		return $entries_per_page_dropdown;
2280
+	}
2281
+
2282
+
2283
+
2284
+	/**
2285
+	 *        _set_search_attributes
2286
+	 *
2287
+	 * @return        void
2288
+	 */
2289
+	public function _set_search_attributes()
2290
+	{
2291
+		$this->_template_args['search']['btn_label'] = sprintf(
2292
+			esc_html__('Search %s', 'event_espresso'),
2293
+			empty($this->_search_btn_label) ? $this->page_label
2294
+				: $this->_search_btn_label
2295
+		);
2296
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2297
+	}
2298
+
2299
+
2300
+
2301
+	/*** END LIST TABLE METHODS **/
2302
+
2303
+
2304
+
2305
+	/**
2306
+	 * _add_registered_metaboxes
2307
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2308
+	 *
2309
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2310
+	 * @return void
2311
+	 * @throws EE_Error
2312
+	 */
2313
+	private function _add_registered_meta_boxes()
2314
+	{
2315
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2316
+		//we only add meta boxes if the page_route calls for it
2317
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2318
+			&& is_array(
2319
+				$this->_route_config['metaboxes']
2320
+			)
2321
+		) {
2322
+			// this simply loops through the callbacks provided
2323
+			// and checks if there is a corresponding callback registered by the child
2324
+			// if there is then we go ahead and process the metabox loader.
2325
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2326
+				// first check for Closures
2327
+				if ($metabox_callback instanceof Closure) {
2328
+					$result = $metabox_callback();
2329
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2330
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2331
+				} else {
2332
+					$result = call_user_func(array($this, &$metabox_callback));
2333
+				}
2334
+				if ($result === false) {
2335
+					// user error msg
2336
+					$error_msg = esc_html__(
2337
+							'An error occurred. The  requested metabox could not be found.',
2338
+							'event_espresso'
2339
+					);
2340
+					// developer error msg
2341
+					$error_msg .= '||' . sprintf(
2342
+							esc_html__(
2343
+								'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2344
+								'event_espresso'
2345
+							),
2346
+							$metabox_callback
2347
+						);
2348
+					throw new EE_Error($error_msg);
2349
+				}
2350
+			}
2351
+		}
2352
+	}
2353
+
2354
+
2355
+
2356
+	/**
2357
+	 * _add_screen_columns
2358
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2359
+	 * the dynamic column template and we'll setup the column options for the page.
2360
+	 *
2361
+	 * @return void
2362
+	 */
2363
+	private function _add_screen_columns()
2364
+	{
2365
+		if (
2366
+			is_array($this->_route_config)
2367
+			&& isset($this->_route_config['columns'])
2368
+			&& is_array($this->_route_config['columns'])
2369
+			&& count($this->_route_config['columns']) === 2
2370
+		) {
2371
+			add_screen_option(
2372
+				'layout_columns',
2373
+				array(
2374
+					'max'     => (int)$this->_route_config['columns'][0],
2375
+					'default' => (int)$this->_route_config['columns'][1],
2376
+				)
2377
+			);
2378
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2379
+			$screen_id                                           = $this->_current_screen->id;
2380
+			$screen_columns                                      = (int)get_user_option("screen_layout_{$screen_id}");
2381
+			$total_columns                                       = ! empty($screen_columns)
2382
+				? $screen_columns
2383
+				: $this->_route_config['columns'][1];
2384
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2385
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2386
+			$this->_template_args['screen']                      = $this->_current_screen;
2387
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2388
+																   . 'admin_details_metabox_column_wrapper.template.php';
2389
+			// finally if we don't have has_metaboxes set in the route config
2390
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2391
+			$this->_route_config['has_metaboxes'] = true;
2392
+		}
2393
+	}
2394
+
2395
+
2396
+
2397
+	/** GLOBALLY AVAILABLE METABOXES **/
2398
+
2399
+
2400
+	/**
2401
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2402
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2403
+	 * these get loaded on.
2404
+	 */
2405
+	private function _espresso_news_post_box()
2406
+	{
2407
+		$news_box_title = apply_filters(
2408
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2409
+			esc_html__('New @ Event Espresso', 'event_espresso')
2410
+		);
2411
+		add_meta_box(
2412
+			'espresso_news_post_box',
2413
+			$news_box_title,
2414
+			array(
2415
+				$this,
2416
+				'espresso_news_post_box',
2417
+			),
2418
+			$this->_wp_page_slug,
2419
+			'side'
2420
+		);
2421
+	}
2422
+
2423
+
2424
+
2425
+	/**
2426
+	 * Code for setting up espresso ratings request metabox.
2427
+	 */
2428
+	protected function _espresso_ratings_request()
2429
+	{
2430
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2431
+			return;
2432
+		}
2433
+		$ratings_box_title = apply_filters(
2434
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2435
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2436
+		);
2437
+		add_meta_box(
2438
+			'espresso_ratings_request',
2439
+			$ratings_box_title,
2440
+			array(
2441
+				$this,
2442
+				'espresso_ratings_request',
2443
+			),
2444
+			$this->_wp_page_slug,
2445
+			'side'
2446
+		);
2447
+	}
2448
+
2449
+
2450
+
2451
+	/**
2452
+	 * Code for setting up espresso ratings request metabox content.
2453
+	 *
2454
+	 * @throws DomainException
2455
+	 */
2456
+	public function espresso_ratings_request()
2457
+	{
2458
+		EEH_Template::display_template(
2459
+			EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2460
+				array()
2461
+		);
2462
+	}
2463
+
2464
+
2465
+
2466
+	public static function cached_rss_display($rss_id, $url)
2467
+	{
2468
+		$loading    = '<p class="widget-loading hide-if-no-js">'
2469
+					  . __('Loading&#8230;')
2470
+					  . '</p><p class="hide-if-js">'
2471
+					  . esc_html__('This widget requires JavaScript.')
2472
+					  . '</p>';
2473
+		$pre        = '<div class="espresso-rss-display">' . "\n\t";
2474
+		$pre        .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2475
+		$post       = '</div>' . "\n";
2476
+		$cache_key  = 'ee_rss_' . md5($rss_id);
2477
+		$output = get_transient($cache_key);
2478
+		if ($output !== false) {
2479
+			echo $pre . $output . $post;
2480
+			return true;
2481
+		}
2482
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2483
+			echo $pre . $loading . $post;
2484
+			return false;
2485
+		}
2486
+		ob_start();
2487
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2488
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2489
+		return true;
2490
+	}
2491
+
2492
+
2493
+
2494
+	public function espresso_news_post_box()
2495
+	{
2496
+		?>
2497 2497
         <div class="padding">
2498 2498
             <div id="espresso_news_post_box_content" class="infolinks">
2499 2499
                 <?php
2500
-                // Get RSS Feed(s)
2501
-                self::cached_rss_display(
2502
-                    'espresso_news_post_box_content',
2503
-                    urlencode(
2504
-                        apply_filters(
2505
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2506
-                            'http://eventespresso.com/feed/'
2507
-                        )
2508
-                    )
2509
-                );
2510
-                ?>
2500
+				// Get RSS Feed(s)
2501
+				self::cached_rss_display(
2502
+					'espresso_news_post_box_content',
2503
+					urlencode(
2504
+						apply_filters(
2505
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2506
+							'http://eventespresso.com/feed/'
2507
+						)
2508
+					)
2509
+				);
2510
+				?>
2511 2511
             </div>
2512 2512
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2513 2513
         </div>
2514 2514
         <?php
2515
-    }
2516
-
2517
-
2518
-
2519
-    private function _espresso_links_post_box()
2520
-    {
2521
-        //Hiding until we actually have content to put in here...
2522
-        //add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2523
-    }
2524
-
2525
-
2526
-
2527
-    public function espresso_links_post_box()
2528
-    {
2529
-        //Hiding until we actually have content to put in here...
2530
-        // EEH_Template::display_template(
2531
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2532
-        // );
2533
-    }
2534
-
2535
-
2536
-
2537
-    protected function _espresso_sponsors_post_box()
2538
-    {
2539
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
-            add_meta_box(
2541
-                'espresso_sponsors_post_box',
2542
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
-                array($this, 'espresso_sponsors_post_box'),
2544
-                $this->_wp_page_slug,
2545
-                'side'
2546
-            );
2547
-        }
2548
-    }
2549
-
2550
-
2551
-
2552
-    public function espresso_sponsors_post_box()
2553
-    {
2554
-        EEH_Template::display_template(
2555
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2556
-        );
2557
-    }
2558
-
2559
-
2560
-
2561
-    private function _publish_post_box()
2562
-    {
2563
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2564
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2565
-        // then we'll use that for the metabox label.
2566
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2567
-        if (! empty($this->_labels['publishbox'])) {
2568
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2569
-                : $this->_labels['publishbox'];
2570
-        } else {
2571
-            $box_label = esc_html__('Publish', 'event_espresso');
2572
-        }
2573
-        $box_label = apply_filters(
2574
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2575
-            $box_label,
2576
-            $this->_req_action,
2577
-            $this
2578
-        );
2579
-        add_meta_box(
2580
-            $meta_box_ref,
2581
-            $box_label,
2582
-            array($this, 'editor_overview'),
2583
-            $this->_current_screen->id,
2584
-            'side',
2585
-            'high'
2586
-        );
2587
-    }
2588
-
2589
-
2590
-
2591
-    public function editor_overview()
2592
-    {
2593
-        //if we have extra content set let's add it in if not make sure its empty
2594
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2595
-            ? $this->_template_args['publish_box_extra_content']
2596
-            : '';
2597
-        echo EEH_Template::display_template(
2598
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2599
-            $this->_template_args,
2600
-            true
2601
-        );
2602
-    }
2603
-
2604
-
2605
-    /** end of globally available metaboxes section **/
2606
-
2607
-
2608
-
2609
-    /**
2610
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2611
-     * protected method.
2612
-     *
2613
-     * @see   $this->_set_publish_post_box_vars for param details
2614
-     * @since 4.6.0
2615
-     * @param string $name
2616
-     * @param int    $id
2617
-     * @param bool   $delete
2618
-     * @param string $save_close_redirect_URL
2619
-     * @param bool   $both_btns
2620
-     * @throws EE_Error
2621
-     * @throws InvalidArgumentException
2622
-     * @throws InvalidDataTypeException
2623
-     * @throws InvalidInterfaceException
2624
-     */
2625
-    public function set_publish_post_box_vars(
2626
-        $name = '',
2627
-        $id = 0,
2628
-        $delete = false,
2629
-        $save_close_redirect_URL = '',
2630
-        $both_btns = true
2631
-    ) {
2632
-        $this->_set_publish_post_box_vars(
2633
-            $name,
2634
-            $id,
2635
-            $delete,
2636
-            $save_close_redirect_URL,
2637
-            $both_btns
2638
-        );
2639
-    }
2640
-
2641
-
2642
-
2643
-    /**
2644
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2645
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2646
-     * save, and save and close buttons to work properly, then you will want to include a
2647
-     * values for the name and id arguments.
2648
-     *
2649
-     * @todo  Add in validation for name/id arguments.
2650
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2651
-     * @param    int     $id                      id attached to the item published
2652
-     * @param    string  $delete                  page route callback for the delete action
2653
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2654
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2655
-     *                                            the Save button
2656
-     * @throws EE_Error
2657
-     * @throws InvalidArgumentException
2658
-     * @throws InvalidDataTypeException
2659
-     * @throws InvalidInterfaceException
2660
-     */
2661
-    protected function _set_publish_post_box_vars(
2662
-        $name = '',
2663
-        $id = 0,
2664
-        $delete = '',
2665
-        $save_close_redirect_URL = '',
2666
-        $both_btns = true
2667
-    ) {
2668
-        // if Save & Close, use a custom redirect URL or default to the main page?
2669
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2670
-            ? $save_close_redirect_URL
2671
-            : $this->_admin_base_url;
2672
-        // create the Save & Close and Save buttons
2673
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2674
-        //if we have extra content set let's add it in if not make sure its empty
2675
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2676
-            ? $this->_template_args['publish_box_extra_content']
2677
-            : '';
2678
-        if ($delete && ! empty($id)) {
2679
-            //make sure we have a default if just true is sent.
2680
-            $delete           = ! empty($delete) ? $delete : 'delete';
2681
-            $delete_link_args = array($name => $id);
2682
-            $delete           = $this->get_action_link_or_button(
2683
-                $delete,
2684
-                $delete,
2685
-                $delete_link_args,
2686
-                'submitdelete deletion',
2687
-                '',
2688
-                false
2689
-            );
2690
-        }
2691
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2692
-        if (! empty($name) && ! empty($id)) {
2693
-            $hidden_field_arr[$name] = array(
2694
-                'type'  => 'hidden',
2695
-                'value' => $id,
2696
-            );
2697
-            $hf                      = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2698
-        } else {
2699
-            $hf = '';
2700
-        }
2701
-        // add hidden field
2702
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2703
-            ? $hf[$name]['field']
2704
-            : $hf;
2705
-    }
2706
-
2707
-
2708
-
2709
-    /**
2710
-     * displays an error message to ppl who have javascript disabled
2711
-     *
2712
-     * @return void
2713
-     */
2714
-    private function _display_no_javascript_warning()
2715
-    {
2716
-        ?>
2515
+	}
2516
+
2517
+
2518
+
2519
+	private function _espresso_links_post_box()
2520
+	{
2521
+		//Hiding until we actually have content to put in here...
2522
+		//add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2523
+	}
2524
+
2525
+
2526
+
2527
+	public function espresso_links_post_box()
2528
+	{
2529
+		//Hiding until we actually have content to put in here...
2530
+		// EEH_Template::display_template(
2531
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2532
+		// );
2533
+	}
2534
+
2535
+
2536
+
2537
+	protected function _espresso_sponsors_post_box()
2538
+	{
2539
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
+			add_meta_box(
2541
+				'espresso_sponsors_post_box',
2542
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
+				array($this, 'espresso_sponsors_post_box'),
2544
+				$this->_wp_page_slug,
2545
+				'side'
2546
+			);
2547
+		}
2548
+	}
2549
+
2550
+
2551
+
2552
+	public function espresso_sponsors_post_box()
2553
+	{
2554
+		EEH_Template::display_template(
2555
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2556
+		);
2557
+	}
2558
+
2559
+
2560
+
2561
+	private function _publish_post_box()
2562
+	{
2563
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2564
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2565
+		// then we'll use that for the metabox label.
2566
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2567
+		if (! empty($this->_labels['publishbox'])) {
2568
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2569
+				: $this->_labels['publishbox'];
2570
+		} else {
2571
+			$box_label = esc_html__('Publish', 'event_espresso');
2572
+		}
2573
+		$box_label = apply_filters(
2574
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2575
+			$box_label,
2576
+			$this->_req_action,
2577
+			$this
2578
+		);
2579
+		add_meta_box(
2580
+			$meta_box_ref,
2581
+			$box_label,
2582
+			array($this, 'editor_overview'),
2583
+			$this->_current_screen->id,
2584
+			'side',
2585
+			'high'
2586
+		);
2587
+	}
2588
+
2589
+
2590
+
2591
+	public function editor_overview()
2592
+	{
2593
+		//if we have extra content set let's add it in if not make sure its empty
2594
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2595
+			? $this->_template_args['publish_box_extra_content']
2596
+			: '';
2597
+		echo EEH_Template::display_template(
2598
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2599
+			$this->_template_args,
2600
+			true
2601
+		);
2602
+	}
2603
+
2604
+
2605
+	/** end of globally available metaboxes section **/
2606
+
2607
+
2608
+
2609
+	/**
2610
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2611
+	 * protected method.
2612
+	 *
2613
+	 * @see   $this->_set_publish_post_box_vars for param details
2614
+	 * @since 4.6.0
2615
+	 * @param string $name
2616
+	 * @param int    $id
2617
+	 * @param bool   $delete
2618
+	 * @param string $save_close_redirect_URL
2619
+	 * @param bool   $both_btns
2620
+	 * @throws EE_Error
2621
+	 * @throws InvalidArgumentException
2622
+	 * @throws InvalidDataTypeException
2623
+	 * @throws InvalidInterfaceException
2624
+	 */
2625
+	public function set_publish_post_box_vars(
2626
+		$name = '',
2627
+		$id = 0,
2628
+		$delete = false,
2629
+		$save_close_redirect_URL = '',
2630
+		$both_btns = true
2631
+	) {
2632
+		$this->_set_publish_post_box_vars(
2633
+			$name,
2634
+			$id,
2635
+			$delete,
2636
+			$save_close_redirect_URL,
2637
+			$both_btns
2638
+		);
2639
+	}
2640
+
2641
+
2642
+
2643
+	/**
2644
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2645
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2646
+	 * save, and save and close buttons to work properly, then you will want to include a
2647
+	 * values for the name and id arguments.
2648
+	 *
2649
+	 * @todo  Add in validation for name/id arguments.
2650
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2651
+	 * @param    int     $id                      id attached to the item published
2652
+	 * @param    string  $delete                  page route callback for the delete action
2653
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2654
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2655
+	 *                                            the Save button
2656
+	 * @throws EE_Error
2657
+	 * @throws InvalidArgumentException
2658
+	 * @throws InvalidDataTypeException
2659
+	 * @throws InvalidInterfaceException
2660
+	 */
2661
+	protected function _set_publish_post_box_vars(
2662
+		$name = '',
2663
+		$id = 0,
2664
+		$delete = '',
2665
+		$save_close_redirect_URL = '',
2666
+		$both_btns = true
2667
+	) {
2668
+		// if Save & Close, use a custom redirect URL or default to the main page?
2669
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2670
+			? $save_close_redirect_URL
2671
+			: $this->_admin_base_url;
2672
+		// create the Save & Close and Save buttons
2673
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2674
+		//if we have extra content set let's add it in if not make sure its empty
2675
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2676
+			? $this->_template_args['publish_box_extra_content']
2677
+			: '';
2678
+		if ($delete && ! empty($id)) {
2679
+			//make sure we have a default if just true is sent.
2680
+			$delete           = ! empty($delete) ? $delete : 'delete';
2681
+			$delete_link_args = array($name => $id);
2682
+			$delete           = $this->get_action_link_or_button(
2683
+				$delete,
2684
+				$delete,
2685
+				$delete_link_args,
2686
+				'submitdelete deletion',
2687
+				'',
2688
+				false
2689
+			);
2690
+		}
2691
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2692
+		if (! empty($name) && ! empty($id)) {
2693
+			$hidden_field_arr[$name] = array(
2694
+				'type'  => 'hidden',
2695
+				'value' => $id,
2696
+			);
2697
+			$hf                      = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2698
+		} else {
2699
+			$hf = '';
2700
+		}
2701
+		// add hidden field
2702
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2703
+			? $hf[$name]['field']
2704
+			: $hf;
2705
+	}
2706
+
2707
+
2708
+
2709
+	/**
2710
+	 * displays an error message to ppl who have javascript disabled
2711
+	 *
2712
+	 * @return void
2713
+	 */
2714
+	private function _display_no_javascript_warning()
2715
+	{
2716
+		?>
2717 2717
         <noscript>
2718 2718
             <div id="no-js-message" class="error">
2719 2719
                 <p style="font-size:1.3em;">
2720 2720
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2721 2721
                     <?php esc_html_e(
2722
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2723
-                        'event_espresso'
2724
-                    ); ?>
2722
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2723
+						'event_espresso'
2724
+					); ?>
2725 2725
                 </p>
2726 2726
             </div>
2727 2727
         </noscript>
2728 2728
         <?php
2729
-    }
2729
+	}
2730 2730
 
2731 2731
 
2732 2732
 
2733
-    /**
2734
-     * displays espresso success and/or error notices
2735
-     *
2736
-     * @return void
2737
-     */
2738
-    private function _display_espresso_notices()
2739
-    {
2740
-        $notices = $this->_get_transient(true);
2741
-        echo stripslashes($notices);
2742
-    }
2733
+	/**
2734
+	 * displays espresso success and/or error notices
2735
+	 *
2736
+	 * @return void
2737
+	 */
2738
+	private function _display_espresso_notices()
2739
+	{
2740
+		$notices = $this->_get_transient(true);
2741
+		echo stripslashes($notices);
2742
+	}
2743 2743
 
2744 2744
 
2745 2745
 
2746
-    /**
2747
-     * spinny things pacify the masses
2748
-     *
2749
-     * @return void
2750
-     */
2751
-    protected function _add_admin_page_ajax_loading_img()
2752
-    {
2753
-        ?>
2746
+	/**
2747
+	 * spinny things pacify the masses
2748
+	 *
2749
+	 * @return void
2750
+	 */
2751
+	protected function _add_admin_page_ajax_loading_img()
2752
+	{
2753
+		?>
2754 2754
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2755 2755
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php esc_html_e(
2756
-                    'loading...',
2757
-                    'event_espresso'
2758
-                ); ?></span>
2756
+					'loading...',
2757
+					'event_espresso'
2758
+				); ?></span>
2759 2759
         </div>
2760 2760
         <?php
2761
-    }
2761
+	}
2762 2762
 
2763 2763
 
2764 2764
 
2765
-    /**
2766
-     * add admin page overlay for modal boxes
2767
-     *
2768
-     * @return void
2769
-     */
2770
-    protected function _add_admin_page_overlay()
2771
-    {
2772
-        ?>
2765
+	/**
2766
+	 * add admin page overlay for modal boxes
2767
+	 *
2768
+	 * @return void
2769
+	 */
2770
+	protected function _add_admin_page_overlay()
2771
+	{
2772
+		?>
2773 2773
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2774 2774
         <?php
2775
-    }
2776
-
2777
-
2778
-
2779
-    /**
2780
-     * facade for add_meta_box
2781
-     *
2782
-     * @param string  $action        where the metabox get's displayed
2783
-     * @param string  $title         Title of Metabox (output in metabox header)
2784
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2785
-     *                               instead of the one created in here.
2786
-     * @param array   $callback_args an array of args supplied for the metabox
2787
-     * @param string  $column        what metabox column
2788
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2789
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2790
-     *                               created but just set our own callback for wp's add_meta_box.
2791
-     * @throws \DomainException
2792
-     */
2793
-    public function _add_admin_page_meta_box(
2794
-        $action,
2795
-        $title,
2796
-        $callback,
2797
-        $callback_args,
2798
-        $column = 'normal',
2799
-        $priority = 'high',
2800
-        $create_func = true
2801
-    ) {
2802
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2803
-        //if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2804
-        if (empty($callback_args) && $create_func) {
2805
-            $callback_args = array(
2806
-                'template_path' => $this->_template_path,
2807
-                'template_args' => $this->_template_args,
2808
-            );
2809
-        }
2810
-        //if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2811
-        $call_back_func = $create_func
2812
-            ? function ($post, $metabox)
2813
-            {
2814
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2815
-                echo EEH_Template::display_template(
2816
-                    $metabox['args']['template_path'],
2817
-                    $metabox['args']['template_args'],
2818
-                    true
2819
-                );
2820
-            }
2821
-            : $callback;
2822
-        add_meta_box(
2823
-            str_replace('_', '-', $action) . '-mbox',
2824
-            $title,
2825
-            $call_back_func,
2826
-            $this->_wp_page_slug,
2827
-            $column,
2828
-            $priority,
2829
-            $callback_args
2830
-        );
2831
-    }
2832
-
2833
-
2834
-
2835
-    /**
2836
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2837
-     *
2838
-     * @throws DomainException
2839
-     * @throws EE_Error
2840
-     */
2841
-    public function display_admin_page_with_metabox_columns()
2842
-    {
2843
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2844
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2845
-            $this->_column_template_path,
2846
-            $this->_template_args,
2847
-            true
2848
-        );
2849
-        //the final wrapper
2850
-        $this->admin_page_wrapper();
2851
-    }
2852
-
2853
-
2854
-
2855
-    /**
2856
-     * generates  HTML wrapper for an admin details page
2857
-     *
2858
-     * @return void
2859
-     * @throws EE_Error
2860
-     * @throws DomainException
2861
-     */
2862
-    public function display_admin_page_with_sidebar()
2863
-    {
2864
-        $this->_display_admin_page(true);
2865
-    }
2866
-
2867
-
2868
-
2869
-    /**
2870
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2871
-     *
2872
-     * @return void
2873
-     * @throws EE_Error
2874
-     * @throws DomainException
2875
-     */
2876
-    public function display_admin_page_with_no_sidebar()
2877
-    {
2878
-        $this->_display_admin_page();
2879
-    }
2880
-
2881
-
2882
-
2883
-    /**
2884
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2885
-     *
2886
-     * @return void
2887
-     * @throws EE_Error
2888
-     * @throws DomainException
2889
-     */
2890
-    public function display_about_admin_page()
2891
-    {
2892
-        $this->_display_admin_page(false, true);
2893
-    }
2894
-
2895
-
2896
-
2897
-    /**
2898
-     * display_admin_page
2899
-     * contains the code for actually displaying an admin page
2900
-     *
2901
-     * @param  boolean $sidebar true with sidebar, false without
2902
-     * @param  boolean $about   use the about admin wrapper instead of the default.
2903
-     * @return void
2904
-     * @throws DomainException
2905
-     * @throws EE_Error
2906
-     */
2907
-    private function _display_admin_page($sidebar = false, $about = false)
2908
-    {
2909
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2910
-        //custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2911
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2912
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2913
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2914
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2915
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2916
-            ? 'poststuff'
2917
-            : 'espresso-default-admin';
2918
-        $template_path                                     = $sidebar
2919
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2920
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2921
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2922
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2923
-        }
2924
-        $template_path                                     = ! empty($this->_column_template_path)
2925
-            ? $this->_column_template_path : $template_path;
2926
-        $this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2927
-            ? $this->_template_args['admin_page_content']
2928
-            : '';
2929
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2930
-            ? $this->_template_args['before_admin_page_content']
2931
-            : '';
2932
-        $this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2933
-            ? $this->_template_args['after_admin_page_content']
2934
-            : '';
2935
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2936
-            $template_path,
2937
-            $this->_template_args,
2938
-            true
2939
-        );
2940
-        // the final template wrapper
2941
-        $this->admin_page_wrapper($about);
2942
-    }
2943
-
2944
-
2945
-
2946
-    /**
2947
-     * This is used to display caf preview pages.
2948
-     *
2949
-     * @since 4.3.2
2950
-     * @param string $utm_campaign_source what is the key used for google analytics link
2951
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2952
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2953
-     * @return void
2954
-     * @throws DomainException
2955
-     * @throws EE_Error
2956
-     * @throws InvalidArgumentException
2957
-     * @throws InvalidDataTypeException
2958
-     * @throws InvalidInterfaceException
2959
-     */
2960
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2961
-    {
2962
-        //let's generate a default preview action button if there isn't one already present.
2963
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2964
-            'Upgrade to Event Espresso 4 Right Now',
2965
-            'event_espresso'
2966
-        );
2967
-        $buy_now_url                                   = add_query_arg(
2968
-            array(
2969
-                'ee_ver'       => 'ee4',
2970
-                'utm_source'   => 'ee4_plugin_admin',
2971
-                'utm_medium'   => 'link',
2972
-                'utm_campaign' => $utm_campaign_source,
2973
-                'utm_content'  => 'buy_now_button',
2974
-            ),
2975
-            'http://eventespresso.com/pricing/'
2976
-        );
2977
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2978
-            ? $this->get_action_link_or_button(
2979
-                '',
2980
-                'buy_now',
2981
-                array(),
2982
-                'button-primary button-large',
2983
-                $buy_now_url,
2984
-                true
2985
-            )
2986
-            : $this->_template_args['preview_action_button'];
2987
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2988
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2989
-            $this->_template_args,
2990
-            true
2991
-        );
2992
-        $this->_display_admin_page($display_sidebar);
2993
-    }
2994
-
2995
-
2996
-
2997
-    /**
2998
-     * display_admin_list_table_page_with_sidebar
2999
-     * generates HTML wrapper for an admin_page with list_table
3000
-     *
3001
-     * @return void
3002
-     * @throws EE_Error
3003
-     * @throws DomainException
3004
-     */
3005
-    public function display_admin_list_table_page_with_sidebar()
3006
-    {
3007
-        $this->_display_admin_list_table_page(true);
3008
-    }
3009
-
3010
-
3011
-
3012
-    /**
3013
-     * display_admin_list_table_page_with_no_sidebar
3014
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3015
-     *
3016
-     * @return void
3017
-     * @throws EE_Error
3018
-     * @throws DomainException
3019
-     */
3020
-    public function display_admin_list_table_page_with_no_sidebar()
3021
-    {
3022
-        $this->_display_admin_list_table_page();
3023
-    }
3024
-
3025
-
3026
-
3027
-    /**
3028
-     * generates html wrapper for an admin_list_table page
3029
-     *
3030
-     * @param boolean $sidebar whether to display with sidebar or not.
3031
-     * @return void
3032
-     * @throws DomainException
3033
-     * @throws EE_Error
3034
-     */
3035
-    private function _display_admin_list_table_page($sidebar = false)
3036
-    {
3037
-        //setup search attributes
3038
-        $this->_set_search_attributes();
3039
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
3040
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3041
-        $this->_template_args['table_url']        = defined('DOING_AJAX')
3042
-            ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
3043
-            : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
3044
-        $this->_template_args['list_table']       = $this->_list_table_object;
3045
-        $this->_template_args['current_route']    = $this->_req_action;
3046
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3047
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3048
-        if (! empty($ajax_sorting_callback)) {
3049
-            $sortable_list_table_form_fields = wp_nonce_field(
3050
-                $ajax_sorting_callback . '_nonce',
3051
-                $ajax_sorting_callback . '_nonce',
3052
-                false,
3053
-                false
3054
-            );
3055
-            //			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
3056
-            //			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
3057
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3058
-                                                . $this->page_slug
3059
-                                                . '" />';
3060
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3061
-                                                . $ajax_sorting_callback
3062
-                                                . '" />';
3063
-        } else {
3064
-            $sortable_list_table_form_fields = '';
3065
-        }
3066
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3067
-        $hidden_form_fields                                      = isset($this->_template_args['list_table_hidden_fields'])
3068
-            ? $this->_template_args['list_table_hidden_fields']
3069
-            : '';
3070
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3071
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3072
-                                                                    . $nonce_ref
3073
-                                                                    . '" value="'
3074
-                                                                    . wp_create_nonce($nonce_ref)
3075
-                                                                    . '">';
3076
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3077
-        //display message about search results?
3078
-        $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
3079
-            ? '<p class="ee-search-results">' . sprintf(
3080
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3081
-                trim($this->_req_data['s'], '%')
3082
-            ) . '</p>'
3083
-            : '';
3084
-        // filter before_list_table template arg
3085
-        $this->_template_args['before_list_table'] = apply_filters(
3086
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3087
-            $this->_template_args['before_list_table'],
3088
-            $this->page_slug,
3089
-            $this->_req_data,
3090
-            $this->_req_action
3091
-        );
3092
-        // convert to array and filter again
3093
-        // arrays are easier to inject new items in a specific location,
3094
-        // but would not be backwards compatible, so we have to add a new filter
3095
-        $this->_template_args['before_list_table'] = implode(
3096
-            " \n",
3097
-            (array)apply_filters(
3098
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3099
-                (array)$this->_template_args['before_list_table'],
3100
-                $this->page_slug,
3101
-                $this->_req_data,
3102
-                $this->_req_action
3103
-            )
3104
-        );
3105
-        // filter after_list_table template arg
3106
-        $this->_template_args['after_list_table'] = apply_filters(
3107
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3108
-            $this->_template_args['after_list_table'],
3109
-            $this->page_slug,
3110
-            $this->_req_data,
3111
-            $this->_req_action
3112
-        );
3113
-        // convert to array and filter again
3114
-        // arrays are easier to inject new items in a specific location,
3115
-        // but would not be backwards compatible, so we have to add a new filter
3116
-        $this->_template_args['after_list_table']   = implode(
3117
-            " \n",
3118
-            (array)apply_filters(
3119
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3120
-                (array)$this->_template_args['after_list_table'],
3121
-                $this->page_slug,
3122
-                $this->_req_data,
3123
-                $this->_req_action
3124
-            )
3125
-        );
3126
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3127
-            $template_path,
3128
-            $this->_template_args,
3129
-            true
3130
-        );
3131
-        // the final template wrapper
3132
-        if ($sidebar) {
3133
-            $this->display_admin_page_with_sidebar();
3134
-        } else {
3135
-            $this->display_admin_page_with_no_sidebar();
3136
-        }
3137
-    }
3138
-
3139
-
3140
-
3141
-    /**
3142
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3143
-     * html string for the legend.
3144
-     * $items are expected in an array in the following format:
3145
-     * $legend_items = array(
3146
-     *        'item_id' => array(
3147
-     *            'icon' => 'http://url_to_icon_being_described.png',
3148
-     *            'desc' => esc_html__('localized description of item');
3149
-     *        )
3150
-     * );
3151
-     *
3152
-     * @param  array $items see above for format of array
3153
-     * @return string html string of legend
3154
-     * @throws DomainException
3155
-     */
3156
-    protected function _display_legend($items)
3157
-    {
3158
-        $this->_template_args['items'] = apply_filters(
3159
-            'FHEE__EE_Admin_Page___display_legend__items',
3160
-            (array)$items,
3161
-            $this
3162
-        );
3163
-        return EEH_Template::display_template(
3164
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3165
-            $this->_template_args,
3166
-            true
3167
-        );
3168
-    }
3169
-
3170
-
3171
-    /**
3172
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3173
-     * The returned json object is created from an array in the following format:
3174
-     * array(
3175
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3176
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3177
-     *  'notices' => '', // - contains any EE_Error formatted notices
3178
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3179
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3180
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3181
-     *  that might be included in here)
3182
-     * )
3183
-     * The json object is populated by whatever is set in the $_template_args property.
3184
-     *
3185
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3186
-     *                                 instead of displayed.
3187
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3188
-     * @return void
3189
-     * @throws EE_Error
3190
-     */
3191
-    protected function _return_json($sticky_notices = false, $notices_arguments = array())
3192
-    {
3193
-        //make sure any EE_Error notices have been handled.
3194
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3195
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3196
-        unset($this->_template_args['data']);
3197
-        $json = array(
3198
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3199
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3200
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3201
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3202
-            'notices'   => EE_Error::get_notices(),
3203
-            'content'   => isset($this->_template_args['admin_page_content'])
3204
-                ? $this->_template_args['admin_page_content'] : '',
3205
-            'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3206
-            'isEEajax'  => true
3207
-            //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3208
-        );
3209
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3210
-        if (null === error_get_last() || ! headers_sent()) {
3211
-            header('Content-Type: application/json; charset=UTF-8');
3212
-        }
3213
-        echo wp_json_encode($json);
3214
-        exit();
3215
-    }
3216
-
3217
-
3218
-
3219
-    /**
3220
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3221
-     *
3222
-     * @return void
3223
-     * @throws EE_Error
3224
-     */
3225
-    public function return_json()
3226
-    {
3227
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3228
-            $this->_return_json();
3229
-        } else {
3230
-            throw new EE_Error(
3231
-                sprintf(
3232
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3233
-                    __FUNCTION__
3234
-                )
3235
-            );
3236
-        }
3237
-    }
3238
-
3239
-
3240
-
3241
-    /**
3242
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3243
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3244
-     *
3245
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3246
-     */
3247
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3248
-    {
3249
-        $this->_hook_obj = $hook_obj;
3250
-    }
3251
-
3252
-
3253
-
3254
-    /**
3255
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3256
-     *
3257
-     * @param  boolean $about whether to use the special about page wrapper or default.
3258
-     * @return void
3259
-     * @throws DomainException
3260
-     * @throws EE_Error
3261
-     */
3262
-    public function admin_page_wrapper($about = false)
3263
-    {
3264
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3265
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3266
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3267
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3268
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3269
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3270
-            isset($this->_template_args['before_admin_page_content'])
3271
-                ? $this->_template_args['before_admin_page_content']
3272
-                : ''
3273
-        );
3274
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3275
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3276
-            isset($this->_template_args['after_admin_page_content'])
3277
-                ? $this->_template_args['after_admin_page_content']
3278
-                : ''
3279
-        );
3280
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3281
-        // load settings page wrapper template
3282
-        $template_path = ! defined('DOING_AJAX')
3283
-            ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3284
-            : EE_ADMIN_TEMPLATE
3285
-              . 'admin_wrapper_ajax.template.php';
3286
-        //about page?
3287
-        $template_path = $about
3288
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3289
-            : $template_path;
3290
-        if (defined('DOING_AJAX')) {
3291
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3292
-                $template_path,
3293
-                $this->_template_args,
3294
-                true
3295
-            );
3296
-            $this->_return_json();
3297
-        } else {
3298
-            EEH_Template::display_template($template_path, $this->_template_args);
3299
-        }
3300
-    }
3301
-
3302
-
3303
-
3304
-    /**
3305
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3306
-     *
3307
-     * @return string html
3308
-     * @throws EE_Error
3309
-     */
3310
-    protected function _get_main_nav_tabs()
3311
-    {
3312
-        // let's generate the html using the EEH_Tabbed_Content helper.
3313
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3314
-        // (rather than setting in the page_routes array)
3315
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3316
-    }
3317
-
3318
-
3319
-
3320
-    /**
3321
-     *        sort nav tabs
3322
-     *
3323
-     * @param $a
3324
-     * @param $b
3325
-     * @return int
3326
-     */
3327
-    private function _sort_nav_tabs($a, $b)
3328
-    {
3329
-        if ($a['order'] === $b['order']) {
3330
-            return 0;
3331
-        }
3332
-        return ($a['order'] < $b['order']) ? -1 : 1;
3333
-    }
3334
-
3335
-
3336
-
3337
-    /**
3338
-     *    generates HTML for the forms used on admin pages
3339
-     *
3340
-     * @param    array $input_vars - array of input field details
3341
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3342
-     *                             use)
3343
-     * @param bool     $id
3344
-     * @return string
3345
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3346
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3347
-     */
3348
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3349
-    {
3350
-        $content = $generator === 'string'
3351
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3352
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3353
-        return $content;
3354
-    }
3355
-
3356
-
3357
-
3358
-    /**
3359
-     * generates the "Save" and "Save & Close" buttons for edit forms
3360
-     *
3361
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
-     *                                   Close" button.
3363
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
-     *                                   'Save', [1] => 'save & close')
3365
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
-     *                                   via the "name" value in the button).  We can also use this to just dump
3367
-     *                                   default actions by submitting some other value.
3368
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
-     *                                   close (normal form handling).
3371
-     */
3372
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3373
-    {
3374
-        //make sure $text and $actions are in an array
3375
-        $text          = (array)$text;
3376
-        $actions       = (array)$actions;
3377
-        $referrer_url  = empty($referrer)
3378
-            ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3379
-              . $_SERVER['REQUEST_URI']
3380
-              . '" />'
3381
-            : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3382
-              . $referrer
3383
-              . '" />';
3384
-        $button_text   = ! empty($text)
3385
-            ? $text
3386
-            : array(
3387
-                esc_html__('Save', 'event_espresso'),
3388
-                esc_html__('Save and Close', 'event_espresso'),
3389
-            );
3390
-        $default_names = array('save', 'save_and_close');
3391
-        //add in a hidden index for the current page (so save and close redirects properly)
3392
-        $this->_template_args['save_buttons'] = $referrer_url;
3393
-        foreach ($button_text as $key => $button) {
3394
-            $ref                                  = $default_names[$key];
3395
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3396
-                                                     . $ref
3397
-                                                     . '" value="'
3398
-                                                     . $button
3399
-                                                     . '" name="'
3400
-                                                     . (! empty($actions) ? $actions[$key] : $ref)
3401
-                                                     . '" id="'
3402
-                                                     . $this->_current_view . '_' . $ref
3403
-                                                     . '" />';
3404
-            if (! $both) {
3405
-                break;
3406
-            }
3407
-        }
3408
-    }
3409
-
3410
-
3411
-
3412
-    /**
3413
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3414
-     *
3415
-     * @see   $this->_set_add_edit_form_tags() for details on params
3416
-     * @since 4.6.0
3417
-     * @param string $route
3418
-     * @param array  $additional_hidden_fields
3419
-     */
3420
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3421
-    {
3422
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3423
-    }
3424
-
3425
-
3426
-
3427
-    /**
3428
-     * set form open and close tags on add/edit pages.
3429
-     *
3430
-     * @param string $route                    the route you want the form to direct to
3431
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3432
-     * @return void
3433
-     */
3434
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3435
-    {
3436
-        if (empty($route)) {
3437
-            $user_msg = esc_html__(
3438
-                'An error occurred. No action was set for this page\'s form.',
3439
-                'event_espresso'
3440
-            );
3441
-            $dev_msg  = $user_msg . "\n" . sprintf(
3442
-                    esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3443
-                    __FUNCTION__,
3444
-                    __CLASS__
3445
-                );
3446
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3447
-        }
3448
-        // open form
3449
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3450
-                                                             . $this->_admin_base_url
3451
-                                                             . '" id="'
3452
-                                                             . $route
3453
-                                                             . '_event_form" >';
3454
-        // add nonce
3455
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3456
-        //		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
3457
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3458
-        // add REQUIRED form action
3459
-        $hidden_fields = array(
3460
-            'action' => array('type' => 'hidden', 'value' => $route),
3461
-        );
3462
-        // merge arrays
3463
-        $hidden_fields = is_array($additional_hidden_fields)
3464
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3465
-            : $hidden_fields;
3466
-        // generate form fields
3467
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3468
-        // add fields to form
3469
-        foreach ((array)$form_fields as $field_name => $form_field) {
3470
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3471
-        }
3472
-        // close form
3473
-        $this->_template_args['after_admin_page_content'] = '</form>';
3474
-    }
3475
-
3476
-
3477
-
3478
-    /**
3479
-     * Public Wrapper for _redirect_after_action() method since its
3480
-     * discovered it would be useful for external code to have access.
3481
-     *
3482
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3483
-     * @since 4.5.0
3484
-     * @param bool   $success
3485
-     * @param string $what
3486
-     * @param string $action_desc
3487
-     * @param array  $query_args
3488
-     * @param bool   $override_overwrite
3489
-     * @throws EE_Error
3490
-     */
3491
-    public function redirect_after_action(
3492
-        $success = false,
3493
-        $what = 'item',
3494
-        $action_desc = 'processed',
3495
-        $query_args = array(),
3496
-        $override_overwrite = false
3497
-    ) {
3498
-        $this->_redirect_after_action(
3499
-            $success,
3500
-            $what,
3501
-            $action_desc,
3502
-            $query_args,
3503
-            $override_overwrite
3504
-        );
3505
-    }
3506
-
3507
-
3508
-
3509
-    /**
3510
-     *    _redirect_after_action
3511
-     *
3512
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3513
-     * @param string $what               - what the action was performed on
3514
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3515
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3516
-     *                                   action is completed
3517
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3518
-     *                                   override this so that they show.
3519
-     * @return void
3520
-     * @throws EE_Error
3521
-     */
3522
-    protected function _redirect_after_action(
3523
-        $success = 0,
3524
-        $what = 'item',
3525
-        $action_desc = 'processed',
3526
-        $query_args = array(),
3527
-        $override_overwrite = false
3528
-    ) {
3529
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3530
-        //class name for actions/filters.
3531
-        $classname = get_class($this);
3532
-        // set redirect url.
3533
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3534
-        // otherwise we go with whatever is set as the _admin_base_url
3535
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3536
-        $notices      = EE_Error::get_notices(false);
3537
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3538
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3539
-            EE_Error::overwrite_success();
3540
-        }
3541
-        if (! empty($what) && ! empty($action_desc)  && empty($notices['errors'])) {
3542
-            // how many records affected ? more than one record ? or just one ?
3543
-            if ($success > 1) {
3544
-                // set plural msg
3545
-                EE_Error::add_success(
3546
-                    sprintf(
3547
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3548
-                        $what,
3549
-                        $action_desc
3550
-                    ),
3551
-                    __FILE__,
3552
-                    __FUNCTION__,
3553
-                    __LINE__
3554
-                );
3555
-            } elseif ($success === 1) {
3556
-                // set singular msg
3557
-                EE_Error::add_success(
3558
-                    sprintf(
3559
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3560
-                        $what,
3561
-                        $action_desc
3562
-                    ),
3563
-                    __FILE__,
3564
-                    __FUNCTION__,
3565
-                    __LINE__
3566
-                );
3567
-            }
3568
-        }
3569
-        // check that $query_args isn't something crazy
3570
-        if (! is_array($query_args)) {
3571
-            $query_args = array();
3572
-        }
3573
-        /**
3574
-         * Allow injecting actions before the query_args are modified for possible different
3575
-         * redirections on save and close actions
3576
-         *
3577
-         * @since 4.2.0
3578
-         * @param array $query_args       The original query_args array coming into the
3579
-         *                                method.
3580
-         */
3581
-        do_action(
3582
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3583
-            $query_args
3584
-        );
3585
-        //calculate where we're going (if we have a "save and close" button pushed)
3586
-        if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3587
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3588
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3589
-            // regenerate query args array from referrer URL
3590
-            parse_str($parsed_url['query'], $query_args);
3591
-            // correct page and action will be in the query args now
3592
-            $redirect_url = admin_url('admin.php');
3593
-        }
3594
-        //merge any default query_args set in _default_route_query_args property
3595
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3596
-            $args_to_merge = array();
3597
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3598
-                //is there a wp_referer array in our _default_route_query_args property?
3599
-                if ($query_param === 'wp_referer') {
3600
-                    $query_value = (array)$query_value;
3601
-                    foreach ($query_value as $reference => $value) {
3602
-                        if (strpos($reference, 'nonce') !== false) {
3603
-                            continue;
3604
-                        }
3605
-                        //finally we will override any arguments in the referer with
3606
-                        //what might be set on the _default_route_query_args array.
3607
-                        if (isset($this->_default_route_query_args[$reference])) {
3608
-                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3609
-                        } else {
3610
-                            $args_to_merge[$reference] = urlencode($value);
3611
-                        }
3612
-                    }
3613
-                    continue;
3614
-                }
3615
-                $args_to_merge[$query_param] = $query_value;
3616
-            }
3617
-            //now let's merge these arguments but override with what was specifically sent in to the
3618
-            //redirect.
3619
-            $query_args = array_merge($args_to_merge, $query_args);
3620
-        }
3621
-        $this->_process_notices($query_args);
3622
-        // generate redirect url
3623
-        // if redirecting to anything other than the main page, add a nonce
3624
-        if (isset($query_args['action'])) {
3625
-            // manually generate wp_nonce and merge that with the query vars
3626
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3627
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3628
-        }
3629
-        // we're adding some hooks and filters in here for processing any things just before redirects
3630
-        // (example: an admin page has done an insert or update and we want to run something after that).
3631
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3632
-        $redirect_url = apply_filters(
3633
-            'FHEE_redirect_' . $classname . $this->_req_action,
3634
-            self::add_query_args_and_nonce($query_args, $redirect_url),
3635
-            $query_args
3636
-        );
3637
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3638
-        if (defined('DOING_AJAX')) {
3639
-            $default_data                    = array(
3640
-                'close'        => true,
3641
-                'redirect_url' => $redirect_url,
3642
-                'where'        => 'main',
3643
-                'what'         => 'append',
3644
-            );
3645
-            $this->_template_args['success'] = $success;
3646
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3647
-                $default_data,
3648
-                $this->_template_args['data']
3649
-            ) : $default_data;
3650
-            $this->_return_json();
3651
-        }
3652
-        wp_safe_redirect($redirect_url);
3653
-        exit();
3654
-    }
3655
-
3656
-
3657
-
3658
-    /**
3659
-     * process any notices before redirecting (or returning ajax request)
3660
-     * This method sets the $this->_template_args['notices'] attribute;
3661
-     *
3662
-     * @param  array $query_args        any query args that need to be used for notice transient ('action')
3663
-     * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3664
-     *                                  page_routes haven't been defined yet.
3665
-     * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3666
-     *                                  still save a transient for the notice.
3667
-     * @return void
3668
-     * @throws EE_Error
3669
-     */
3670
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3671
-    {
3672
-        //first let's set individual error properties if doing_ajax and the properties aren't already set.
3673
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3674
-            $notices = EE_Error::get_notices(false);
3675
-            if (empty($this->_template_args['success'])) {
3676
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3677
-            }
3678
-            if (empty($this->_template_args['errors'])) {
3679
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3680
-            }
3681
-            if (empty($this->_template_args['attention'])) {
3682
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3683
-            }
3684
-        }
3685
-        $this->_template_args['notices'] = EE_Error::get_notices();
3686
-        //IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3687
-        if (! defined('DOING_AJAX') || $sticky_notices) {
3688
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3689
-            $this->_add_transient(
3690
-                $route,
3691
-                $this->_template_args['notices'],
3692
-                true,
3693
-                $skip_route_verify
3694
-            );
3695
-        }
3696
-    }
3697
-
3698
-
3699
-
3700
-    /**
3701
-     * get_action_link_or_button
3702
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3703
-     *
3704
-     * @param string $action        use this to indicate which action the url is generated with.
3705
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3706
-     *                              property.
3707
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3708
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3709
-     * @param string $base_url      If this is not provided
3710
-     *                              the _admin_base_url will be used as the default for the button base_url.
3711
-     *                              Otherwise this value will be used.
3712
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3713
-     * @return string
3714
-     * @throws InvalidArgumentException
3715
-     * @throws InvalidInterfaceException
3716
-     * @throws InvalidDataTypeException
3717
-     * @throws EE_Error
3718
-     */
3719
-    public function get_action_link_or_button(
3720
-        $action,
3721
-        $type = 'add',
3722
-        $extra_request = array(),
3723
-        $class = 'button-primary',
3724
-        $base_url = '',
3725
-        $exclude_nonce = false
3726
-    ) {
3727
-        //first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3728
-        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3729
-            throw new EE_Error(
3730
-                sprintf(
3731
-                    esc_html__(
3732
-                        'There is no page route for given action for the button.  This action was given: %s',
3733
-                        'event_espresso'
3734
-                    ),
3735
-                    $action
3736
-                )
3737
-            );
3738
-        }
3739
-        if (! isset($this->_labels['buttons'][$type])) {
3740
-            throw new EE_Error(
3741
-                sprintf(
3742
-                    __(
3743
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3744
-                        'event_espresso'
3745
-                    ),
3746
-                    $type
3747
-                )
3748
-            );
3749
-        }
3750
-        //finally check user access for this button.
3751
-        $has_access = $this->check_user_access($action, true);
3752
-        if (! $has_access) {
3753
-            return '';
3754
-        }
3755
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3756
-        $query_args = array(
3757
-            'action' => $action,
3758
-        );
3759
-        //merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3760
-        if (! empty($extra_request)) {
3761
-            $query_args = array_merge($extra_request, $query_args);
3762
-        }
3763
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3764
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3765
-    }
3766
-
3767
-
3768
-
3769
-    /**
3770
-     * _per_page_screen_option
3771
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3772
-     *
3773
-     * @return void
3774
-     * @throws InvalidArgumentException
3775
-     * @throws InvalidInterfaceException
3776
-     * @throws InvalidDataTypeException
3777
-     */
3778
-    protected function _per_page_screen_option()
3779
-    {
3780
-        $option = 'per_page';
3781
-        $args   = array(
3782
-            'label'   => esc_html__(
3783
-                    apply_filters(
3784
-                        'FHEE__EE_Admin_Page___per_page_screen_options___label',
3785
-                        $this->_admin_page_title,
3786
-                        $this
3787
-                    )
3788
-            ),
3789
-            'default' => (int) apply_filters(
3790
-                    'FHEE__EE_Admin_Page___per_page_screen_options__default',
3791
-                    10
3792
-            ),
3793
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3794
-        );
3795
-        //ONLY add the screen option if the user has access to it.
3796
-        if ($this->check_user_access($this->_current_view, true)) {
3797
-            add_screen_option($option, $args);
3798
-        }
3799
-    }
3800
-
3801
-
3802
-
3803
-    /**
3804
-     * set_per_page_screen_option
3805
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3806
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3807
-     * admin_menu.
3808
-     *
3809
-     * @return void
3810
-     */
3811
-    private function _set_per_page_screen_options()
3812
-    {
3813
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3814
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3815
-            if (! $user = wp_get_current_user()) {
3816
-                return;
3817
-            }
3818
-            $option = $_POST['wp_screen_options']['option'];
3819
-            $value  = $_POST['wp_screen_options']['value'];
3820
-            if ($option != sanitize_key($option)) {
3821
-                return;
3822
-            }
3823
-            $map_option = $option;
3824
-            $option     = str_replace('-', '_', $option);
3825
-            switch ($map_option) {
3826
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3827
-                    $value = (int)$value;
3828
-                    $max_value = apply_filters(
3829
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3830
-                        999,
3831
-                        $this->_current_page,
3832
-                        $this->_current_view
3833
-                    );
3834
-                    if ($value < 1) {
3835
-                        return;
3836
-                    }
3837
-                    $value = min($value, $max_value);
3838
-                    break;
3839
-                default:
3840
-                    $value = apply_filters(
3841
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3842
-                        false,
3843
-                        $option,
3844
-                        $value
3845
-                    );
3846
-                    if (false === $value) {
3847
-                        return;
3848
-                    }
3849
-                    break;
3850
-            }
3851
-            update_user_meta($user->ID, $option, $value);
3852
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3853
-            exit;
3854
-        }
3855
-    }
3856
-
3857
-
3858
-
3859
-    /**
3860
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3861
-     *
3862
-     * @param array $data array that will be assigned to template args.
3863
-     */
3864
-    public function set_template_args($data)
3865
-    {
3866
-        $this->_template_args = array_merge($this->_template_args, (array)$data);
3867
-    }
3868
-
3869
-
3870
-
3871
-    /**
3872
-     * This makes available the WP transient system for temporarily moving data between routes
3873
-     *
3874
-     * @param string $route             the route that should receive the transient
3875
-     * @param array  $data              the data that gets sent
3876
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3877
-     *                                  normal route transient.
3878
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3879
-     *                                  when we are adding a transient before page_routes have been defined.
3880
-     * @return void
3881
-     * @throws EE_Error
3882
-     */
3883
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3884
-    {
3885
-        $user_id = get_current_user_id();
3886
-        if (! $skip_route_verify) {
3887
-            $this->_verify_route($route);
3888
-        }
3889
-        //now let's set the string for what kind of transient we're setting
3890
-        $transient = $notices
3891
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3892
-            : 'rte_tx_' . $route . '_' . $user_id;
3893
-        $data      = $notices ? array('notices' => $data) : $data;
3894
-        //is there already a transient for this route?  If there is then let's ADD to that transient
3895
-        $existing = is_multisite() && is_network_admin()
3896
-            ? get_site_transient($transient)
3897
-            : get_transient($transient);
3898
-        if ($existing) {
3899
-            $data = array_merge((array)$data, (array)$existing);
3900
-        }
3901
-        if (is_multisite() && is_network_admin()) {
3902
-            set_site_transient($transient, $data, 8);
3903
-        } else {
3904
-            set_transient($transient, $data, 8);
3905
-        }
3906
-    }
3907
-
3908
-
3909
-
3910
-    /**
3911
-     * this retrieves the temporary transient that has been set for moving data between routes.
3912
-     *
3913
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3914
-     * @param string $route
3915
-     * @return mixed data
3916
-     */
3917
-    protected function _get_transient($notices = false, $route = '')
3918
-    {
3919
-        $user_id   = get_current_user_id();
3920
-        $route     = ! $route ? $this->_req_action : $route;
3921
-        $transient = $notices
3922
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3923
-            : 'rte_tx_' . $route . '_' . $user_id;
3924
-        $data      = is_multisite() && is_network_admin()
3925
-            ? get_site_transient($transient)
3926
-            : get_transient($transient);
3927
-        //delete transient after retrieval (just in case it hasn't expired);
3928
-        if (is_multisite() && is_network_admin()) {
3929
-            delete_site_transient($transient);
3930
-        } else {
3931
-            delete_transient($transient);
3932
-        }
3933
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3934
-    }
3935
-
3936
-
3937
-
3938
-    /**
3939
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3940
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3941
-     * default route callback on the EE_Admin page you want it run.)
3942
-     *
3943
-     * @return void
3944
-     */
3945
-    protected function _transient_garbage_collection()
3946
-    {
3947
-        global $wpdb;
3948
-        //retrieve all existing transients
3949
-        $query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3950
-        if ($results = $wpdb->get_results($query)) {
3951
-            foreach ($results as $result) {
3952
-                $transient = str_replace('_transient_', '', $result->option_name);
3953
-                get_transient($transient);
3954
-                if (is_multisite() && is_network_admin()) {
3955
-                    get_site_transient($transient);
3956
-                }
3957
-            }
3958
-        }
3959
-    }
3960
-
3961
-
3962
-
3963
-    /**
3964
-     * get_view
3965
-     *
3966
-     * @return string content of _view property
3967
-     */
3968
-    public function get_view()
3969
-    {
3970
-        return $this->_view;
3971
-    }
3972
-
3973
-
3974
-
3975
-    /**
3976
-     * getter for the protected $_views property
3977
-     *
3978
-     * @return array
3979
-     */
3980
-    public function get_views()
3981
-    {
3982
-        return $this->_views;
3983
-    }
3984
-
3985
-
3986
-
3987
-    /**
3988
-     * get_current_page
3989
-     *
3990
-     * @return string _current_page property value
3991
-     */
3992
-    public function get_current_page()
3993
-    {
3994
-        return $this->_current_page;
3995
-    }
3996
-
3997
-
3998
-
3999
-    /**
4000
-     * get_current_view
4001
-     *
4002
-     * @return string _current_view property value
4003
-     */
4004
-    public function get_current_view()
4005
-    {
4006
-        return $this->_current_view;
4007
-    }
4008
-
4009
-
4010
-
4011
-    /**
4012
-     * get_current_screen
4013
-     *
4014
-     * @return object The current WP_Screen object
4015
-     */
4016
-    public function get_current_screen()
4017
-    {
4018
-        return $this->_current_screen;
4019
-    }
4020
-
4021
-
4022
-
4023
-    /**
4024
-     * get_current_page_view_url
4025
-     *
4026
-     * @return string This returns the url for the current_page_view.
4027
-     */
4028
-    public function get_current_page_view_url()
4029
-    {
4030
-        return $this->_current_page_view_url;
4031
-    }
4032
-
4033
-
4034
-
4035
-    /**
4036
-     * just returns the _req_data property
4037
-     *
4038
-     * @return array
4039
-     */
4040
-    public function get_request_data()
4041
-    {
4042
-        return $this->_req_data;
4043
-    }
4044
-
4045
-
4046
-
4047
-    /**
4048
-     * returns the _req_data protected property
4049
-     *
4050
-     * @return string
4051
-     */
4052
-    public function get_req_action()
4053
-    {
4054
-        return $this->_req_action;
4055
-    }
4056
-
4057
-
4058
-
4059
-    /**
4060
-     * @return bool  value of $_is_caf property
4061
-     */
4062
-    public function is_caf()
4063
-    {
4064
-        return $this->_is_caf;
4065
-    }
4066
-
4067
-
4068
-
4069
-    /**
4070
-     * @return mixed
4071
-     */
4072
-    public function default_espresso_metaboxes()
4073
-    {
4074
-        return $this->_default_espresso_metaboxes;
4075
-    }
4076
-
4077
-
4078
-
4079
-    /**
4080
-     * @return mixed
4081
-     */
4082
-    public function admin_base_url()
4083
-    {
4084
-        return $this->_admin_base_url;
4085
-    }
2775
+	}
2776
+
2777
+
2778
+
2779
+	/**
2780
+	 * facade for add_meta_box
2781
+	 *
2782
+	 * @param string  $action        where the metabox get's displayed
2783
+	 * @param string  $title         Title of Metabox (output in metabox header)
2784
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2785
+	 *                               instead of the one created in here.
2786
+	 * @param array   $callback_args an array of args supplied for the metabox
2787
+	 * @param string  $column        what metabox column
2788
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2789
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2790
+	 *                               created but just set our own callback for wp's add_meta_box.
2791
+	 * @throws \DomainException
2792
+	 */
2793
+	public function _add_admin_page_meta_box(
2794
+		$action,
2795
+		$title,
2796
+		$callback,
2797
+		$callback_args,
2798
+		$column = 'normal',
2799
+		$priority = 'high',
2800
+		$create_func = true
2801
+	) {
2802
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2803
+		//if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2804
+		if (empty($callback_args) && $create_func) {
2805
+			$callback_args = array(
2806
+				'template_path' => $this->_template_path,
2807
+				'template_args' => $this->_template_args,
2808
+			);
2809
+		}
2810
+		//if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2811
+		$call_back_func = $create_func
2812
+			? function ($post, $metabox)
2813
+			{
2814
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2815
+				echo EEH_Template::display_template(
2816
+					$metabox['args']['template_path'],
2817
+					$metabox['args']['template_args'],
2818
+					true
2819
+				);
2820
+			}
2821
+			: $callback;
2822
+		add_meta_box(
2823
+			str_replace('_', '-', $action) . '-mbox',
2824
+			$title,
2825
+			$call_back_func,
2826
+			$this->_wp_page_slug,
2827
+			$column,
2828
+			$priority,
2829
+			$callback_args
2830
+		);
2831
+	}
2832
+
2833
+
2834
+
2835
+	/**
2836
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2837
+	 *
2838
+	 * @throws DomainException
2839
+	 * @throws EE_Error
2840
+	 */
2841
+	public function display_admin_page_with_metabox_columns()
2842
+	{
2843
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2844
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2845
+			$this->_column_template_path,
2846
+			$this->_template_args,
2847
+			true
2848
+		);
2849
+		//the final wrapper
2850
+		$this->admin_page_wrapper();
2851
+	}
2852
+
2853
+
2854
+
2855
+	/**
2856
+	 * generates  HTML wrapper for an admin details page
2857
+	 *
2858
+	 * @return void
2859
+	 * @throws EE_Error
2860
+	 * @throws DomainException
2861
+	 */
2862
+	public function display_admin_page_with_sidebar()
2863
+	{
2864
+		$this->_display_admin_page(true);
2865
+	}
2866
+
2867
+
2868
+
2869
+	/**
2870
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2871
+	 *
2872
+	 * @return void
2873
+	 * @throws EE_Error
2874
+	 * @throws DomainException
2875
+	 */
2876
+	public function display_admin_page_with_no_sidebar()
2877
+	{
2878
+		$this->_display_admin_page();
2879
+	}
2880
+
2881
+
2882
+
2883
+	/**
2884
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2885
+	 *
2886
+	 * @return void
2887
+	 * @throws EE_Error
2888
+	 * @throws DomainException
2889
+	 */
2890
+	public function display_about_admin_page()
2891
+	{
2892
+		$this->_display_admin_page(false, true);
2893
+	}
2894
+
2895
+
2896
+
2897
+	/**
2898
+	 * display_admin_page
2899
+	 * contains the code for actually displaying an admin page
2900
+	 *
2901
+	 * @param  boolean $sidebar true with sidebar, false without
2902
+	 * @param  boolean $about   use the about admin wrapper instead of the default.
2903
+	 * @return void
2904
+	 * @throws DomainException
2905
+	 * @throws EE_Error
2906
+	 */
2907
+	private function _display_admin_page($sidebar = false, $about = false)
2908
+	{
2909
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2910
+		//custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2911
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2912
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2913
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2914
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2915
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2916
+			? 'poststuff'
2917
+			: 'espresso-default-admin';
2918
+		$template_path                                     = $sidebar
2919
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2920
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2921
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2922
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2923
+		}
2924
+		$template_path                                     = ! empty($this->_column_template_path)
2925
+			? $this->_column_template_path : $template_path;
2926
+		$this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2927
+			? $this->_template_args['admin_page_content']
2928
+			: '';
2929
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2930
+			? $this->_template_args['before_admin_page_content']
2931
+			: '';
2932
+		$this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2933
+			? $this->_template_args['after_admin_page_content']
2934
+			: '';
2935
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2936
+			$template_path,
2937
+			$this->_template_args,
2938
+			true
2939
+		);
2940
+		// the final template wrapper
2941
+		$this->admin_page_wrapper($about);
2942
+	}
2943
+
2944
+
2945
+
2946
+	/**
2947
+	 * This is used to display caf preview pages.
2948
+	 *
2949
+	 * @since 4.3.2
2950
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2951
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2952
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2953
+	 * @return void
2954
+	 * @throws DomainException
2955
+	 * @throws EE_Error
2956
+	 * @throws InvalidArgumentException
2957
+	 * @throws InvalidDataTypeException
2958
+	 * @throws InvalidInterfaceException
2959
+	 */
2960
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2961
+	{
2962
+		//let's generate a default preview action button if there isn't one already present.
2963
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2964
+			'Upgrade to Event Espresso 4 Right Now',
2965
+			'event_espresso'
2966
+		);
2967
+		$buy_now_url                                   = add_query_arg(
2968
+			array(
2969
+				'ee_ver'       => 'ee4',
2970
+				'utm_source'   => 'ee4_plugin_admin',
2971
+				'utm_medium'   => 'link',
2972
+				'utm_campaign' => $utm_campaign_source,
2973
+				'utm_content'  => 'buy_now_button',
2974
+			),
2975
+			'http://eventespresso.com/pricing/'
2976
+		);
2977
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2978
+			? $this->get_action_link_or_button(
2979
+				'',
2980
+				'buy_now',
2981
+				array(),
2982
+				'button-primary button-large',
2983
+				$buy_now_url,
2984
+				true
2985
+			)
2986
+			: $this->_template_args['preview_action_button'];
2987
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2988
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2989
+			$this->_template_args,
2990
+			true
2991
+		);
2992
+		$this->_display_admin_page($display_sidebar);
2993
+	}
2994
+
2995
+
2996
+
2997
+	/**
2998
+	 * display_admin_list_table_page_with_sidebar
2999
+	 * generates HTML wrapper for an admin_page with list_table
3000
+	 *
3001
+	 * @return void
3002
+	 * @throws EE_Error
3003
+	 * @throws DomainException
3004
+	 */
3005
+	public function display_admin_list_table_page_with_sidebar()
3006
+	{
3007
+		$this->_display_admin_list_table_page(true);
3008
+	}
3009
+
3010
+
3011
+
3012
+	/**
3013
+	 * display_admin_list_table_page_with_no_sidebar
3014
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3015
+	 *
3016
+	 * @return void
3017
+	 * @throws EE_Error
3018
+	 * @throws DomainException
3019
+	 */
3020
+	public function display_admin_list_table_page_with_no_sidebar()
3021
+	{
3022
+		$this->_display_admin_list_table_page();
3023
+	}
3024
+
3025
+
3026
+
3027
+	/**
3028
+	 * generates html wrapper for an admin_list_table page
3029
+	 *
3030
+	 * @param boolean $sidebar whether to display with sidebar or not.
3031
+	 * @return void
3032
+	 * @throws DomainException
3033
+	 * @throws EE_Error
3034
+	 */
3035
+	private function _display_admin_list_table_page($sidebar = false)
3036
+	{
3037
+		//setup search attributes
3038
+		$this->_set_search_attributes();
3039
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
3040
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3041
+		$this->_template_args['table_url']        = defined('DOING_AJAX')
3042
+			? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
3043
+			: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
3044
+		$this->_template_args['list_table']       = $this->_list_table_object;
3045
+		$this->_template_args['current_route']    = $this->_req_action;
3046
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3047
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3048
+		if (! empty($ajax_sorting_callback)) {
3049
+			$sortable_list_table_form_fields = wp_nonce_field(
3050
+				$ajax_sorting_callback . '_nonce',
3051
+				$ajax_sorting_callback . '_nonce',
3052
+				false,
3053
+				false
3054
+			);
3055
+			//			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
3056
+			//			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
3057
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3058
+												. $this->page_slug
3059
+												. '" />';
3060
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3061
+												. $ajax_sorting_callback
3062
+												. '" />';
3063
+		} else {
3064
+			$sortable_list_table_form_fields = '';
3065
+		}
3066
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3067
+		$hidden_form_fields                                      = isset($this->_template_args['list_table_hidden_fields'])
3068
+			? $this->_template_args['list_table_hidden_fields']
3069
+			: '';
3070
+		$nonce_ref                                               = $this->_req_action . '_nonce';
3071
+		$hidden_form_fields                                      .= '<input type="hidden" name="'
3072
+																	. $nonce_ref
3073
+																	. '" value="'
3074
+																	. wp_create_nonce($nonce_ref)
3075
+																	. '">';
3076
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3077
+		//display message about search results?
3078
+		$this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
3079
+			? '<p class="ee-search-results">' . sprintf(
3080
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3081
+				trim($this->_req_data['s'], '%')
3082
+			) . '</p>'
3083
+			: '';
3084
+		// filter before_list_table template arg
3085
+		$this->_template_args['before_list_table'] = apply_filters(
3086
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3087
+			$this->_template_args['before_list_table'],
3088
+			$this->page_slug,
3089
+			$this->_req_data,
3090
+			$this->_req_action
3091
+		);
3092
+		// convert to array and filter again
3093
+		// arrays are easier to inject new items in a specific location,
3094
+		// but would not be backwards compatible, so we have to add a new filter
3095
+		$this->_template_args['before_list_table'] = implode(
3096
+			" \n",
3097
+			(array)apply_filters(
3098
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3099
+				(array)$this->_template_args['before_list_table'],
3100
+				$this->page_slug,
3101
+				$this->_req_data,
3102
+				$this->_req_action
3103
+			)
3104
+		);
3105
+		// filter after_list_table template arg
3106
+		$this->_template_args['after_list_table'] = apply_filters(
3107
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3108
+			$this->_template_args['after_list_table'],
3109
+			$this->page_slug,
3110
+			$this->_req_data,
3111
+			$this->_req_action
3112
+		);
3113
+		// convert to array and filter again
3114
+		// arrays are easier to inject new items in a specific location,
3115
+		// but would not be backwards compatible, so we have to add a new filter
3116
+		$this->_template_args['after_list_table']   = implode(
3117
+			" \n",
3118
+			(array)apply_filters(
3119
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3120
+				(array)$this->_template_args['after_list_table'],
3121
+				$this->page_slug,
3122
+				$this->_req_data,
3123
+				$this->_req_action
3124
+			)
3125
+		);
3126
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3127
+			$template_path,
3128
+			$this->_template_args,
3129
+			true
3130
+		);
3131
+		// the final template wrapper
3132
+		if ($sidebar) {
3133
+			$this->display_admin_page_with_sidebar();
3134
+		} else {
3135
+			$this->display_admin_page_with_no_sidebar();
3136
+		}
3137
+	}
3138
+
3139
+
3140
+
3141
+	/**
3142
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3143
+	 * html string for the legend.
3144
+	 * $items are expected in an array in the following format:
3145
+	 * $legend_items = array(
3146
+	 *        'item_id' => array(
3147
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3148
+	 *            'desc' => esc_html__('localized description of item');
3149
+	 *        )
3150
+	 * );
3151
+	 *
3152
+	 * @param  array $items see above for format of array
3153
+	 * @return string html string of legend
3154
+	 * @throws DomainException
3155
+	 */
3156
+	protected function _display_legend($items)
3157
+	{
3158
+		$this->_template_args['items'] = apply_filters(
3159
+			'FHEE__EE_Admin_Page___display_legend__items',
3160
+			(array)$items,
3161
+			$this
3162
+		);
3163
+		return EEH_Template::display_template(
3164
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3165
+			$this->_template_args,
3166
+			true
3167
+		);
3168
+	}
3169
+
3170
+
3171
+	/**
3172
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3173
+	 * The returned json object is created from an array in the following format:
3174
+	 * array(
3175
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3176
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3177
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3178
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3179
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3180
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3181
+	 *  that might be included in here)
3182
+	 * )
3183
+	 * The json object is populated by whatever is set in the $_template_args property.
3184
+	 *
3185
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3186
+	 *                                 instead of displayed.
3187
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3188
+	 * @return void
3189
+	 * @throws EE_Error
3190
+	 */
3191
+	protected function _return_json($sticky_notices = false, $notices_arguments = array())
3192
+	{
3193
+		//make sure any EE_Error notices have been handled.
3194
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3195
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3196
+		unset($this->_template_args['data']);
3197
+		$json = array(
3198
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3199
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3200
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3201
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3202
+			'notices'   => EE_Error::get_notices(),
3203
+			'content'   => isset($this->_template_args['admin_page_content'])
3204
+				? $this->_template_args['admin_page_content'] : '',
3205
+			'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3206
+			'isEEajax'  => true
3207
+			//special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3208
+		);
3209
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3210
+		if (null === error_get_last() || ! headers_sent()) {
3211
+			header('Content-Type: application/json; charset=UTF-8');
3212
+		}
3213
+		echo wp_json_encode($json);
3214
+		exit();
3215
+	}
3216
+
3217
+
3218
+
3219
+	/**
3220
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3221
+	 *
3222
+	 * @return void
3223
+	 * @throws EE_Error
3224
+	 */
3225
+	public function return_json()
3226
+	{
3227
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3228
+			$this->_return_json();
3229
+		} else {
3230
+			throw new EE_Error(
3231
+				sprintf(
3232
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3233
+					__FUNCTION__
3234
+				)
3235
+			);
3236
+		}
3237
+	}
3238
+
3239
+
3240
+
3241
+	/**
3242
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3243
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3244
+	 *
3245
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3246
+	 */
3247
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3248
+	{
3249
+		$this->_hook_obj = $hook_obj;
3250
+	}
3251
+
3252
+
3253
+
3254
+	/**
3255
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3256
+	 *
3257
+	 * @param  boolean $about whether to use the special about page wrapper or default.
3258
+	 * @return void
3259
+	 * @throws DomainException
3260
+	 * @throws EE_Error
3261
+	 */
3262
+	public function admin_page_wrapper($about = false)
3263
+	{
3264
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3265
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3266
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3267
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3268
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3269
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3270
+			isset($this->_template_args['before_admin_page_content'])
3271
+				? $this->_template_args['before_admin_page_content']
3272
+				: ''
3273
+		);
3274
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3275
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3276
+			isset($this->_template_args['after_admin_page_content'])
3277
+				? $this->_template_args['after_admin_page_content']
3278
+				: ''
3279
+		);
3280
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3281
+		// load settings page wrapper template
3282
+		$template_path = ! defined('DOING_AJAX')
3283
+			? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3284
+			: EE_ADMIN_TEMPLATE
3285
+			  . 'admin_wrapper_ajax.template.php';
3286
+		//about page?
3287
+		$template_path = $about
3288
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3289
+			: $template_path;
3290
+		if (defined('DOING_AJAX')) {
3291
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3292
+				$template_path,
3293
+				$this->_template_args,
3294
+				true
3295
+			);
3296
+			$this->_return_json();
3297
+		} else {
3298
+			EEH_Template::display_template($template_path, $this->_template_args);
3299
+		}
3300
+	}
3301
+
3302
+
3303
+
3304
+	/**
3305
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3306
+	 *
3307
+	 * @return string html
3308
+	 * @throws EE_Error
3309
+	 */
3310
+	protected function _get_main_nav_tabs()
3311
+	{
3312
+		// let's generate the html using the EEH_Tabbed_Content helper.
3313
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3314
+		// (rather than setting in the page_routes array)
3315
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3316
+	}
3317
+
3318
+
3319
+
3320
+	/**
3321
+	 *        sort nav tabs
3322
+	 *
3323
+	 * @param $a
3324
+	 * @param $b
3325
+	 * @return int
3326
+	 */
3327
+	private function _sort_nav_tabs($a, $b)
3328
+	{
3329
+		if ($a['order'] === $b['order']) {
3330
+			return 0;
3331
+		}
3332
+		return ($a['order'] < $b['order']) ? -1 : 1;
3333
+	}
3334
+
3335
+
3336
+
3337
+	/**
3338
+	 *    generates HTML for the forms used on admin pages
3339
+	 *
3340
+	 * @param    array $input_vars - array of input field details
3341
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3342
+	 *                             use)
3343
+	 * @param bool     $id
3344
+	 * @return string
3345
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3346
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3347
+	 */
3348
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3349
+	{
3350
+		$content = $generator === 'string'
3351
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3352
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3353
+		return $content;
3354
+	}
3355
+
3356
+
3357
+
3358
+	/**
3359
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3360
+	 *
3361
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
+	 *                                   Close" button.
3363
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
+	 *                                   'Save', [1] => 'save & close')
3365
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3367
+	 *                                   default actions by submitting some other value.
3368
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
+	 *                                   close (normal form handling).
3371
+	 */
3372
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3373
+	{
3374
+		//make sure $text and $actions are in an array
3375
+		$text          = (array)$text;
3376
+		$actions       = (array)$actions;
3377
+		$referrer_url  = empty($referrer)
3378
+			? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3379
+			  . $_SERVER['REQUEST_URI']
3380
+			  . '" />'
3381
+			: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3382
+			  . $referrer
3383
+			  . '" />';
3384
+		$button_text   = ! empty($text)
3385
+			? $text
3386
+			: array(
3387
+				esc_html__('Save', 'event_espresso'),
3388
+				esc_html__('Save and Close', 'event_espresso'),
3389
+			);
3390
+		$default_names = array('save', 'save_and_close');
3391
+		//add in a hidden index for the current page (so save and close redirects properly)
3392
+		$this->_template_args['save_buttons'] = $referrer_url;
3393
+		foreach ($button_text as $key => $button) {
3394
+			$ref                                  = $default_names[$key];
3395
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3396
+													 . $ref
3397
+													 . '" value="'
3398
+													 . $button
3399
+													 . '" name="'
3400
+													 . (! empty($actions) ? $actions[$key] : $ref)
3401
+													 . '" id="'
3402
+													 . $this->_current_view . '_' . $ref
3403
+													 . '" />';
3404
+			if (! $both) {
3405
+				break;
3406
+			}
3407
+		}
3408
+	}
3409
+
3410
+
3411
+
3412
+	/**
3413
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3414
+	 *
3415
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3416
+	 * @since 4.6.0
3417
+	 * @param string $route
3418
+	 * @param array  $additional_hidden_fields
3419
+	 */
3420
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3421
+	{
3422
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3423
+	}
3424
+
3425
+
3426
+
3427
+	/**
3428
+	 * set form open and close tags on add/edit pages.
3429
+	 *
3430
+	 * @param string $route                    the route you want the form to direct to
3431
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3432
+	 * @return void
3433
+	 */
3434
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3435
+	{
3436
+		if (empty($route)) {
3437
+			$user_msg = esc_html__(
3438
+				'An error occurred. No action was set for this page\'s form.',
3439
+				'event_espresso'
3440
+			);
3441
+			$dev_msg  = $user_msg . "\n" . sprintf(
3442
+					esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3443
+					__FUNCTION__,
3444
+					__CLASS__
3445
+				);
3446
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3447
+		}
3448
+		// open form
3449
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3450
+															 . $this->_admin_base_url
3451
+															 . '" id="'
3452
+															 . $route
3453
+															 . '_event_form" >';
3454
+		// add nonce
3455
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3456
+		//		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
3457
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3458
+		// add REQUIRED form action
3459
+		$hidden_fields = array(
3460
+			'action' => array('type' => 'hidden', 'value' => $route),
3461
+		);
3462
+		// merge arrays
3463
+		$hidden_fields = is_array($additional_hidden_fields)
3464
+			? array_merge($hidden_fields, $additional_hidden_fields)
3465
+			: $hidden_fields;
3466
+		// generate form fields
3467
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3468
+		// add fields to form
3469
+		foreach ((array)$form_fields as $field_name => $form_field) {
3470
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3471
+		}
3472
+		// close form
3473
+		$this->_template_args['after_admin_page_content'] = '</form>';
3474
+	}
3475
+
3476
+
3477
+
3478
+	/**
3479
+	 * Public Wrapper for _redirect_after_action() method since its
3480
+	 * discovered it would be useful for external code to have access.
3481
+	 *
3482
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3483
+	 * @since 4.5.0
3484
+	 * @param bool   $success
3485
+	 * @param string $what
3486
+	 * @param string $action_desc
3487
+	 * @param array  $query_args
3488
+	 * @param bool   $override_overwrite
3489
+	 * @throws EE_Error
3490
+	 */
3491
+	public function redirect_after_action(
3492
+		$success = false,
3493
+		$what = 'item',
3494
+		$action_desc = 'processed',
3495
+		$query_args = array(),
3496
+		$override_overwrite = false
3497
+	) {
3498
+		$this->_redirect_after_action(
3499
+			$success,
3500
+			$what,
3501
+			$action_desc,
3502
+			$query_args,
3503
+			$override_overwrite
3504
+		);
3505
+	}
3506
+
3507
+
3508
+
3509
+	/**
3510
+	 *    _redirect_after_action
3511
+	 *
3512
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3513
+	 * @param string $what               - what the action was performed on
3514
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3515
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3516
+	 *                                   action is completed
3517
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3518
+	 *                                   override this so that they show.
3519
+	 * @return void
3520
+	 * @throws EE_Error
3521
+	 */
3522
+	protected function _redirect_after_action(
3523
+		$success = 0,
3524
+		$what = 'item',
3525
+		$action_desc = 'processed',
3526
+		$query_args = array(),
3527
+		$override_overwrite = false
3528
+	) {
3529
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3530
+		//class name for actions/filters.
3531
+		$classname = get_class($this);
3532
+		// set redirect url.
3533
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3534
+		// otherwise we go with whatever is set as the _admin_base_url
3535
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3536
+		$notices      = EE_Error::get_notices(false);
3537
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3538
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3539
+			EE_Error::overwrite_success();
3540
+		}
3541
+		if (! empty($what) && ! empty($action_desc)  && empty($notices['errors'])) {
3542
+			// how many records affected ? more than one record ? or just one ?
3543
+			if ($success > 1) {
3544
+				// set plural msg
3545
+				EE_Error::add_success(
3546
+					sprintf(
3547
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3548
+						$what,
3549
+						$action_desc
3550
+					),
3551
+					__FILE__,
3552
+					__FUNCTION__,
3553
+					__LINE__
3554
+				);
3555
+			} elseif ($success === 1) {
3556
+				// set singular msg
3557
+				EE_Error::add_success(
3558
+					sprintf(
3559
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3560
+						$what,
3561
+						$action_desc
3562
+					),
3563
+					__FILE__,
3564
+					__FUNCTION__,
3565
+					__LINE__
3566
+				);
3567
+			}
3568
+		}
3569
+		// check that $query_args isn't something crazy
3570
+		if (! is_array($query_args)) {
3571
+			$query_args = array();
3572
+		}
3573
+		/**
3574
+		 * Allow injecting actions before the query_args are modified for possible different
3575
+		 * redirections on save and close actions
3576
+		 *
3577
+		 * @since 4.2.0
3578
+		 * @param array $query_args       The original query_args array coming into the
3579
+		 *                                method.
3580
+		 */
3581
+		do_action(
3582
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3583
+			$query_args
3584
+		);
3585
+		//calculate where we're going (if we have a "save and close" button pushed)
3586
+		if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3587
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3588
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3589
+			// regenerate query args array from referrer URL
3590
+			parse_str($parsed_url['query'], $query_args);
3591
+			// correct page and action will be in the query args now
3592
+			$redirect_url = admin_url('admin.php');
3593
+		}
3594
+		//merge any default query_args set in _default_route_query_args property
3595
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3596
+			$args_to_merge = array();
3597
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3598
+				//is there a wp_referer array in our _default_route_query_args property?
3599
+				if ($query_param === 'wp_referer') {
3600
+					$query_value = (array)$query_value;
3601
+					foreach ($query_value as $reference => $value) {
3602
+						if (strpos($reference, 'nonce') !== false) {
3603
+							continue;
3604
+						}
3605
+						//finally we will override any arguments in the referer with
3606
+						//what might be set on the _default_route_query_args array.
3607
+						if (isset($this->_default_route_query_args[$reference])) {
3608
+							$args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3609
+						} else {
3610
+							$args_to_merge[$reference] = urlencode($value);
3611
+						}
3612
+					}
3613
+					continue;
3614
+				}
3615
+				$args_to_merge[$query_param] = $query_value;
3616
+			}
3617
+			//now let's merge these arguments but override with what was specifically sent in to the
3618
+			//redirect.
3619
+			$query_args = array_merge($args_to_merge, $query_args);
3620
+		}
3621
+		$this->_process_notices($query_args);
3622
+		// generate redirect url
3623
+		// if redirecting to anything other than the main page, add a nonce
3624
+		if (isset($query_args['action'])) {
3625
+			// manually generate wp_nonce and merge that with the query vars
3626
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3627
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3628
+		}
3629
+		// we're adding some hooks and filters in here for processing any things just before redirects
3630
+		// (example: an admin page has done an insert or update and we want to run something after that).
3631
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3632
+		$redirect_url = apply_filters(
3633
+			'FHEE_redirect_' . $classname . $this->_req_action,
3634
+			self::add_query_args_and_nonce($query_args, $redirect_url),
3635
+			$query_args
3636
+		);
3637
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3638
+		if (defined('DOING_AJAX')) {
3639
+			$default_data                    = array(
3640
+				'close'        => true,
3641
+				'redirect_url' => $redirect_url,
3642
+				'where'        => 'main',
3643
+				'what'         => 'append',
3644
+			);
3645
+			$this->_template_args['success'] = $success;
3646
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3647
+				$default_data,
3648
+				$this->_template_args['data']
3649
+			) : $default_data;
3650
+			$this->_return_json();
3651
+		}
3652
+		wp_safe_redirect($redirect_url);
3653
+		exit();
3654
+	}
3655
+
3656
+
3657
+
3658
+	/**
3659
+	 * process any notices before redirecting (or returning ajax request)
3660
+	 * This method sets the $this->_template_args['notices'] attribute;
3661
+	 *
3662
+	 * @param  array $query_args        any query args that need to be used for notice transient ('action')
3663
+	 * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3664
+	 *                                  page_routes haven't been defined yet.
3665
+	 * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3666
+	 *                                  still save a transient for the notice.
3667
+	 * @return void
3668
+	 * @throws EE_Error
3669
+	 */
3670
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3671
+	{
3672
+		//first let's set individual error properties if doing_ajax and the properties aren't already set.
3673
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3674
+			$notices = EE_Error::get_notices(false);
3675
+			if (empty($this->_template_args['success'])) {
3676
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3677
+			}
3678
+			if (empty($this->_template_args['errors'])) {
3679
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3680
+			}
3681
+			if (empty($this->_template_args['attention'])) {
3682
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3683
+			}
3684
+		}
3685
+		$this->_template_args['notices'] = EE_Error::get_notices();
3686
+		//IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3687
+		if (! defined('DOING_AJAX') || $sticky_notices) {
3688
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3689
+			$this->_add_transient(
3690
+				$route,
3691
+				$this->_template_args['notices'],
3692
+				true,
3693
+				$skip_route_verify
3694
+			);
3695
+		}
3696
+	}
3697
+
3698
+
3699
+
3700
+	/**
3701
+	 * get_action_link_or_button
3702
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3703
+	 *
3704
+	 * @param string $action        use this to indicate which action the url is generated with.
3705
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3706
+	 *                              property.
3707
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3708
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3709
+	 * @param string $base_url      If this is not provided
3710
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3711
+	 *                              Otherwise this value will be used.
3712
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3713
+	 * @return string
3714
+	 * @throws InvalidArgumentException
3715
+	 * @throws InvalidInterfaceException
3716
+	 * @throws InvalidDataTypeException
3717
+	 * @throws EE_Error
3718
+	 */
3719
+	public function get_action_link_or_button(
3720
+		$action,
3721
+		$type = 'add',
3722
+		$extra_request = array(),
3723
+		$class = 'button-primary',
3724
+		$base_url = '',
3725
+		$exclude_nonce = false
3726
+	) {
3727
+		//first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3728
+		if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3729
+			throw new EE_Error(
3730
+				sprintf(
3731
+					esc_html__(
3732
+						'There is no page route for given action for the button.  This action was given: %s',
3733
+						'event_espresso'
3734
+					),
3735
+					$action
3736
+				)
3737
+			);
3738
+		}
3739
+		if (! isset($this->_labels['buttons'][$type])) {
3740
+			throw new EE_Error(
3741
+				sprintf(
3742
+					__(
3743
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3744
+						'event_espresso'
3745
+					),
3746
+					$type
3747
+				)
3748
+			);
3749
+		}
3750
+		//finally check user access for this button.
3751
+		$has_access = $this->check_user_access($action, true);
3752
+		if (! $has_access) {
3753
+			return '';
3754
+		}
3755
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3756
+		$query_args = array(
3757
+			'action' => $action,
3758
+		);
3759
+		//merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3760
+		if (! empty($extra_request)) {
3761
+			$query_args = array_merge($extra_request, $query_args);
3762
+		}
3763
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3764
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3765
+	}
3766
+
3767
+
3768
+
3769
+	/**
3770
+	 * _per_page_screen_option
3771
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3772
+	 *
3773
+	 * @return void
3774
+	 * @throws InvalidArgumentException
3775
+	 * @throws InvalidInterfaceException
3776
+	 * @throws InvalidDataTypeException
3777
+	 */
3778
+	protected function _per_page_screen_option()
3779
+	{
3780
+		$option = 'per_page';
3781
+		$args   = array(
3782
+			'label'   => esc_html__(
3783
+					apply_filters(
3784
+						'FHEE__EE_Admin_Page___per_page_screen_options___label',
3785
+						$this->_admin_page_title,
3786
+						$this
3787
+					)
3788
+			),
3789
+			'default' => (int) apply_filters(
3790
+					'FHEE__EE_Admin_Page___per_page_screen_options__default',
3791
+					10
3792
+			),
3793
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3794
+		);
3795
+		//ONLY add the screen option if the user has access to it.
3796
+		if ($this->check_user_access($this->_current_view, true)) {
3797
+			add_screen_option($option, $args);
3798
+		}
3799
+	}
3800
+
3801
+
3802
+
3803
+	/**
3804
+	 * set_per_page_screen_option
3805
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3806
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3807
+	 * admin_menu.
3808
+	 *
3809
+	 * @return void
3810
+	 */
3811
+	private function _set_per_page_screen_options()
3812
+	{
3813
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3814
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3815
+			if (! $user = wp_get_current_user()) {
3816
+				return;
3817
+			}
3818
+			$option = $_POST['wp_screen_options']['option'];
3819
+			$value  = $_POST['wp_screen_options']['value'];
3820
+			if ($option != sanitize_key($option)) {
3821
+				return;
3822
+			}
3823
+			$map_option = $option;
3824
+			$option     = str_replace('-', '_', $option);
3825
+			switch ($map_option) {
3826
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3827
+					$value = (int)$value;
3828
+					$max_value = apply_filters(
3829
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3830
+						999,
3831
+						$this->_current_page,
3832
+						$this->_current_view
3833
+					);
3834
+					if ($value < 1) {
3835
+						return;
3836
+					}
3837
+					$value = min($value, $max_value);
3838
+					break;
3839
+				default:
3840
+					$value = apply_filters(
3841
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3842
+						false,
3843
+						$option,
3844
+						$value
3845
+					);
3846
+					if (false === $value) {
3847
+						return;
3848
+					}
3849
+					break;
3850
+			}
3851
+			update_user_meta($user->ID, $option, $value);
3852
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3853
+			exit;
3854
+		}
3855
+	}
3856
+
3857
+
3858
+
3859
+	/**
3860
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3861
+	 *
3862
+	 * @param array $data array that will be assigned to template args.
3863
+	 */
3864
+	public function set_template_args($data)
3865
+	{
3866
+		$this->_template_args = array_merge($this->_template_args, (array)$data);
3867
+	}
3868
+
3869
+
3870
+
3871
+	/**
3872
+	 * This makes available the WP transient system for temporarily moving data between routes
3873
+	 *
3874
+	 * @param string $route             the route that should receive the transient
3875
+	 * @param array  $data              the data that gets sent
3876
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3877
+	 *                                  normal route transient.
3878
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3879
+	 *                                  when we are adding a transient before page_routes have been defined.
3880
+	 * @return void
3881
+	 * @throws EE_Error
3882
+	 */
3883
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3884
+	{
3885
+		$user_id = get_current_user_id();
3886
+		if (! $skip_route_verify) {
3887
+			$this->_verify_route($route);
3888
+		}
3889
+		//now let's set the string for what kind of transient we're setting
3890
+		$transient = $notices
3891
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3892
+			: 'rte_tx_' . $route . '_' . $user_id;
3893
+		$data      = $notices ? array('notices' => $data) : $data;
3894
+		//is there already a transient for this route?  If there is then let's ADD to that transient
3895
+		$existing = is_multisite() && is_network_admin()
3896
+			? get_site_transient($transient)
3897
+			: get_transient($transient);
3898
+		if ($existing) {
3899
+			$data = array_merge((array)$data, (array)$existing);
3900
+		}
3901
+		if (is_multisite() && is_network_admin()) {
3902
+			set_site_transient($transient, $data, 8);
3903
+		} else {
3904
+			set_transient($transient, $data, 8);
3905
+		}
3906
+	}
3907
+
3908
+
3909
+
3910
+	/**
3911
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3912
+	 *
3913
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3914
+	 * @param string $route
3915
+	 * @return mixed data
3916
+	 */
3917
+	protected function _get_transient($notices = false, $route = '')
3918
+	{
3919
+		$user_id   = get_current_user_id();
3920
+		$route     = ! $route ? $this->_req_action : $route;
3921
+		$transient = $notices
3922
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3923
+			: 'rte_tx_' . $route . '_' . $user_id;
3924
+		$data      = is_multisite() && is_network_admin()
3925
+			? get_site_transient($transient)
3926
+			: get_transient($transient);
3927
+		//delete transient after retrieval (just in case it hasn't expired);
3928
+		if (is_multisite() && is_network_admin()) {
3929
+			delete_site_transient($transient);
3930
+		} else {
3931
+			delete_transient($transient);
3932
+		}
3933
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3934
+	}
3935
+
3936
+
3937
+
3938
+	/**
3939
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3940
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3941
+	 * default route callback on the EE_Admin page you want it run.)
3942
+	 *
3943
+	 * @return void
3944
+	 */
3945
+	protected function _transient_garbage_collection()
3946
+	{
3947
+		global $wpdb;
3948
+		//retrieve all existing transients
3949
+		$query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3950
+		if ($results = $wpdb->get_results($query)) {
3951
+			foreach ($results as $result) {
3952
+				$transient = str_replace('_transient_', '', $result->option_name);
3953
+				get_transient($transient);
3954
+				if (is_multisite() && is_network_admin()) {
3955
+					get_site_transient($transient);
3956
+				}
3957
+			}
3958
+		}
3959
+	}
3960
+
3961
+
3962
+
3963
+	/**
3964
+	 * get_view
3965
+	 *
3966
+	 * @return string content of _view property
3967
+	 */
3968
+	public function get_view()
3969
+	{
3970
+		return $this->_view;
3971
+	}
3972
+
3973
+
3974
+
3975
+	/**
3976
+	 * getter for the protected $_views property
3977
+	 *
3978
+	 * @return array
3979
+	 */
3980
+	public function get_views()
3981
+	{
3982
+		return $this->_views;
3983
+	}
3984
+
3985
+
3986
+
3987
+	/**
3988
+	 * get_current_page
3989
+	 *
3990
+	 * @return string _current_page property value
3991
+	 */
3992
+	public function get_current_page()
3993
+	{
3994
+		return $this->_current_page;
3995
+	}
3996
+
3997
+
3998
+
3999
+	/**
4000
+	 * get_current_view
4001
+	 *
4002
+	 * @return string _current_view property value
4003
+	 */
4004
+	public function get_current_view()
4005
+	{
4006
+		return $this->_current_view;
4007
+	}
4008
+
4009
+
4010
+
4011
+	/**
4012
+	 * get_current_screen
4013
+	 *
4014
+	 * @return object The current WP_Screen object
4015
+	 */
4016
+	public function get_current_screen()
4017
+	{
4018
+		return $this->_current_screen;
4019
+	}
4020
+
4021
+
4022
+
4023
+	/**
4024
+	 * get_current_page_view_url
4025
+	 *
4026
+	 * @return string This returns the url for the current_page_view.
4027
+	 */
4028
+	public function get_current_page_view_url()
4029
+	{
4030
+		return $this->_current_page_view_url;
4031
+	}
4032
+
4033
+
4034
+
4035
+	/**
4036
+	 * just returns the _req_data property
4037
+	 *
4038
+	 * @return array
4039
+	 */
4040
+	public function get_request_data()
4041
+	{
4042
+		return $this->_req_data;
4043
+	}
4044
+
4045
+
4046
+
4047
+	/**
4048
+	 * returns the _req_data protected property
4049
+	 *
4050
+	 * @return string
4051
+	 */
4052
+	public function get_req_action()
4053
+	{
4054
+		return $this->_req_action;
4055
+	}
4056
+
4057
+
4058
+
4059
+	/**
4060
+	 * @return bool  value of $_is_caf property
4061
+	 */
4062
+	public function is_caf()
4063
+	{
4064
+		return $this->_is_caf;
4065
+	}
4066
+
4067
+
4068
+
4069
+	/**
4070
+	 * @return mixed
4071
+	 */
4072
+	public function default_espresso_metaboxes()
4073
+	{
4074
+		return $this->_default_espresso_metaboxes;
4075
+	}
4076
+
4077
+
4078
+
4079
+	/**
4080
+	 * @return mixed
4081
+	 */
4082
+	public function admin_base_url()
4083
+	{
4084
+		return $this->_admin_base_url;
4085
+	}
4086 4086
 
4087 4087
 
4088 4088
 
4089
-    /**
4090
-     * @return mixed
4091
-     */
4092
-    public function wp_page_slug()
4093
-    {
4094
-        return $this->_wp_page_slug;
4095
-    }
4089
+	/**
4090
+	 * @return mixed
4091
+	 */
4092
+	public function wp_page_slug()
4093
+	{
4094
+		return $this->_wp_page_slug;
4095
+	}
4096 4096
 
4097 4097
 
4098
-
4099
-    /**
4100
-     * updates  espresso configuration settings
4101
-     *
4102
-     * @param string                   $tab
4103
-     * @param EE_Config_Base|EE_Config $config
4104
-     * @param string                   $file file where error occurred
4105
-     * @param string                   $func function  where error occurred
4106
-     * @param string                   $line line no where error occurred
4107
-     * @return boolean
4108
-     */
4109
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4110
-    {
4111
-        //remove any options that are NOT going to be saved with the config settings.
4112
-        if (isset($config->core->ee_ueip_optin)) {
4113
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4114
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4115
-            update_option('ee_ueip_has_notified', true);
4116
-        }
4117
-        // and save it (note we're also doing the network save here)
4118
-        $net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4119
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4120
-        if ($config_saved && $net_saved) {
4121
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4122
-            return true;
4123
-        }
4124
-        EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4125
-        return false;
4126
-    }
4127
-
4128
-
4129
-
4130
-    /**
4131
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4132
-     *
4133
-     * @return array
4134
-     */
4135
-    public function get_yes_no_values()
4136
-    {
4137
-        return $this->_yes_no_values;
4138
-    }
4139
-
4140
-
4141
-
4142
-    protected function _get_dir()
4143
-    {
4144
-        $reflector = new ReflectionClass(get_class($this));
4145
-        return dirname($reflector->getFileName());
4146
-    }
4147
-
4148
-
4149
-
4150
-    /**
4151
-     * A helper for getting a "next link".
4152
-     *
4153
-     * @param string $url   The url to link to
4154
-     * @param string $class The class to use.
4155
-     * @return string
4156
-     */
4157
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4158
-    {
4159
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4160
-    }
4161
-
4162
-
4163
-
4164
-    /**
4165
-     * A helper for getting a "previous link".
4166
-     *
4167
-     * @param string $url   The url to link to
4168
-     * @param string $class The class to use.
4169
-     * @return string
4170
-     */
4171
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4172
-    {
4173
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4174
-    }
4175
-
4176
-
4177
-
4178
-
4179
-
4180
-
4181
-
4182
-    //below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4183
-
4184
-
4185
-    /**
4186
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4187
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4188
-     * _req_data array.
4189
-     *
4190
-     * @return bool success/fail
4191
-     * @throws EE_Error
4192
-     * @throws InvalidArgumentException
4193
-     * @throws ReflectionException
4194
-     * @throws InvalidDataTypeException
4195
-     * @throws InvalidInterfaceException
4196
-     */
4197
-    protected function _process_resend_registration()
4198
-    {
4199
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4200
-        do_action(
4201
-            'AHEE__EE_Admin_Page___process_resend_registration',
4202
-            $this->_template_args['success'],
4203
-            $this->_req_data
4204
-        );
4205
-        return $this->_template_args['success'];
4206
-    }
4207
-
4208
-
4209
-
4210
-    /**
4211
-     * This automatically processes any payment message notifications when manual payment has been applied.
4212
-     *
4213
-     * @param \EE_Payment $payment
4214
-     * @return bool success/fail
4215
-     */
4216
-    protected function _process_payment_notification(EE_Payment $payment)
4217
-    {
4218
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4219
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4220
-        $this->_template_args['success'] = apply_filters(
4221
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4222
-            false,
4223
-            $payment
4224
-        );
4225
-        return $this->_template_args['success'];
4226
-    }
4098
+
4099
+	/**
4100
+	 * updates  espresso configuration settings
4101
+	 *
4102
+	 * @param string                   $tab
4103
+	 * @param EE_Config_Base|EE_Config $config
4104
+	 * @param string                   $file file where error occurred
4105
+	 * @param string                   $func function  where error occurred
4106
+	 * @param string                   $line line no where error occurred
4107
+	 * @return boolean
4108
+	 */
4109
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4110
+	{
4111
+		//remove any options that are NOT going to be saved with the config settings.
4112
+		if (isset($config->core->ee_ueip_optin)) {
4113
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4114
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4115
+			update_option('ee_ueip_has_notified', true);
4116
+		}
4117
+		// and save it (note we're also doing the network save here)
4118
+		$net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4119
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4120
+		if ($config_saved && $net_saved) {
4121
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4122
+			return true;
4123
+		}
4124
+		EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4125
+		return false;
4126
+	}
4127
+
4128
+
4129
+
4130
+	/**
4131
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4132
+	 *
4133
+	 * @return array
4134
+	 */
4135
+	public function get_yes_no_values()
4136
+	{
4137
+		return $this->_yes_no_values;
4138
+	}
4139
+
4140
+
4141
+
4142
+	protected function _get_dir()
4143
+	{
4144
+		$reflector = new ReflectionClass(get_class($this));
4145
+		return dirname($reflector->getFileName());
4146
+	}
4147
+
4148
+
4149
+
4150
+	/**
4151
+	 * A helper for getting a "next link".
4152
+	 *
4153
+	 * @param string $url   The url to link to
4154
+	 * @param string $class The class to use.
4155
+	 * @return string
4156
+	 */
4157
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4158
+	{
4159
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4160
+	}
4161
+
4162
+
4163
+
4164
+	/**
4165
+	 * A helper for getting a "previous link".
4166
+	 *
4167
+	 * @param string $url   The url to link to
4168
+	 * @param string $class The class to use.
4169
+	 * @return string
4170
+	 */
4171
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4172
+	{
4173
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4174
+	}
4175
+
4176
+
4177
+
4178
+
4179
+
4180
+
4181
+
4182
+	//below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4183
+
4184
+
4185
+	/**
4186
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4187
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4188
+	 * _req_data array.
4189
+	 *
4190
+	 * @return bool success/fail
4191
+	 * @throws EE_Error
4192
+	 * @throws InvalidArgumentException
4193
+	 * @throws ReflectionException
4194
+	 * @throws InvalidDataTypeException
4195
+	 * @throws InvalidInterfaceException
4196
+	 */
4197
+	protected function _process_resend_registration()
4198
+	{
4199
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4200
+		do_action(
4201
+			'AHEE__EE_Admin_Page___process_resend_registration',
4202
+			$this->_template_args['success'],
4203
+			$this->_req_data
4204
+		);
4205
+		return $this->_template_args['success'];
4206
+	}
4207
+
4208
+
4209
+
4210
+	/**
4211
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4212
+	 *
4213
+	 * @param \EE_Payment $payment
4214
+	 * @return bool success/fail
4215
+	 */
4216
+	protected function _process_payment_notification(EE_Payment $payment)
4217
+	{
4218
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4219
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4220
+		$this->_template_args['success'] = apply_filters(
4221
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4222
+			false,
4223
+			$payment
4224
+		);
4225
+		return $this->_template_args['success'];
4226
+	}
4227 4227
 
4228 4228
 
4229 4229
 }
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 2 patches
Indentation   +859 added lines, -859 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\services\request\ResponseInterface;
9 9
 
10 10
 if (! defined('EVENT_ESPRESSO_VERSION')) {
11
-    exit('No direct script access allowed');
11
+	exit('No direct script access allowed');
12 12
 }
13 13
 
14 14
 
@@ -25,865 +25,865 @@  discard block
 block discarded – undo
25 25
 class EE_Dependency_Map
26 26
 {
27 27
 
28
-    /**
29
-     * This means that the requested class dependency is not present in the dependency map
30
-     */
31
-    const not_registered = 0;
32
-
33
-    /**
34
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
35
-     */
36
-    const load_new_object = 1;
37
-
38
-    /**
39
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
40
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
41
-     */
42
-    const load_from_cache = 2;
43
-
44
-    /**
45
-     * When registering a dependency,
46
-     * this indicates to keep any existing dependencies that already exist,
47
-     * and simply discard any new dependencies declared in the incoming data
48
-     */
49
-    const KEEP_EXISTING_DEPENDENCIES = 0;
50
-
51
-    /**
52
-     * When registering a dependency,
53
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
54
-     */
55
-    const OVERWRITE_DEPENDENCIES = 1;
56
-
57
-
58
-
59
-    /**
60
-     * @type EE_Dependency_Map $_instance
61
-     */
62
-    protected static $_instance;
63
-
64
-    /**
65
-     * @type RequestInterface $request
66
-     */
67
-    protected $request;
68
-
69
-    /**
70
-     * @type LegacyRequestInterface $legacy_request
71
-     */
72
-    protected $legacy_request;
73
-
74
-    /**
75
-     * @type ResponseInterface $response
76
-     */
77
-    protected $response;
78
-
79
-    /**
80
-     * @type LoaderInterface $loader
81
-     */
82
-    protected $loader;
83
-
84
-    /**
85
-     * @type array $_dependency_map
86
-     */
87
-    protected $_dependency_map = array();
88
-
89
-    /**
90
-     * @type array $_class_loaders
91
-     */
92
-    protected $_class_loaders = array();
93
-
94
-    /**
95
-     * @type array $_aliases
96
-     */
97
-    protected $_aliases = array();
98
-
99
-
100
-
101
-    /**
102
-     * EE_Dependency_Map constructor.
103
-     */
104
-    protected function __construct()
105
-    {
106
-        // add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
107
-        do_action('EE_Dependency_Map____construct');
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidArgumentException
116
-     */
117
-    public function initialize()
118
-    {
119
-        $this->_register_core_dependencies();
120
-        $this->_register_core_class_loaders();
121
-        $this->_register_core_aliases();
122
-    }
123
-
124
-
125
-
126
-    /**
127
-     * @singleton method used to instantiate class object
128
-     * @return EE_Dependency_Map
129
-     */
130
-    public static function instance() {
131
-        // check if class object is instantiated, and instantiated properly
132
-        if (! self::$_instance instanceof EE_Dependency_Map) {
133
-            self::$_instance = new EE_Dependency_Map(/*$request, $response, $legacy_request*/);
134
-        }
135
-        return self::$_instance;
136
-    }
137
-
138
-
139
-    /**
140
-     * @param RequestInterface $request
141
-     */
142
-    public function setRequest(RequestInterface $request)
143
-    {
144
-        $this->request = $request;
145
-    }
146
-
147
-
148
-    /**
149
-     * @param LegacyRequestInterface $legacy_request
150
-     */
151
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
152
-    {
153
-        $this->legacy_request = $legacy_request;
154
-    }
155
-
156
-
157
-    /**
158
-     * @param ResponseInterface $response
159
-     */
160
-    public function setResponse(ResponseInterface $response)
161
-    {
162
-        $this->response = $response;
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * @param LoaderInterface $loader
169
-     */
170
-    public function setLoader(LoaderInterface $loader)
171
-    {
172
-        $this->loader = $loader;
173
-    }
174
-
175
-
176
-
177
-    /**
178
-     * @param string $class
179
-     * @param array  $dependencies
180
-     * @param int    $overwrite
181
-     * @return bool
182
-     */
183
-    public static function register_dependencies(
184
-        $class,
185
-        array $dependencies,
186
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
187
-    ) {
188
-        return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
189
-    }
190
-
191
-
192
-
193
-    /**
194
-     * Assigns an array of class names and corresponding load sources (new or cached)
195
-     * to the class specified by the first parameter.
196
-     * IMPORTANT !!!
197
-     * The order of elements in the incoming $dependencies array MUST match
198
-     * the order of the constructor parameters for the class in question.
199
-     * This is especially important when overriding any existing dependencies that are registered.
200
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
201
-     *
202
-     * @param string $class
203
-     * @param array  $dependencies
204
-     * @param int    $overwrite
205
-     * @return bool
206
-     */
207
-    public function registerDependencies(
208
-        $class,
209
-        array $dependencies,
210
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
211
-    ) {
212
-        $class = trim($class, '\\');
213
-        $registered = false;
214
-        if (empty(self::$_instance->_dependency_map[ $class ])) {
215
-            self::$_instance->_dependency_map[ $class ] = array();
216
-        }
217
-        // we need to make sure that any aliases used when registering a dependency
218
-        // get resolved to the correct class name
219
-        foreach ($dependencies as $dependency => $load_source) {
220
-            $alias = self::$_instance->get_alias($dependency);
221
-            if (
222
-                $overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
223
-                || ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
224
-            ) {
225
-                unset($dependencies[$dependency]);
226
-                $dependencies[$alias] = $load_source;
227
-                $registered = true;
228
-            }
229
-        }
230
-        // now add our two lists of dependencies together.
231
-        // using Union (+=) favours the arrays in precedence from left to right,
232
-        // so $dependencies is NOT overwritten because it is listed first
233
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
234
-        // Union is way faster than array_merge() but should be used with caution...
235
-        // especially with numerically indexed arrays
236
-        $dependencies += self::$_instance->_dependency_map[ $class ];
237
-        // now we need to ensure that the resulting dependencies
238
-        // array only has the entries that are required for the class
239
-        // so first count how many dependencies were originally registered for the class
240
-        $dependency_count = count(self::$_instance->_dependency_map[ $class ]);
241
-        // if that count is non-zero (meaning dependencies were already registered)
242
-        self::$_instance->_dependency_map[ $class ] = $dependency_count
243
-            // then truncate the  final array to match that count
244
-            ? array_slice($dependencies, 0, $dependency_count)
245
-            // otherwise just take the incoming array because nothing previously existed
246
-            : $dependencies;
247
-        return $registered;
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * @param string $class_name
254
-     * @param string $loader
255
-     * @return bool
256
-     * @throws DomainException
257
-     */
258
-    public static function register_class_loader($class_name, $loader = 'load_core')
259
-    {
260
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
261
-            throw new DomainException(
262
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
263
-            );
264
-        }
265
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
266
-        if (
267
-            ! is_callable($loader)
268
-            && (
269
-                strpos($loader, 'load_') !== 0
270
-                || ! method_exists('EE_Registry', $loader)
271
-            )
272
-        ) {
273
-            throw new DomainException(
274
-                sprintf(
275
-                    esc_html__(
276
-                        '"%1$s" is not a valid loader method on EE_Registry.',
277
-                        'event_espresso'
278
-                    ),
279
-                    $loader
280
-                )
281
-            );
282
-        }
283
-        $class_name = self::$_instance->get_alias($class_name);
284
-        if (! isset(self::$_instance->_class_loaders[$class_name])) {
285
-            self::$_instance->_class_loaders[$class_name] = $loader;
286
-            return true;
287
-        }
288
-        return false;
289
-    }
290
-
291
-
292
-
293
-    /**
294
-     * @return array
295
-     */
296
-    public function dependency_map()
297
-    {
298
-        return $this->_dependency_map;
299
-    }
300
-
301
-
302
-
303
-    /**
304
-     * returns TRUE if dependency map contains a listing for the provided class name
305
-     *
306
-     * @param string $class_name
307
-     * @return boolean
308
-     */
309
-    public function has($class_name = '')
310
-    {
311
-        // all legacy models have the same dependencies
312
-        if (strpos($class_name, 'EEM_') === 0) {
313
-            $class_name = 'LEGACY_MODELS';
314
-        }
315
-        return isset($this->_dependency_map[$class_name]) ? true : false;
316
-    }
317
-
318
-
319
-
320
-    /**
321
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
322
-     *
323
-     * @param string $class_name
324
-     * @param string $dependency
325
-     * @return bool
326
-     */
327
-    public function has_dependency_for_class($class_name = '', $dependency = '')
328
-    {
329
-        // all legacy models have the same dependencies
330
-        if (strpos($class_name, 'EEM_') === 0) {
331
-            $class_name = 'LEGACY_MODELS';
332
-        }
333
-        $dependency = $this->get_alias($dependency);
334
-        return isset($this->_dependency_map[$class_name][$dependency])
335
-            ? true
336
-            : false;
337
-    }
338
-
339
-
340
-
341
-    /**
342
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
343
-     *
344
-     * @param string $class_name
345
-     * @param string $dependency
346
-     * @return int
347
-     */
348
-    public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
349
-    {
350
-        // all legacy models have the same dependencies
351
-        if (strpos($class_name, 'EEM_') === 0) {
352
-            $class_name = 'LEGACY_MODELS';
353
-        }
354
-        $dependency = $this->get_alias($dependency);
355
-        return $this->has_dependency_for_class($class_name, $dependency)
356
-            ? $this->_dependency_map[$class_name][$dependency]
357
-            : EE_Dependency_Map::not_registered;
358
-    }
359
-
360
-
361
-
362
-    /**
363
-     * @param string $class_name
364
-     * @return string | Closure
365
-     */
366
-    public function class_loader($class_name)
367
-    {
368
-        // all legacy models use load_model()
369
-        if(strpos($class_name, 'EEM_') === 0){
370
-            return 'load_model';
371
-        }
372
-        $class_name = $this->get_alias($class_name);
373
-        return isset($this->_class_loaders[$class_name]) ? $this->_class_loaders[$class_name] : '';
374
-    }
375
-
376
-
377
-
378
-    /**
379
-     * @return array
380
-     */
381
-    public function class_loaders()
382
-    {
383
-        return $this->_class_loaders;
384
-    }
385
-
386
-
387
-
388
-    /**
389
-     * adds an alias for a classname
390
-     *
391
-     * @param string $class_name the class name that should be used (concrete class to replace interface)
392
-     * @param string $alias      the class name that would be type hinted for (abstract parent or interface)
393
-     * @param string $for_class  the class that has the dependency (is type hinting for the interface)
394
-     */
395
-    public function add_alias($class_name, $alias, $for_class = '')
396
-    {
397
-        if ($for_class !== '') {
398
-            if (! isset($this->_aliases[$for_class])) {
399
-                $this->_aliases[$for_class] = array();
400
-            }
401
-            $this->_aliases[$for_class][$class_name] = $alias;
402
-        }
403
-        $this->_aliases[$class_name] = $alias;
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * returns TRUE if the provided class name has an alias
410
-     *
411
-     * @param string $class_name
412
-     * @param string $for_class
413
-     * @return bool
414
-     */
415
-    public function has_alias($class_name = '', $for_class = '')
416
-    {
417
-        return isset($this->_aliases[$for_class][$class_name])
418
-               || (
419
-                   isset($this->_aliases[$class_name])
420
-                   && ! is_array($this->_aliases[$class_name])
421
-               );
422
-    }
423
-
424
-
425
-
426
-    /**
427
-     * returns alias for class name if one exists, otherwise returns the original classname
428
-     * functions recursively, so that multiple aliases can be used to drill down to a classname
429
-     *  for example:
430
-     *      if the following two entries were added to the _aliases array:
431
-     *          array(
432
-     *              'interface_alias'           => 'some\namespace\interface'
433
-     *              'some\namespace\interface'  => 'some\namespace\classname'
434
-     *          )
435
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
436
-     *      to load an instance of 'some\namespace\classname'
437
-     *
438
-     * @param string $class_name
439
-     * @param string $for_class
440
-     * @return string
441
-     */
442
-    public function get_alias($class_name = '', $for_class = '')
443
-    {
444
-        if (! $this->has_alias($class_name, $for_class)) {
445
-            return $class_name;
446
-        }
447
-        if ($for_class !== '' && isset($this->_aliases[ $for_class ][ $class_name ])) {
448
-            return $this->get_alias($this->_aliases[$for_class][$class_name], $for_class);
449
-        }
450
-        return $this->get_alias($this->_aliases[$class_name]);
451
-    }
452
-
453
-
454
-
455
-    /**
456
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
457
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
458
-     * This is done by using the following class constants:
459
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
460
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
461
-     */
462
-    protected function _register_core_dependencies()
463
-    {
464
-        $this->_dependency_map = array(
465
-            'EE_Request_Handler'                                                                                          => array(
466
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
467
-            ),
468
-            'EE_System'                                                                                                   => array(
469
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
470
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
471
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
472
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
473
-            ),
474
-            'EE_Session'                                                                                                  => array(
475
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
476
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
477
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
478
-                'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
479
-            ),
480
-            'EE_Cart'                                                                                                     => array(
481
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
482
-            ),
483
-            'EE_Front_Controller'                                                                                         => array(
484
-                'EE_Registry'              => EE_Dependency_Map::load_from_cache,
485
-                'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
486
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
487
-            ),
488
-            'EE_Messenger_Collection_Loader'                                                                              => array(
489
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
490
-            ),
491
-            'EE_Message_Type_Collection_Loader'                                                                           => array(
492
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
493
-            ),
494
-            'EE_Message_Resource_Manager'                                                                                 => array(
495
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
496
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
497
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
498
-            ),
499
-            'EE_Message_Factory'                                                                                          => array(
500
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
501
-            ),
502
-            'EE_messages'                                                                                                 => array(
503
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
-            ),
505
-            'EE_Messages_Generator'                                                                                       => array(
506
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
507
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
508
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
509
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
510
-            ),
511
-            'EE_Messages_Processor'                                                                                       => array(
512
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
513
-            ),
514
-            'EE_Messages_Queue'                                                                                           => array(
515
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
516
-            ),
517
-            'EE_Messages_Template_Defaults'                                                                               => array(
518
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
519
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
520
-            ),
521
-            'EE_Message_To_Generate_From_Request'                                                                         => array(
522
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
523
-                'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
524
-            ),
525
-            'EventEspresso\core\services\commands\CommandBus'                                                             => array(
526
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
527
-            ),
528
-            'EventEspresso\services\commands\CommandHandler'                                                              => array(
529
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
530
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
531
-            ),
532
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
533
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
534
-            ),
535
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
536
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
537
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
538
-            ),
539
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
540
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
541
-            ),
542
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
543
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
544
-            ),
545
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
546
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
547
-            ),
548
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
549
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
-            ),
551
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
552
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
553
-            ),
554
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
555
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
556
-            ),
557
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
558
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
-            ),
560
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
561
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
562
-            ),
563
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
564
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
565
-            ),
566
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
567
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
568
-            ),
569
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
570
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
-            ),
572
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
573
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
-            ),
575
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
576
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
577
-            ),
578
-            'EventEspresso\core\services\database\TableManager'                                                           => array(
579
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
580
-            ),
581
-            'EE_Data_Migration_Class_Base'                                                                                => array(
582
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
584
-            ),
585
-            'EE_DMS_Core_4_1_0'                                                                                           => array(
586
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
587
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
588
-            ),
589
-            'EE_DMS_Core_4_2_0'                                                                                           => array(
590
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
591
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
592
-            ),
593
-            'EE_DMS_Core_4_3_0'                                                                                           => array(
594
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
595
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
596
-            ),
597
-            'EE_DMS_Core_4_4_0'                                                                                           => array(
598
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
599
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
600
-            ),
601
-            'EE_DMS_Core_4_5_0'                                                                                           => array(
602
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
603
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
604
-            ),
605
-            'EE_DMS_Core_4_6_0'                                                                                           => array(
606
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
607
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
608
-            ),
609
-            'EE_DMS_Core_4_7_0'                                                                                           => array(
610
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
611
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
612
-            ),
613
-            'EE_DMS_Core_4_8_0'                                                                                           => array(
614
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
615
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
616
-            ),
617
-            'EE_DMS_Core_4_9_0'                                                                                           => array(
618
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
619
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
620
-            ),
621
-            'EventEspresso\core\services\assets\Registry'                                                                 => array(
622
-                'EE_Template_Config' => EE_Dependency_Map::load_from_cache,
623
-                'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
624
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache
625
-            ),
626
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
627
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
628
-            ),
629
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
630
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
631
-            ),
632
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
633
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
634
-            ),
635
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
636
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
637
-            ),
638
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
639
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
640
-            ),
641
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
642
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
643
-            ),
644
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
645
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
646
-            ),
647
-            'EventEspresso\core\services\cache\BasicCacheManager'                        => array(
648
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
649
-            ),
650
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                  => array(
651
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
652
-            ),
653
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService' => array(
654
-                'EE_Registration_Config'                                  => EE_Dependency_Map::load_from_cache,
655
-                'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
656
-            ),
657
-            'EventEspresso\core\domain\values\EmailAddress'                              => array(
658
-                null,
659
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
660
-            ),
661
-            'EventEspresso\core\services\orm\ModelFieldFactory' => array(
662
-                'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
663
-            ),
664
-            'LEGACY_MODELS'                                                   => array(
665
-                null,
666
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
667
-            ),
668
-            'EE_Module_Request_Router' => array(
669
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
670
-            ),
671
-            'EE_Registration_Processor' => array(
672
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
673
-            ),
674
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' => array(
675
-                null,
676
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
677
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
678
-            ),
679
-            'EventEspresso\core\services\licensing\LicenseService' => array(
680
-                'EventEspresso\core\domain\services\pue\Stats' => EE_Dependency_Map::load_from_cache,
681
-                'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache
682
-            ),
28
+	/**
29
+	 * This means that the requested class dependency is not present in the dependency map
30
+	 */
31
+	const not_registered = 0;
32
+
33
+	/**
34
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
35
+	 */
36
+	const load_new_object = 1;
37
+
38
+	/**
39
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
40
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
41
+	 */
42
+	const load_from_cache = 2;
43
+
44
+	/**
45
+	 * When registering a dependency,
46
+	 * this indicates to keep any existing dependencies that already exist,
47
+	 * and simply discard any new dependencies declared in the incoming data
48
+	 */
49
+	const KEEP_EXISTING_DEPENDENCIES = 0;
50
+
51
+	/**
52
+	 * When registering a dependency,
53
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
54
+	 */
55
+	const OVERWRITE_DEPENDENCIES = 1;
56
+
57
+
58
+
59
+	/**
60
+	 * @type EE_Dependency_Map $_instance
61
+	 */
62
+	protected static $_instance;
63
+
64
+	/**
65
+	 * @type RequestInterface $request
66
+	 */
67
+	protected $request;
68
+
69
+	/**
70
+	 * @type LegacyRequestInterface $legacy_request
71
+	 */
72
+	protected $legacy_request;
73
+
74
+	/**
75
+	 * @type ResponseInterface $response
76
+	 */
77
+	protected $response;
78
+
79
+	/**
80
+	 * @type LoaderInterface $loader
81
+	 */
82
+	protected $loader;
83
+
84
+	/**
85
+	 * @type array $_dependency_map
86
+	 */
87
+	protected $_dependency_map = array();
88
+
89
+	/**
90
+	 * @type array $_class_loaders
91
+	 */
92
+	protected $_class_loaders = array();
93
+
94
+	/**
95
+	 * @type array $_aliases
96
+	 */
97
+	protected $_aliases = array();
98
+
99
+
100
+
101
+	/**
102
+	 * EE_Dependency_Map constructor.
103
+	 */
104
+	protected function __construct()
105
+	{
106
+		// add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
107
+		do_action('EE_Dependency_Map____construct');
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidArgumentException
116
+	 */
117
+	public function initialize()
118
+	{
119
+		$this->_register_core_dependencies();
120
+		$this->_register_core_class_loaders();
121
+		$this->_register_core_aliases();
122
+	}
123
+
124
+
125
+
126
+	/**
127
+	 * @singleton method used to instantiate class object
128
+	 * @return EE_Dependency_Map
129
+	 */
130
+	public static function instance() {
131
+		// check if class object is instantiated, and instantiated properly
132
+		if (! self::$_instance instanceof EE_Dependency_Map) {
133
+			self::$_instance = new EE_Dependency_Map(/*$request, $response, $legacy_request*/);
134
+		}
135
+		return self::$_instance;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @param RequestInterface $request
141
+	 */
142
+	public function setRequest(RequestInterface $request)
143
+	{
144
+		$this->request = $request;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @param LegacyRequestInterface $legacy_request
150
+	 */
151
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
152
+	{
153
+		$this->legacy_request = $legacy_request;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @param ResponseInterface $response
159
+	 */
160
+	public function setResponse(ResponseInterface $response)
161
+	{
162
+		$this->response = $response;
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * @param LoaderInterface $loader
169
+	 */
170
+	public function setLoader(LoaderInterface $loader)
171
+	{
172
+		$this->loader = $loader;
173
+	}
174
+
175
+
176
+
177
+	/**
178
+	 * @param string $class
179
+	 * @param array  $dependencies
180
+	 * @param int    $overwrite
181
+	 * @return bool
182
+	 */
183
+	public static function register_dependencies(
184
+		$class,
185
+		array $dependencies,
186
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
187
+	) {
188
+		return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
189
+	}
190
+
191
+
192
+
193
+	/**
194
+	 * Assigns an array of class names and corresponding load sources (new or cached)
195
+	 * to the class specified by the first parameter.
196
+	 * IMPORTANT !!!
197
+	 * The order of elements in the incoming $dependencies array MUST match
198
+	 * the order of the constructor parameters for the class in question.
199
+	 * This is especially important when overriding any existing dependencies that are registered.
200
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
201
+	 *
202
+	 * @param string $class
203
+	 * @param array  $dependencies
204
+	 * @param int    $overwrite
205
+	 * @return bool
206
+	 */
207
+	public function registerDependencies(
208
+		$class,
209
+		array $dependencies,
210
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
211
+	) {
212
+		$class = trim($class, '\\');
213
+		$registered = false;
214
+		if (empty(self::$_instance->_dependency_map[ $class ])) {
215
+			self::$_instance->_dependency_map[ $class ] = array();
216
+		}
217
+		// we need to make sure that any aliases used when registering a dependency
218
+		// get resolved to the correct class name
219
+		foreach ($dependencies as $dependency => $load_source) {
220
+			$alias = self::$_instance->get_alias($dependency);
221
+			if (
222
+				$overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
223
+				|| ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
224
+			) {
225
+				unset($dependencies[$dependency]);
226
+				$dependencies[$alias] = $load_source;
227
+				$registered = true;
228
+			}
229
+		}
230
+		// now add our two lists of dependencies together.
231
+		// using Union (+=) favours the arrays in precedence from left to right,
232
+		// so $dependencies is NOT overwritten because it is listed first
233
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
234
+		// Union is way faster than array_merge() but should be used with caution...
235
+		// especially with numerically indexed arrays
236
+		$dependencies += self::$_instance->_dependency_map[ $class ];
237
+		// now we need to ensure that the resulting dependencies
238
+		// array only has the entries that are required for the class
239
+		// so first count how many dependencies were originally registered for the class
240
+		$dependency_count = count(self::$_instance->_dependency_map[ $class ]);
241
+		// if that count is non-zero (meaning dependencies were already registered)
242
+		self::$_instance->_dependency_map[ $class ] = $dependency_count
243
+			// then truncate the  final array to match that count
244
+			? array_slice($dependencies, 0, $dependency_count)
245
+			// otherwise just take the incoming array because nothing previously existed
246
+			: $dependencies;
247
+		return $registered;
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * @param string $class_name
254
+	 * @param string $loader
255
+	 * @return bool
256
+	 * @throws DomainException
257
+	 */
258
+	public static function register_class_loader($class_name, $loader = 'load_core')
259
+	{
260
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
261
+			throw new DomainException(
262
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
263
+			);
264
+		}
265
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
266
+		if (
267
+			! is_callable($loader)
268
+			&& (
269
+				strpos($loader, 'load_') !== 0
270
+				|| ! method_exists('EE_Registry', $loader)
271
+			)
272
+		) {
273
+			throw new DomainException(
274
+				sprintf(
275
+					esc_html__(
276
+						'"%1$s" is not a valid loader method on EE_Registry.',
277
+						'event_espresso'
278
+					),
279
+					$loader
280
+				)
281
+			);
282
+		}
283
+		$class_name = self::$_instance->get_alias($class_name);
284
+		if (! isset(self::$_instance->_class_loaders[$class_name])) {
285
+			self::$_instance->_class_loaders[$class_name] = $loader;
286
+			return true;
287
+		}
288
+		return false;
289
+	}
290
+
291
+
292
+
293
+	/**
294
+	 * @return array
295
+	 */
296
+	public function dependency_map()
297
+	{
298
+		return $this->_dependency_map;
299
+	}
300
+
301
+
302
+
303
+	/**
304
+	 * returns TRUE if dependency map contains a listing for the provided class name
305
+	 *
306
+	 * @param string $class_name
307
+	 * @return boolean
308
+	 */
309
+	public function has($class_name = '')
310
+	{
311
+		// all legacy models have the same dependencies
312
+		if (strpos($class_name, 'EEM_') === 0) {
313
+			$class_name = 'LEGACY_MODELS';
314
+		}
315
+		return isset($this->_dependency_map[$class_name]) ? true : false;
316
+	}
317
+
318
+
319
+
320
+	/**
321
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
322
+	 *
323
+	 * @param string $class_name
324
+	 * @param string $dependency
325
+	 * @return bool
326
+	 */
327
+	public function has_dependency_for_class($class_name = '', $dependency = '')
328
+	{
329
+		// all legacy models have the same dependencies
330
+		if (strpos($class_name, 'EEM_') === 0) {
331
+			$class_name = 'LEGACY_MODELS';
332
+		}
333
+		$dependency = $this->get_alias($dependency);
334
+		return isset($this->_dependency_map[$class_name][$dependency])
335
+			? true
336
+			: false;
337
+	}
338
+
339
+
340
+
341
+	/**
342
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
343
+	 *
344
+	 * @param string $class_name
345
+	 * @param string $dependency
346
+	 * @return int
347
+	 */
348
+	public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
349
+	{
350
+		// all legacy models have the same dependencies
351
+		if (strpos($class_name, 'EEM_') === 0) {
352
+			$class_name = 'LEGACY_MODELS';
353
+		}
354
+		$dependency = $this->get_alias($dependency);
355
+		return $this->has_dependency_for_class($class_name, $dependency)
356
+			? $this->_dependency_map[$class_name][$dependency]
357
+			: EE_Dependency_Map::not_registered;
358
+	}
359
+
360
+
361
+
362
+	/**
363
+	 * @param string $class_name
364
+	 * @return string | Closure
365
+	 */
366
+	public function class_loader($class_name)
367
+	{
368
+		// all legacy models use load_model()
369
+		if(strpos($class_name, 'EEM_') === 0){
370
+			return 'load_model';
371
+		}
372
+		$class_name = $this->get_alias($class_name);
373
+		return isset($this->_class_loaders[$class_name]) ? $this->_class_loaders[$class_name] : '';
374
+	}
375
+
376
+
377
+
378
+	/**
379
+	 * @return array
380
+	 */
381
+	public function class_loaders()
382
+	{
383
+		return $this->_class_loaders;
384
+	}
385
+
386
+
387
+
388
+	/**
389
+	 * adds an alias for a classname
390
+	 *
391
+	 * @param string $class_name the class name that should be used (concrete class to replace interface)
392
+	 * @param string $alias      the class name that would be type hinted for (abstract parent or interface)
393
+	 * @param string $for_class  the class that has the dependency (is type hinting for the interface)
394
+	 */
395
+	public function add_alias($class_name, $alias, $for_class = '')
396
+	{
397
+		if ($for_class !== '') {
398
+			if (! isset($this->_aliases[$for_class])) {
399
+				$this->_aliases[$for_class] = array();
400
+			}
401
+			$this->_aliases[$for_class][$class_name] = $alias;
402
+		}
403
+		$this->_aliases[$class_name] = $alias;
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * returns TRUE if the provided class name has an alias
410
+	 *
411
+	 * @param string $class_name
412
+	 * @param string $for_class
413
+	 * @return bool
414
+	 */
415
+	public function has_alias($class_name = '', $for_class = '')
416
+	{
417
+		return isset($this->_aliases[$for_class][$class_name])
418
+			   || (
419
+				   isset($this->_aliases[$class_name])
420
+				   && ! is_array($this->_aliases[$class_name])
421
+			   );
422
+	}
423
+
424
+
425
+
426
+	/**
427
+	 * returns alias for class name if one exists, otherwise returns the original classname
428
+	 * functions recursively, so that multiple aliases can be used to drill down to a classname
429
+	 *  for example:
430
+	 *      if the following two entries were added to the _aliases array:
431
+	 *          array(
432
+	 *              'interface_alias'           => 'some\namespace\interface'
433
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
434
+	 *          )
435
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
436
+	 *      to load an instance of 'some\namespace\classname'
437
+	 *
438
+	 * @param string $class_name
439
+	 * @param string $for_class
440
+	 * @return string
441
+	 */
442
+	public function get_alias($class_name = '', $for_class = '')
443
+	{
444
+		if (! $this->has_alias($class_name, $for_class)) {
445
+			return $class_name;
446
+		}
447
+		if ($for_class !== '' && isset($this->_aliases[ $for_class ][ $class_name ])) {
448
+			return $this->get_alias($this->_aliases[$for_class][$class_name], $for_class);
449
+		}
450
+		return $this->get_alias($this->_aliases[$class_name]);
451
+	}
452
+
453
+
454
+
455
+	/**
456
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
457
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
458
+	 * This is done by using the following class constants:
459
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
460
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
461
+	 */
462
+	protected function _register_core_dependencies()
463
+	{
464
+		$this->_dependency_map = array(
465
+			'EE_Request_Handler'                                                                                          => array(
466
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
467
+			),
468
+			'EE_System'                                                                                                   => array(
469
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
470
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
471
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
472
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
473
+			),
474
+			'EE_Session'                                                                                                  => array(
475
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
476
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
477
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
478
+				'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
479
+			),
480
+			'EE_Cart'                                                                                                     => array(
481
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
482
+			),
483
+			'EE_Front_Controller'                                                                                         => array(
484
+				'EE_Registry'              => EE_Dependency_Map::load_from_cache,
485
+				'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
486
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
487
+			),
488
+			'EE_Messenger_Collection_Loader'                                                                              => array(
489
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
490
+			),
491
+			'EE_Message_Type_Collection_Loader'                                                                           => array(
492
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
493
+			),
494
+			'EE_Message_Resource_Manager'                                                                                 => array(
495
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
496
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
497
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
498
+			),
499
+			'EE_Message_Factory'                                                                                          => array(
500
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
501
+			),
502
+			'EE_messages'                                                                                                 => array(
503
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
+			),
505
+			'EE_Messages_Generator'                                                                                       => array(
506
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
507
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
508
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
509
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
510
+			),
511
+			'EE_Messages_Processor'                                                                                       => array(
512
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
513
+			),
514
+			'EE_Messages_Queue'                                                                                           => array(
515
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
516
+			),
517
+			'EE_Messages_Template_Defaults'                                                                               => array(
518
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
519
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
520
+			),
521
+			'EE_Message_To_Generate_From_Request'                                                                         => array(
522
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
523
+				'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
524
+			),
525
+			'EventEspresso\core\services\commands\CommandBus'                                                             => array(
526
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
527
+			),
528
+			'EventEspresso\services\commands\CommandHandler'                                                              => array(
529
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
530
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
531
+			),
532
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
533
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
534
+			),
535
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
536
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
537
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
538
+			),
539
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
540
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
541
+			),
542
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
543
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
544
+			),
545
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
546
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
547
+			),
548
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
549
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
+			),
551
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
552
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
553
+			),
554
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
555
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
556
+			),
557
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
558
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
+			),
560
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
561
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
562
+			),
563
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
564
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
565
+			),
566
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
567
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
568
+			),
569
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
570
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
+			),
572
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
573
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
+			),
575
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
576
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
577
+			),
578
+			'EventEspresso\core\services\database\TableManager'                                                           => array(
579
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
580
+			),
581
+			'EE_Data_Migration_Class_Base'                                                                                => array(
582
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
584
+			),
585
+			'EE_DMS_Core_4_1_0'                                                                                           => array(
586
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
587
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
588
+			),
589
+			'EE_DMS_Core_4_2_0'                                                                                           => array(
590
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
591
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
592
+			),
593
+			'EE_DMS_Core_4_3_0'                                                                                           => array(
594
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
595
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
596
+			),
597
+			'EE_DMS_Core_4_4_0'                                                                                           => array(
598
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
599
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
600
+			),
601
+			'EE_DMS_Core_4_5_0'                                                                                           => array(
602
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
603
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
604
+			),
605
+			'EE_DMS_Core_4_6_0'                                                                                           => array(
606
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
607
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
608
+			),
609
+			'EE_DMS_Core_4_7_0'                                                                                           => array(
610
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
611
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
612
+			),
613
+			'EE_DMS_Core_4_8_0'                                                                                           => array(
614
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
615
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
616
+			),
617
+			'EE_DMS_Core_4_9_0'                                                                                           => array(
618
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
619
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
620
+			),
621
+			'EventEspresso\core\services\assets\Registry'                                                                 => array(
622
+				'EE_Template_Config' => EE_Dependency_Map::load_from_cache,
623
+				'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
624
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache
625
+			),
626
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
627
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
628
+			),
629
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
630
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
631
+			),
632
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
633
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
634
+			),
635
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
636
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
637
+			),
638
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
639
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
640
+			),
641
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
642
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
643
+			),
644
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
645
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
646
+			),
647
+			'EventEspresso\core\services\cache\BasicCacheManager'                        => array(
648
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
649
+			),
650
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                  => array(
651
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
652
+			),
653
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService' => array(
654
+				'EE_Registration_Config'                                  => EE_Dependency_Map::load_from_cache,
655
+				'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
656
+			),
657
+			'EventEspresso\core\domain\values\EmailAddress'                              => array(
658
+				null,
659
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
660
+			),
661
+			'EventEspresso\core\services\orm\ModelFieldFactory' => array(
662
+				'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
663
+			),
664
+			'LEGACY_MODELS'                                                   => array(
665
+				null,
666
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
667
+			),
668
+			'EE_Module_Request_Router' => array(
669
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
670
+			),
671
+			'EE_Registration_Processor' => array(
672
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
673
+			),
674
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' => array(
675
+				null,
676
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
677
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
678
+			),
679
+			'EventEspresso\core\services\licensing\LicenseService' => array(
680
+				'EventEspresso\core\domain\services\pue\Stats' => EE_Dependency_Map::load_from_cache,
681
+				'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache
682
+			),
683 683
 			'EE_Admin_Transactions_List_Table' => array(
684
-                null,
685
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
686
-			),
687
-            'EventEspresso\core\domain\services\pue\Stats' => array(
688
-                'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
689
-                'EE_Maintenance_Mode' => EE_Dependency_Map::load_from_cache,
690
-                'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache
691
-            ),
692
-            'EventEspresso\core\domain\services\pue\Config' => array(
693
-                'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
694
-                'EE_Config' => EE_Dependency_Map::load_from_cache
695
-            ),
696
-            'EventEspresso\core\domain\services\pue\StatsGatherer' => array(
697
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
698
-                'EEM_Event' => EE_Dependency_Map::load_from_cache,
699
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
700
-                'EEM_Ticket' => EE_Dependency_Map::load_from_cache,
701
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache,
702
-                'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
703
-                'EE_Config' => EE_Dependency_Map::load_from_cache
704
-            )
705
-        );
706
-    }
707
-
708
-
709
-
710
-    /**
711
-     * Registers how core classes are loaded.
712
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
713
-     *        'EE_Request_Handler' => 'load_core'
714
-     *        'EE_Messages_Queue'  => 'load_lib'
715
-     *        'EEH_Debug_Tools'    => 'load_helper'
716
-     * or, if greater control is required, by providing a custom closure. For example:
717
-     *        'Some_Class' => function () {
718
-     *            return new Some_Class();
719
-     *        },
720
-     * This is required for instantiating dependencies
721
-     * where an interface has been type hinted in a class constructor. For example:
722
-     *        'Required_Interface' => function () {
723
-     *            return new A_Class_That_Implements_Required_Interface();
724
-     *        },
725
-     *
726
-     * @throws InvalidInterfaceException
727
-     * @throws InvalidDataTypeException
728
-     * @throws InvalidArgumentException
729
-     */
730
-    protected function _register_core_class_loaders()
731
-    {
732
-        //for PHP5.3 compat, we need to register any properties called here in a variable because `$this` cannot
733
-        //be used in a closure.
734
-        $request = &$this->request;
735
-        $response = &$this->response;
736
-        $legacy_request = &$this->legacy_request;
737
-        // $loader = &$this->loader;
738
-        $this->_class_loaders = array(
739
-            //load_core
740
-            'EE_Capabilities'          => 'load_core',
741
-            'EE_Encryption'            => 'load_core',
742
-            'EE_Front_Controller'      => 'load_core',
743
-            'EE_Module_Request_Router' => 'load_core',
744
-            'EE_Registry'              => 'load_core',
745
-            'EE_Request'               => function () use (&$legacy_request) {
746
-                return $legacy_request;
747
-            },
748
-            'EventEspresso\core\services\request\Request' => function () use (&$request) {
749
-                return $request;
750
-            },
751
-            'EventEspresso\core\services\request\Response' => function () use (&$response) {
752
-                return $response;
753
-            },
754
-            'EE_Request_Handler'       => 'load_core',
755
-            'EE_Session'               => 'load_core',
756
-            'EE_Cron_Tasks'            => 'load_core',
757
-            'EE_System'                => 'load_core',
758
-            'EE_Maintenance_Mode'      => 'load_core',
759
-            'EE_Register_CPTs'         => 'load_core',
760
-            'EE_Admin'                 => 'load_core',
761
-            //load_lib
762
-            'EE_Message_Resource_Manager'          => 'load_lib',
763
-            'EE_Message_Type_Collection'           => 'load_lib',
764
-            'EE_Message_Type_Collection_Loader'    => 'load_lib',
765
-            'EE_Messenger_Collection'              => 'load_lib',
766
-            'EE_Messenger_Collection_Loader'       => 'load_lib',
767
-            'EE_Messages_Processor'                => 'load_lib',
768
-            'EE_Message_Repository'                => 'load_lib',
769
-            'EE_Messages_Queue'                    => 'load_lib',
770
-            'EE_Messages_Data_Handler_Collection'  => 'load_lib',
771
-            'EE_Message_Template_Group_Collection' => 'load_lib',
772
-            'EE_Payment_Method_Manager'            => 'load_lib',
773
-            'EE_Messages_Generator'                => function () {
774
-                return EE_Registry::instance()->load_lib(
775
-                    'Messages_Generator',
776
-                    array(),
777
-                    false,
778
-                    false
779
-                );
780
-            },
781
-            'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
782
-                return EE_Registry::instance()->load_lib(
783
-                    'Messages_Template_Defaults',
784
-                    $arguments,
785
-                    false,
786
-                    false
787
-                );
788
-            },
789
-            //load_helper
790
-            'EEH_Parse_Shortcodes'                 => function () {
791
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
792
-                    return new EEH_Parse_Shortcodes();
793
-                }
794
-                return null;
795
-            },
796
-            'EE_Template_Config'                   => function () {
797
-                return EE_Config::instance()->template_settings;
798
-            },
799
-            'EE_Currency_Config'                   => function () {
800
-                return EE_Config::instance()->currency;
801
-            },
802
-            'EE_Registration_Config'                   => function () {
803
-                return EE_Config::instance()->registration;
804
-            },
805
-            'EventEspresso\core\services\loaders\Loader' => function () {
806
-                return LoaderFactory::getLoader();
807
-            },
808
-            'EE_Network_Config' => function() {
809
-                return EE_Network_Config::instance();
810
-            },
811
-            'EE_Config' => function () {
812
-                return EE_Config::instance();
813
-            }
814
-        );
815
-    }
816
-
817
-
818
-
819
-    /**
820
-     * can be used for supplying alternate names for classes,
821
-     * or for connecting interface names to instantiable classes
822
-     */
823
-    protected function _register_core_aliases()
824
-    {
825
-        $this->_aliases = array(
826
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
827
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
828
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
829
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
830
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
831
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
832
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
833
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
834
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
835
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
836
-            'CreateRegCodeCommandHandler'                                                  => 'EventEspresso\core\services\commands\registration\CreateRegCodeCommand',
837
-            'CreateRegUrlLinkCommandHandler'                                               => 'EventEspresso\core\services\commands\registration\CreateRegUrlLinkCommand',
838
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
839
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
840
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
841
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
842
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
843
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
844
-            'CreateTransactionCommandHandler'                                     => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
845
-            'CreateAttendeeCommandHandler'                                        => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
846
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
847
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
848
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
849
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
850
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
851
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
852
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
853
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
854
-            'CommandFactoryInterface'                                                     => 'EventEspresso\core\services\commands\CommandFactoryInterface',
855
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                => 'EventEspresso\core\services\commands\CommandFactory',
856
-            'EventEspresso\core\domain\services\session\SessionIdentifierInterface'       => 'EE_Session',
857
-            'EmailValidatorInterface'                                                     => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
858
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface' => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
859
-            'NoticeConverterInterface'                                            => 'EventEspresso\core\services\notices\NoticeConverterInterface',
860
-            'EventEspresso\core\services\notices\NoticeConverterInterface'        => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
861
-            'NoticesContainerInterface'                                           => 'EventEspresso\core\services\notices\NoticesContainerInterface',
862
-            'EventEspresso\core\services\notices\NoticesContainerInterface'       => 'EventEspresso\core\services\notices\NoticesContainer',
863
-            'EventEspresso\core\services\request\RequestInterface'                => 'EventEspresso\core\services\request\Request',
864
-            'EventEspresso\core\services\request\ResponseInterface'               => 'EventEspresso\core\services\request\Response',
865
-            'EventEspresso\core\domain\DomainInterface'                           => 'EventEspresso\core\domain\Domain',
866
-        );
867
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
868
-            $this->_aliases['EventEspresso\core\services\notices\NoticeConverterInterface'] = 'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices';
869
-        }
870
-    }
871
-
872
-
873
-
874
-    /**
875
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
876
-     * request Primarily used by unit tests.
877
-     *
878
-     * @throws InvalidDataTypeException
879
-     * @throws InvalidInterfaceException
880
-     * @throws InvalidArgumentException
881
-     */
882
-    public function reset()
883
-    {
884
-        $this->_register_core_class_loaders();
885
-        $this->_register_core_dependencies();
886
-    }
684
+				null,
685
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
686
+			),
687
+			'EventEspresso\core\domain\services\pue\Stats' => array(
688
+				'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
689
+				'EE_Maintenance_Mode' => EE_Dependency_Map::load_from_cache,
690
+				'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache
691
+			),
692
+			'EventEspresso\core\domain\services\pue\Config' => array(
693
+				'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
694
+				'EE_Config' => EE_Dependency_Map::load_from_cache
695
+			),
696
+			'EventEspresso\core\domain\services\pue\StatsGatherer' => array(
697
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
698
+				'EEM_Event' => EE_Dependency_Map::load_from_cache,
699
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
700
+				'EEM_Ticket' => EE_Dependency_Map::load_from_cache,
701
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache,
702
+				'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
703
+				'EE_Config' => EE_Dependency_Map::load_from_cache
704
+			)
705
+		);
706
+	}
707
+
708
+
709
+
710
+	/**
711
+	 * Registers how core classes are loaded.
712
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
713
+	 *        'EE_Request_Handler' => 'load_core'
714
+	 *        'EE_Messages_Queue'  => 'load_lib'
715
+	 *        'EEH_Debug_Tools'    => 'load_helper'
716
+	 * or, if greater control is required, by providing a custom closure. For example:
717
+	 *        'Some_Class' => function () {
718
+	 *            return new Some_Class();
719
+	 *        },
720
+	 * This is required for instantiating dependencies
721
+	 * where an interface has been type hinted in a class constructor. For example:
722
+	 *        'Required_Interface' => function () {
723
+	 *            return new A_Class_That_Implements_Required_Interface();
724
+	 *        },
725
+	 *
726
+	 * @throws InvalidInterfaceException
727
+	 * @throws InvalidDataTypeException
728
+	 * @throws InvalidArgumentException
729
+	 */
730
+	protected function _register_core_class_loaders()
731
+	{
732
+		//for PHP5.3 compat, we need to register any properties called here in a variable because `$this` cannot
733
+		//be used in a closure.
734
+		$request = &$this->request;
735
+		$response = &$this->response;
736
+		$legacy_request = &$this->legacy_request;
737
+		// $loader = &$this->loader;
738
+		$this->_class_loaders = array(
739
+			//load_core
740
+			'EE_Capabilities'          => 'load_core',
741
+			'EE_Encryption'            => 'load_core',
742
+			'EE_Front_Controller'      => 'load_core',
743
+			'EE_Module_Request_Router' => 'load_core',
744
+			'EE_Registry'              => 'load_core',
745
+			'EE_Request'               => function () use (&$legacy_request) {
746
+				return $legacy_request;
747
+			},
748
+			'EventEspresso\core\services\request\Request' => function () use (&$request) {
749
+				return $request;
750
+			},
751
+			'EventEspresso\core\services\request\Response' => function () use (&$response) {
752
+				return $response;
753
+			},
754
+			'EE_Request_Handler'       => 'load_core',
755
+			'EE_Session'               => 'load_core',
756
+			'EE_Cron_Tasks'            => 'load_core',
757
+			'EE_System'                => 'load_core',
758
+			'EE_Maintenance_Mode'      => 'load_core',
759
+			'EE_Register_CPTs'         => 'load_core',
760
+			'EE_Admin'                 => 'load_core',
761
+			//load_lib
762
+			'EE_Message_Resource_Manager'          => 'load_lib',
763
+			'EE_Message_Type_Collection'           => 'load_lib',
764
+			'EE_Message_Type_Collection_Loader'    => 'load_lib',
765
+			'EE_Messenger_Collection'              => 'load_lib',
766
+			'EE_Messenger_Collection_Loader'       => 'load_lib',
767
+			'EE_Messages_Processor'                => 'load_lib',
768
+			'EE_Message_Repository'                => 'load_lib',
769
+			'EE_Messages_Queue'                    => 'load_lib',
770
+			'EE_Messages_Data_Handler_Collection'  => 'load_lib',
771
+			'EE_Message_Template_Group_Collection' => 'load_lib',
772
+			'EE_Payment_Method_Manager'            => 'load_lib',
773
+			'EE_Messages_Generator'                => function () {
774
+				return EE_Registry::instance()->load_lib(
775
+					'Messages_Generator',
776
+					array(),
777
+					false,
778
+					false
779
+				);
780
+			},
781
+			'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
782
+				return EE_Registry::instance()->load_lib(
783
+					'Messages_Template_Defaults',
784
+					$arguments,
785
+					false,
786
+					false
787
+				);
788
+			},
789
+			//load_helper
790
+			'EEH_Parse_Shortcodes'                 => function () {
791
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
792
+					return new EEH_Parse_Shortcodes();
793
+				}
794
+				return null;
795
+			},
796
+			'EE_Template_Config'                   => function () {
797
+				return EE_Config::instance()->template_settings;
798
+			},
799
+			'EE_Currency_Config'                   => function () {
800
+				return EE_Config::instance()->currency;
801
+			},
802
+			'EE_Registration_Config'                   => function () {
803
+				return EE_Config::instance()->registration;
804
+			},
805
+			'EventEspresso\core\services\loaders\Loader' => function () {
806
+				return LoaderFactory::getLoader();
807
+			},
808
+			'EE_Network_Config' => function() {
809
+				return EE_Network_Config::instance();
810
+			},
811
+			'EE_Config' => function () {
812
+				return EE_Config::instance();
813
+			}
814
+		);
815
+	}
816
+
817
+
818
+
819
+	/**
820
+	 * can be used for supplying alternate names for classes,
821
+	 * or for connecting interface names to instantiable classes
822
+	 */
823
+	protected function _register_core_aliases()
824
+	{
825
+		$this->_aliases = array(
826
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
827
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
828
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
829
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
830
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
831
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
832
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
833
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
834
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
835
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
836
+			'CreateRegCodeCommandHandler'                                                  => 'EventEspresso\core\services\commands\registration\CreateRegCodeCommand',
837
+			'CreateRegUrlLinkCommandHandler'                                               => 'EventEspresso\core\services\commands\registration\CreateRegUrlLinkCommand',
838
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
839
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
840
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
841
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
842
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
843
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
844
+			'CreateTransactionCommandHandler'                                     => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
845
+			'CreateAttendeeCommandHandler'                                        => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
846
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
847
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
848
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
849
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
850
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
851
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
852
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
853
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
854
+			'CommandFactoryInterface'                                                     => 'EventEspresso\core\services\commands\CommandFactoryInterface',
855
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                => 'EventEspresso\core\services\commands\CommandFactory',
856
+			'EventEspresso\core\domain\services\session\SessionIdentifierInterface'       => 'EE_Session',
857
+			'EmailValidatorInterface'                                                     => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
858
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface' => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
859
+			'NoticeConverterInterface'                                            => 'EventEspresso\core\services\notices\NoticeConverterInterface',
860
+			'EventEspresso\core\services\notices\NoticeConverterInterface'        => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
861
+			'NoticesContainerInterface'                                           => 'EventEspresso\core\services\notices\NoticesContainerInterface',
862
+			'EventEspresso\core\services\notices\NoticesContainerInterface'       => 'EventEspresso\core\services\notices\NoticesContainer',
863
+			'EventEspresso\core\services\request\RequestInterface'                => 'EventEspresso\core\services\request\Request',
864
+			'EventEspresso\core\services\request\ResponseInterface'               => 'EventEspresso\core\services\request\Response',
865
+			'EventEspresso\core\domain\DomainInterface'                           => 'EventEspresso\core\domain\Domain',
866
+		);
867
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
868
+			$this->_aliases['EventEspresso\core\services\notices\NoticeConverterInterface'] = 'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices';
869
+		}
870
+	}
871
+
872
+
873
+
874
+	/**
875
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
876
+	 * request Primarily used by unit tests.
877
+	 *
878
+	 * @throws InvalidDataTypeException
879
+	 * @throws InvalidInterfaceException
880
+	 * @throws InvalidArgumentException
881
+	 */
882
+	public function reset()
883
+	{
884
+		$this->_register_core_class_loaders();
885
+		$this->_register_core_dependencies();
886
+	}
887 887
 
888 888
 
889 889
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
 use EventEspresso\core\services\request\RequestInterface;
8 8
 use EventEspresso\core\services\request\ResponseInterface;
9 9
 
10
-if (! defined('EVENT_ESPRESSO_VERSION')) {
10
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
11 11
     exit('No direct script access allowed');
12 12
 }
13 13
 
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
      */
130 130
     public static function instance() {
131 131
         // check if class object is instantiated, and instantiated properly
132
-        if (! self::$_instance instanceof EE_Dependency_Map) {
132
+        if ( ! self::$_instance instanceof EE_Dependency_Map) {
133 133
             self::$_instance = new EE_Dependency_Map(/*$request, $response, $legacy_request*/);
134 134
         }
135 135
         return self::$_instance;
@@ -211,8 +211,8 @@  discard block
 block discarded – undo
211 211
     ) {
212 212
         $class = trim($class, '\\');
213 213
         $registered = false;
214
-        if (empty(self::$_instance->_dependency_map[ $class ])) {
215
-            self::$_instance->_dependency_map[ $class ] = array();
214
+        if (empty(self::$_instance->_dependency_map[$class])) {
215
+            self::$_instance->_dependency_map[$class] = array();
216 216
         }
217 217
         // we need to make sure that any aliases used when registering a dependency
218 218
         // get resolved to the correct class name
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
             $alias = self::$_instance->get_alias($dependency);
221 221
             if (
222 222
                 $overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
223
-                || ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
223
+                || ! isset(self::$_instance->_dependency_map[$class][$alias])
224 224
             ) {
225 225
                 unset($dependencies[$dependency]);
226 226
                 $dependencies[$alias] = $load_source;
@@ -233,13 +233,13 @@  discard block
 block discarded – undo
233 233
         // ie: with A = B + C, entries in B take precedence over duplicate entries in C
234 234
         // Union is way faster than array_merge() but should be used with caution...
235 235
         // especially with numerically indexed arrays
236
-        $dependencies += self::$_instance->_dependency_map[ $class ];
236
+        $dependencies += self::$_instance->_dependency_map[$class];
237 237
         // now we need to ensure that the resulting dependencies
238 238
         // array only has the entries that are required for the class
239 239
         // so first count how many dependencies were originally registered for the class
240
-        $dependency_count = count(self::$_instance->_dependency_map[ $class ]);
240
+        $dependency_count = count(self::$_instance->_dependency_map[$class]);
241 241
         // if that count is non-zero (meaning dependencies were already registered)
242
-        self::$_instance->_dependency_map[ $class ] = $dependency_count
242
+        self::$_instance->_dependency_map[$class] = $dependency_count
243 243
             // then truncate the  final array to match that count
244 244
             ? array_slice($dependencies, 0, $dependency_count)
245 245
             // otherwise just take the incoming array because nothing previously existed
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
      */
258 258
     public static function register_class_loader($class_name, $loader = 'load_core')
259 259
     {
260
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
260
+        if ( ! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
261 261
             throw new DomainException(
262 262
                 esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
263 263
             );
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
             );
282 282
         }
283 283
         $class_name = self::$_instance->get_alias($class_name);
284
-        if (! isset(self::$_instance->_class_loaders[$class_name])) {
284
+        if ( ! isset(self::$_instance->_class_loaders[$class_name])) {
285 285
             self::$_instance->_class_loaders[$class_name] = $loader;
286 286
             return true;
287 287
         }
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
     public function class_loader($class_name)
367 367
     {
368 368
         // all legacy models use load_model()
369
-        if(strpos($class_name, 'EEM_') === 0){
369
+        if (strpos($class_name, 'EEM_') === 0) {
370 370
             return 'load_model';
371 371
         }
372 372
         $class_name = $this->get_alias($class_name);
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
     public function add_alias($class_name, $alias, $for_class = '')
396 396
     {
397 397
         if ($for_class !== '') {
398
-            if (! isset($this->_aliases[$for_class])) {
398
+            if ( ! isset($this->_aliases[$for_class])) {
399 399
                 $this->_aliases[$for_class] = array();
400 400
             }
401 401
             $this->_aliases[$for_class][$class_name] = $alias;
@@ -441,10 +441,10 @@  discard block
 block discarded – undo
441 441
      */
442 442
     public function get_alias($class_name = '', $for_class = '')
443 443
     {
444
-        if (! $this->has_alias($class_name, $for_class)) {
444
+        if ( ! $this->has_alias($class_name, $for_class)) {
445 445
             return $class_name;
446 446
         }
447
-        if ($for_class !== '' && isset($this->_aliases[ $for_class ][ $class_name ])) {
447
+        if ($for_class !== '' && isset($this->_aliases[$for_class][$class_name])) {
448 448
             return $this->get_alias($this->_aliases[$for_class][$class_name], $for_class);
449 449
         }
450 450
         return $this->get_alias($this->_aliases[$class_name]);
@@ -742,13 +742,13 @@  discard block
 block discarded – undo
742 742
             'EE_Front_Controller'      => 'load_core',
743 743
             'EE_Module_Request_Router' => 'load_core',
744 744
             'EE_Registry'              => 'load_core',
745
-            'EE_Request'               => function () use (&$legacy_request) {
745
+            'EE_Request'               => function() use (&$legacy_request) {
746 746
                 return $legacy_request;
747 747
             },
748
-            'EventEspresso\core\services\request\Request' => function () use (&$request) {
748
+            'EventEspresso\core\services\request\Request' => function() use (&$request) {
749 749
                 return $request;
750 750
             },
751
-            'EventEspresso\core\services\request\Response' => function () use (&$response) {
751
+            'EventEspresso\core\services\request\Response' => function() use (&$response) {
752 752
                 return $response;
753 753
             },
754 754
             'EE_Request_Handler'       => 'load_core',
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
             'EE_Messages_Data_Handler_Collection'  => 'load_lib',
771 771
             'EE_Message_Template_Group_Collection' => 'load_lib',
772 772
             'EE_Payment_Method_Manager'            => 'load_lib',
773
-            'EE_Messages_Generator'                => function () {
773
+            'EE_Messages_Generator'                => function() {
774 774
                 return EE_Registry::instance()->load_lib(
775 775
                     'Messages_Generator',
776 776
                     array(),
@@ -778,7 +778,7 @@  discard block
 block discarded – undo
778 778
                     false
779 779
                 );
780 780
             },
781
-            'EE_Messages_Template_Defaults'        => function ($arguments = array()) {
781
+            'EE_Messages_Template_Defaults'        => function($arguments = array()) {
782 782
                 return EE_Registry::instance()->load_lib(
783 783
                     'Messages_Template_Defaults',
784 784
                     $arguments,
@@ -787,28 +787,28 @@  discard block
 block discarded – undo
787 787
                 );
788 788
             },
789 789
             //load_helper
790
-            'EEH_Parse_Shortcodes'                 => function () {
790
+            'EEH_Parse_Shortcodes'                 => function() {
791 791
                 if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
792 792
                     return new EEH_Parse_Shortcodes();
793 793
                 }
794 794
                 return null;
795 795
             },
796
-            'EE_Template_Config'                   => function () {
796
+            'EE_Template_Config'                   => function() {
797 797
                 return EE_Config::instance()->template_settings;
798 798
             },
799
-            'EE_Currency_Config'                   => function () {
799
+            'EE_Currency_Config'                   => function() {
800 800
                 return EE_Config::instance()->currency;
801 801
             },
802
-            'EE_Registration_Config'                   => function () {
802
+            'EE_Registration_Config'                   => function() {
803 803
                 return EE_Config::instance()->registration;
804 804
             },
805
-            'EventEspresso\core\services\loaders\Loader' => function () {
805
+            'EventEspresso\core\services\loaders\Loader' => function() {
806 806
                 return LoaderFactory::getLoader();
807 807
             },
808 808
             'EE_Network_Config' => function() {
809 809
                 return EE_Network_Config::instance();
810 810
             },
811
-            'EE_Config' => function () {
811
+            'EE_Config' => function() {
812 812
                 return EE_Config::instance();
813 813
             }
814 814
         );
@@ -864,7 +864,7 @@  discard block
 block discarded – undo
864 864
             'EventEspresso\core\services\request\ResponseInterface'               => 'EventEspresso\core\services\request\Response',
865 865
             'EventEspresso\core\domain\DomainInterface'                           => 'EventEspresso\core\domain\Domain',
866 866
         );
867
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
867
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
868 868
             $this->_aliases['EventEspresso\core\services\notices\NoticeConverterInterface'] = 'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices';
869 869
         }
870 870
     }
Please login to merge, or discard this patch.