Completed
Branch ENH/mobile-browser-state-optio... (1db822)
by
unknown
27:33 queued 18:43
created
libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php 1 patch
Indentation   +557 added lines, -557 removed lines patch added patch discarded remove patch
@@ -20,585 +20,585 @@
 block discarded – undo
20 20
 class EE_Messages_Preview_incoming_data extends EE_Messages_incoming_data
21 21
 {
22 22
     
23
-    // some specific properties we need for this class
24
-    private $_events = array();
25
-    private $_attendees = array();
26
-    private $_registrations = array();
23
+	// some specific properties we need for this class
24
+	private $_events = array();
25
+	private $_attendees = array();
26
+	private $_registrations = array();
27 27
     
28 28
     
29
-    /**
30
-     * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
31
-     * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
32
-     * we'll get the first three published events from the users database and use that as a source.
33
-     *
34
-     * @param array $data
35
-     */
36
-    public function __construct($data = array())
37
-    {
38
-        $this->_data = isset($data['event_ids']) ? $data['event_ids'] : array();
39
-        $this->_setup_attendees_events();
40
-        parent::__construct($data);
41
-    }
29
+	/**
30
+	 * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
31
+	 * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
32
+	 * we'll get the first three published events from the users database and use that as a source.
33
+	 *
34
+	 * @param array $data
35
+	 */
36
+	public function __construct($data = array())
37
+	{
38
+		$this->_data = isset($data['event_ids']) ? $data['event_ids'] : array();
39
+		$this->_setup_attendees_events();
40
+		parent::__construct($data);
41
+	}
42 42
     
43 43
     
44
-    /**
45
-     * Returns database safe representation of the data later used to when instantiating this object.
46
-     *
47
-     * @param array $data The incoming data to be prepped.
48
-     *
49
-     * @return array   The prepped data for db
50
-     */
51
-    public static function convert_data_for_persistent_storage($data)
52
-    {
53
-        return $data;
54
-    }
44
+	/**
45
+	 * Returns database safe representation of the data later used to when instantiating this object.
46
+	 *
47
+	 * @param array $data The incoming data to be prepped.
48
+	 *
49
+	 * @return array   The prepped data for db
50
+	 */
51
+	public static function convert_data_for_persistent_storage($data)
52
+	{
53
+		return $data;
54
+	}
55 55
     
56 56
     
57
-    /**
58
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
59
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
60
-     *
61
-     * @param array $data
62
-     *
63
-     * @return array
64
-     */
65
-    public static function convert_data_from_persistent_storage($data)
66
-    {
67
-        return $data;
68
-    }
57
+	/**
58
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
59
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
60
+	 *
61
+	 * @param array $data
62
+	 *
63
+	 * @return array
64
+	 */
65
+	public static function convert_data_from_persistent_storage($data)
66
+	{
67
+		return $data;
68
+	}
69 69
     
70 70
     
71
-    /**
72
-     * This will just setup the _events property in the expected format.
73
-     *
74
-     * @throws \EE_Error
75
-     */
76
-    private function _setup_attendees_events()
77
-    {
78
-        
79
-        // setup some attendee objects
80
-        $attendees = $this->_get_some_attendees();
81
-        
82
-        // if empty $data we'll do a query to get some events from the server. otherwise we'll retrieve the event data for the given ids.
83
-        $events = $this->_get_some_events($this->_data);
84
-        
85
-        $answers_n_questions = $this->_get_some_q_and_as();
86
-        
87
-        if (count($events) < 1) {
88
-            throw new EE_Error(__(
89
-                'We can\'t generate a preview for you because there are no active events in your database',
90
-                'event_espresso'
91
-            ));
92
-        }
93
-        
94
-        
95
-        // now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
96
-        
97
-        
98
-        // we'll actually use the generated line_item identifiers for our loop
99
-        $dtts = $tkts = array();
100
-        foreach ($events as $id => $event) {
101
-            if (! $event instanceof EE_Event) {
102
-                continue;
103
-            }
104
-            $this->_events[ $id ]['ID']       = $id;
105
-            $this->_events[ $id ]['name']     = $event->get('EVT_name');
106
-            $datetime                       = $event->get_first_related('Datetime');
107
-            $tickets                        = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
108
-                'Ticket',
109
-                array('default_where_conditions' => 'none')
110
-            ) : array();
111
-            $this->_events[ $id ]['event']    = $event;
112
-            $this->_events[ $id ]['reg_objs'] = array();
113
-            $this->_events[ $id ]['tkt_objs'] = $tickets;
114
-            $this->_events[ $id ]['dtt_objs'] = array();
71
+	/**
72
+	 * This will just setup the _events property in the expected format.
73
+	 *
74
+	 * @throws \EE_Error
75
+	 */
76
+	private function _setup_attendees_events()
77
+	{
78
+        
79
+		// setup some attendee objects
80
+		$attendees = $this->_get_some_attendees();
81
+        
82
+		// if empty $data we'll do a query to get some events from the server. otherwise we'll retrieve the event data for the given ids.
83
+		$events = $this->_get_some_events($this->_data);
84
+        
85
+		$answers_n_questions = $this->_get_some_q_and_as();
86
+        
87
+		if (count($events) < 1) {
88
+			throw new EE_Error(__(
89
+				'We can\'t generate a preview for you because there are no active events in your database',
90
+				'event_espresso'
91
+			));
92
+		}
93
+        
94
+        
95
+		// now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
96
+        
97
+        
98
+		// we'll actually use the generated line_item identifiers for our loop
99
+		$dtts = $tkts = array();
100
+		foreach ($events as $id => $event) {
101
+			if (! $event instanceof EE_Event) {
102
+				continue;
103
+			}
104
+			$this->_events[ $id ]['ID']       = $id;
105
+			$this->_events[ $id ]['name']     = $event->get('EVT_name');
106
+			$datetime                       = $event->get_first_related('Datetime');
107
+			$tickets                        = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
108
+				'Ticket',
109
+				array('default_where_conditions' => 'none')
110
+			) : array();
111
+			$this->_events[ $id ]['event']    = $event;
112
+			$this->_events[ $id ]['reg_objs'] = array();
113
+			$this->_events[ $id ]['tkt_objs'] = $tickets;
114
+			$this->_events[ $id ]['dtt_objs'] = array();
115 115
             
116
-            $dttcache = array();
117
-            $tkts     = array();
118
-            foreach ($tickets as $ticket) {
119
-                if (! $ticket instanceof EE_Ticket) {
120
-                    continue;
121
-                }
122
-                $reldatetime                     = $ticket->datetimes();
123
-                $tkts[ $ticket->ID() ]             = array();
124
-                $tkts[ $ticket->ID() ]['ticket']   = $ticket;
125
-                $tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
126
-                $tkts[ $ticket->ID() ]['att_objs'] = $attendees;
127
-                $tkts[ $ticket->ID() ]['count']    = count($attendees);
128
-                $tkts[ $ticket->ID() ]['EE_Event'] = $event;
129
-                foreach ($reldatetime as $datetime) {
130
-                    if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
131
-                        $this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
132
-                        $dtts[ $datetime->ID() ]['datetime']               = $datetime;
133
-                        $dtts[ $datetime->ID() ]['tkt_objs'][]             = $ticket;
134
-                        $dtts[ $datetime->ID() ]['evt_objs'][]             = $event;
135
-                        $dttcache[ $datetime->ID() ]                       = $datetime;
136
-                    }
137
-                }
138
-            }
116
+			$dttcache = array();
117
+			$tkts     = array();
118
+			foreach ($tickets as $ticket) {
119
+				if (! $ticket instanceof EE_Ticket) {
120
+					continue;
121
+				}
122
+				$reldatetime                     = $ticket->datetimes();
123
+				$tkts[ $ticket->ID() ]             = array();
124
+				$tkts[ $ticket->ID() ]['ticket']   = $ticket;
125
+				$tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
126
+				$tkts[ $ticket->ID() ]['att_objs'] = $attendees;
127
+				$tkts[ $ticket->ID() ]['count']    = count($attendees);
128
+				$tkts[ $ticket->ID() ]['EE_Event'] = $event;
129
+				foreach ($reldatetime as $datetime) {
130
+					if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
131
+						$this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
132
+						$dtts[ $datetime->ID() ]['datetime']               = $datetime;
133
+						$dtts[ $datetime->ID() ]['tkt_objs'][]             = $ticket;
134
+						$dtts[ $datetime->ID() ]['evt_objs'][]             = $event;
135
+						$dttcache[ $datetime->ID() ]                       = $datetime;
136
+					}
137
+				}
138
+			}
139 139
             
140
-            $this->_events[ $id ]['total_attendees'] = count($attendees);
141
-            $this->_events[ $id ]['att_objs']        = $attendees;
140
+			$this->_events[ $id ]['total_attendees'] = count($attendees);
141
+			$this->_events[ $id ]['att_objs']        = $attendees;
142 142
             
143
-            // let's also setup the dummy attendees property!
144
-            foreach ($attendees as $att_key => $attendee) {
145
-                if (! $attendee instanceof EE_Attendee) {
146
-                    continue;
147
-                }
148
-                $this->_attendees[ $att_key ]['line_ref'][] = $id;  // so later it can be determined what events this attendee registered for!
149
-                $this->_attendees[ $att_key ]['evt_objs'][] = $event;
150
-                $this->_attendees[ $att_key ]['att_obj']    = $attendee;
151
-                // $this->_attendees[$att_key]['registration_id'] = 0;
152
-                $this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
153
-                $this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
154
-                if ($att_key == 999999991) {
155
-                    $this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
156
-                    $this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
157
-                    $this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
158
-                } elseif ($att_key == 999999992) {
159
-                    $this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
160
-                    $this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
161
-                    $this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
162
-                } elseif ($att_key == 999999993) {
163
-                    $this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
164
-                    $this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
165
-                    $this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
166
-                }
167
-            }
168
-        }
169
-        
170
-        $this->tickets            = $tkts;
171
-        $this->datetimes          = $dtts;
172
-        $this->answers            = $answers_n_questions['answers'];
173
-        $this->questions          = $answers_n_questions['questions'];
174
-        $this->total_ticket_count = count($tkts) * count($this->_attendees);
175
-    }
143
+			// let's also setup the dummy attendees property!
144
+			foreach ($attendees as $att_key => $attendee) {
145
+				if (! $attendee instanceof EE_Attendee) {
146
+					continue;
147
+				}
148
+				$this->_attendees[ $att_key ]['line_ref'][] = $id;  // so later it can be determined what events this attendee registered for!
149
+				$this->_attendees[ $att_key ]['evt_objs'][] = $event;
150
+				$this->_attendees[ $att_key ]['att_obj']    = $attendee;
151
+				// $this->_attendees[$att_key]['registration_id'] = 0;
152
+				$this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
153
+				$this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
154
+				if ($att_key == 999999991) {
155
+					$this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
156
+					$this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
157
+					$this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
158
+				} elseif ($att_key == 999999992) {
159
+					$this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
160
+					$this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
161
+					$this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
162
+				} elseif ($att_key == 999999993) {
163
+					$this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
164
+					$this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
165
+					$this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
166
+				}
167
+			}
168
+		}
169
+        
170
+		$this->tickets            = $tkts;
171
+		$this->datetimes          = $dtts;
172
+		$this->answers            = $answers_n_questions['answers'];
173
+		$this->questions          = $answers_n_questions['questions'];
174
+		$this->total_ticket_count = count($tkts) * count($this->_attendees);
175
+	}
176 176
     
177 177
     
178
-    /**
179
-     * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
180
-     *
181
-     * @access private
182
-     * @return array an array of attendee objects
183
-     */
184
-    private function _get_some_attendees()
185
-    {
186
-        // let's just setup a dummy array of various attendee details
187
-        $dummy_attendees = array(
188
-            0 => array(
189
-                'Luke',
190
-                'Skywalker',
191
-                '[email protected]',
192
-                '804 Bantha Dr.',
193
-                'Complex 8',
194
-                'Mos Eisley',
195
-                32,
196
-                'US',
197
-                'f0r3e',
198
-                '222-333-4763',
199
-                false,
200
-                '999999991'
201
-            ),
202
-            1 => array(
203
-                'Princess',
204
-                'Leia',
205
-                '[email protected]',
206
-                '1456 Valley Way Boulevard',
207
-                'Suite 9',
208
-                'Alderaan',
209
-                15,
210
-                'US',
211
-                'c1h2c',
212
-                '78-123-111-1111',
213
-                false,
214
-                '999999992'
215
-            ),
216
-            2 => array(
217
-                'Yoda',
218
-                'I Am',
219
-                '[email protected]',
220
-                '4th Tree',
221
-                '5th Knot',
222
-                'Marsh',
223
-                22,
224
-                'US',
225
-                'l18n',
226
-                '999-999-9999',
227
-                false,
228
-                '999999993'
229
-            ),
230
-        );
231
-        
232
-        // let's generate the attendee objects
233
-        $attendees = array();
234
-        $var_array = array(
235
-            'fname',
236
-            'lname',
237
-            'email',
238
-            'address',
239
-            'address2',
240
-            'city',
241
-            'staid',
242
-            'cntry',
243
-            'zip',
244
-            'phone',
245
-            'deleted',
246
-            'attid'
247
-        );
248
-        
249
-        // EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
250
-        foreach ($dummy_attendees as $dummy) {
251
-            $att = array_combine($var_array, $dummy);
252
-            extract($att);
253
-            /** @var $fname string */
254
-            /** @var $lname string */
255
-            /** @var $address string */
256
-            /** @var $address2 string */
257
-            /** @var $city string */
258
-            /** @var $staid string */
259
-            /** @var $cntry string */
260
-            /** @var $zip string */
261
-            /** @var $email string */
262
-            /** @var $phone string */
263
-            /** @var $attid string */
264
-            $attendees[ $attid ] = EE_Attendee::new_instance(
265
-                array(
266
-                    'ATT_fname'    => $fname,
267
-                    'ATT_lname'    => $lname,
268
-                    'ATT_address'  => $address,
269
-                    'ATT_address2' => $address2,
270
-                    'ATT_city'     => $city,
271
-                    'STA_ID'       => $staid,
272
-                    'CNT_ISO'      => $cntry,
273
-                    'ATT_zip'      => $zip,
274
-                    'ATT_email'    => $email,
275
-                    'ATT_phone'    => $phone,
276
-                    'ATT_ID'       => $attid
277
-                )
278
-            );
279
-        }
280
-        
281
-        return $attendees;
282
-    }
178
+	/**
179
+	 * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
180
+	 *
181
+	 * @access private
182
+	 * @return array an array of attendee objects
183
+	 */
184
+	private function _get_some_attendees()
185
+	{
186
+		// let's just setup a dummy array of various attendee details
187
+		$dummy_attendees = array(
188
+			0 => array(
189
+				'Luke',
190
+				'Skywalker',
191
+				'[email protected]',
192
+				'804 Bantha Dr.',
193
+				'Complex 8',
194
+				'Mos Eisley',
195
+				32,
196
+				'US',
197
+				'f0r3e',
198
+				'222-333-4763',
199
+				false,
200
+				'999999991'
201
+			),
202
+			1 => array(
203
+				'Princess',
204
+				'Leia',
205
+				'[email protected]',
206
+				'1456 Valley Way Boulevard',
207
+				'Suite 9',
208
+				'Alderaan',
209
+				15,
210
+				'US',
211
+				'c1h2c',
212
+				'78-123-111-1111',
213
+				false,
214
+				'999999992'
215
+			),
216
+			2 => array(
217
+				'Yoda',
218
+				'I Am',
219
+				'[email protected]',
220
+				'4th Tree',
221
+				'5th Knot',
222
+				'Marsh',
223
+				22,
224
+				'US',
225
+				'l18n',
226
+				'999-999-9999',
227
+				false,
228
+				'999999993'
229
+			),
230
+		);
231
+        
232
+		// let's generate the attendee objects
233
+		$attendees = array();
234
+		$var_array = array(
235
+			'fname',
236
+			'lname',
237
+			'email',
238
+			'address',
239
+			'address2',
240
+			'city',
241
+			'staid',
242
+			'cntry',
243
+			'zip',
244
+			'phone',
245
+			'deleted',
246
+			'attid'
247
+		);
248
+        
249
+		// EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
250
+		foreach ($dummy_attendees as $dummy) {
251
+			$att = array_combine($var_array, $dummy);
252
+			extract($att);
253
+			/** @var $fname string */
254
+			/** @var $lname string */
255
+			/** @var $address string */
256
+			/** @var $address2 string */
257
+			/** @var $city string */
258
+			/** @var $staid string */
259
+			/** @var $cntry string */
260
+			/** @var $zip string */
261
+			/** @var $email string */
262
+			/** @var $phone string */
263
+			/** @var $attid string */
264
+			$attendees[ $attid ] = EE_Attendee::new_instance(
265
+				array(
266
+					'ATT_fname'    => $fname,
267
+					'ATT_lname'    => $lname,
268
+					'ATT_address'  => $address,
269
+					'ATT_address2' => $address2,
270
+					'ATT_city'     => $city,
271
+					'STA_ID'       => $staid,
272
+					'CNT_ISO'      => $cntry,
273
+					'ATT_zip'      => $zip,
274
+					'ATT_email'    => $email,
275
+					'ATT_phone'    => $phone,
276
+					'ATT_ID'       => $attid
277
+				)
278
+			);
279
+		}
280
+        
281
+		return $attendees;
282
+	}
283 283
     
284 284
     
285
-    /**
286
-     * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
287
-     * This will be used in our dummy data setup
288
-     * @return array
289
-     */
290
-    private function _get_some_q_and_as()
291
-    {
292
-        
293
-        
294
-        $quests_array = array(
295
-            0 => array(
296
-                555,
297
-                __('What is your favorite planet?', 'event_espresso'),
298
-                0
299
-            ),
300
-            1 => array(
301
-                556,
302
-                __('What is your favorite food?', 'event_espresso'),
303
-                0
304
-            ),
305
-            2 => array(
306
-                557,
307
-                __('How many lightyears have you travelled', 'event_espresso'),
308
-                0
309
-            )
310
-        );
311
-        
312
-        
313
-        $ans_array = array(
314
-            0 => array(
315
-                999,
316
-                555,
317
-                'Tattoine'
318
-            ),
319
-            1 => array(
320
-                1000,
321
-                555,
322
-                'Alderaan'
323
-            ),
324
-            2 => array(
325
-                1001,
326
-                555,
327
-                'Dantooine'
328
-            ),
329
-            3 => array(
330
-                1002,
331
-                556,
332
-                'Fish Fingers'
333
-            ),
334
-            4 => array(
335
-                1003,
336
-                556,
337
-                'Sushi'
338
-            ),
339
-            5 => array(
340
-                1004,
341
-                556,
342
-                'Water'
343
-            ),
344
-            6 => array(
345
-                1005,
346
-                557,
347
-                'A lot',
348
-            ),
349
-            7 => array(
350
-                1006,
351
-                557,
352
-                "That's none of your business."
353
-            ),
354
-            8 => array(
355
-                1007,
356
-                557,
357
-                "People less travel me then."
358
-            )
359
-        );
360
-        
361
-        $qst_columns = array('QST_ID', 'QST_display_text', 'QST_system');
362
-        $ans_columns = array('ANS_ID', 'QST_ID', 'ANS_value');
363
-        
364
-        // EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
365
-        // EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
366
-        
367
-        $qsts = array();
368
-        // first the questions
369
-        foreach ($quests_array as $qst) {
370
-            $qstobj                  = array_combine($qst_columns, $qst);
371
-            $qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
372
-        }
373
-        
374
-        // now the answers (and we'll setup our arrays)
375
-        $q_n_as = array();
376
-        foreach ($ans_array as $ans) {
377
-            $ansobj                             = array_combine($ans_columns, $ans);
378
-            $ansobj                             = EE_Answer::new_instance($ansobj);
379
-            $q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
380
-            $q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
381
-        }
382
-        
383
-        return $q_n_as;
384
-    }
285
+	/**
286
+	 * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
287
+	 * This will be used in our dummy data setup
288
+	 * @return array
289
+	 */
290
+	private function _get_some_q_and_as()
291
+	{
292
+        
293
+        
294
+		$quests_array = array(
295
+			0 => array(
296
+				555,
297
+				__('What is your favorite planet?', 'event_espresso'),
298
+				0
299
+			),
300
+			1 => array(
301
+				556,
302
+				__('What is your favorite food?', 'event_espresso'),
303
+				0
304
+			),
305
+			2 => array(
306
+				557,
307
+				__('How many lightyears have you travelled', 'event_espresso'),
308
+				0
309
+			)
310
+		);
311
+        
312
+        
313
+		$ans_array = array(
314
+			0 => array(
315
+				999,
316
+				555,
317
+				'Tattoine'
318
+			),
319
+			1 => array(
320
+				1000,
321
+				555,
322
+				'Alderaan'
323
+			),
324
+			2 => array(
325
+				1001,
326
+				555,
327
+				'Dantooine'
328
+			),
329
+			3 => array(
330
+				1002,
331
+				556,
332
+				'Fish Fingers'
333
+			),
334
+			4 => array(
335
+				1003,
336
+				556,
337
+				'Sushi'
338
+			),
339
+			5 => array(
340
+				1004,
341
+				556,
342
+				'Water'
343
+			),
344
+			6 => array(
345
+				1005,
346
+				557,
347
+				'A lot',
348
+			),
349
+			7 => array(
350
+				1006,
351
+				557,
352
+				"That's none of your business."
353
+			),
354
+			8 => array(
355
+				1007,
356
+				557,
357
+				"People less travel me then."
358
+			)
359
+		);
360
+        
361
+		$qst_columns = array('QST_ID', 'QST_display_text', 'QST_system');
362
+		$ans_columns = array('ANS_ID', 'QST_ID', 'ANS_value');
363
+        
364
+		// EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
365
+		// EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
366
+        
367
+		$qsts = array();
368
+		// first the questions
369
+		foreach ($quests_array as $qst) {
370
+			$qstobj                  = array_combine($qst_columns, $qst);
371
+			$qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
372
+		}
373
+        
374
+		// now the answers (and we'll setup our arrays)
375
+		$q_n_as = array();
376
+		foreach ($ans_array as $ans) {
377
+			$ansobj                             = array_combine($ans_columns, $ans);
378
+			$ansobj                             = EE_Answer::new_instance($ansobj);
379
+			$q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
380
+			$q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
381
+		}
382
+        
383
+		return $q_n_as;
384
+	}
385 385
     
386 386
     
387
-    /**
388
-     * Return an array of event objects from the database
389
-     *
390
-     * If event ids are not included then we'll just retrieve the first published event from the database.
391
-     *
392
-     * @param  array $event_ids if set, this will be an array of event ids to obtain events for.
393
-     *
394
-     * @return array    An array of event objects from the db.
395
-     */
396
-    private function _get_some_events($event_ids = array())
397
-    {
398
-        
399
-        // HEY, if we have an evt_id then we want to make sure we use that for the preview (because a specific event template is being viewed);
400
-        $event_ids = isset($_REQUEST['evt_id']) && ! empty($_REQUEST['evt_id'])
401
-            ? array($_REQUEST['evt_id'])
402
-            : $event_ids;
403
-        
404
-        $limit = ! empty($event_ids)
405
-            ? null
406
-            : apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
407
-        
408
-        $where = ! empty($event_ids)
409
-            ? array(
410
-                'EVT_ID'                 => array('IN', $event_ids),
411
-                'Datetime.Ticket.TKT_ID' => array('>', 1)
412
-            )
413
-            : array('Datetime.Ticket.TKT_ID' => array('>', 1));
414
-        
415
-        $events = EE_Registry::instance()->load_model('Event')->get_all(array($where, 'limit' => $limit));
416
-        
417
-        return $events;
418
-    }
387
+	/**
388
+	 * Return an array of event objects from the database
389
+	 *
390
+	 * If event ids are not included then we'll just retrieve the first published event from the database.
391
+	 *
392
+	 * @param  array $event_ids if set, this will be an array of event ids to obtain events for.
393
+	 *
394
+	 * @return array    An array of event objects from the db.
395
+	 */
396
+	private function _get_some_events($event_ids = array())
397
+	{
398
+        
399
+		// HEY, if we have an evt_id then we want to make sure we use that for the preview (because a specific event template is being viewed);
400
+		$event_ids = isset($_REQUEST['evt_id']) && ! empty($_REQUEST['evt_id'])
401
+			? array($_REQUEST['evt_id'])
402
+			: $event_ids;
403
+        
404
+		$limit = ! empty($event_ids)
405
+			? null
406
+			: apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
407
+        
408
+		$where = ! empty($event_ids)
409
+			? array(
410
+				'EVT_ID'                 => array('IN', $event_ids),
411
+				'Datetime.Ticket.TKT_ID' => array('>', 1)
412
+			)
413
+			: array('Datetime.Ticket.TKT_ID' => array('>', 1));
414
+        
415
+		$events = EE_Registry::instance()->load_model('Event')->get_all(array($where, 'limit' => $limit));
416
+        
417
+		return $events;
418
+	}
419 419
     
420 420
     
421
-    protected function _setup_data()
422
-    {
423
-        
424
-        // need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
425
-        if (EE_Registry::instance()->SSN instanceof EE_Session) {
426
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
427
-            $session = EE_Registry::instance()->SSN;
428
-        } else {
429
-            $session = EE_Registry::instance()->load_core('Session');
430
-        }
431
-        $cart = EE_Cart::instance(null, $session);
432
-        
433
-        
434
-        // add tickets to cart
435
-        foreach ($this->tickets as $ticket) {
436
-            $cart->add_ticket_to_cart($ticket['ticket']);
437
-        }
438
-        
439
-        
440
-        // setup txn property
441
-        $this->txn = EE_Transaction::new_instance(
442
-            array(
443
-                'TXN_timestamp'    => time(), // unix timestamp
444
-                'TXN_total'        => 0, // txn_total
445
-                'TXN_paid'         => 0, // txn_paid
446
-                'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
447
-                'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
448
-                'TXN_hash_salt'    => null, // hash salt blank as well
449
-                'TXN_ID'           => 999999
450
-            )
451
-        );
452
-        
453
-        
454
-        // setup reg_objects
455
-        // note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
456
-        $this->reg_objs = array();
457
-        $regid          = 9999990;
458
-        foreach ($this->_attendees as $key => $attendee) {
459
-            // note we need to setup reg_objects for each event this attendee belongs to
460
-            $regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
461
-            $regtxn = $this->txn->ID();
462
-            $regcnt = 1;
463
-            foreach ($attendee['line_ref'] as $evtid) {
464
-                foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
465
-                    if (! $ticket instanceof EE_Ticket) {
466
-                        continue;
467
-                    }
468
-                    $reg_array                                        = array(
469
-                        'EVT_ID'           => $evtid,
470
-                        'ATT_ID'           => $regatt,
471
-                        'TXN_ID'           => $regtxn,
472
-                        'TKT_ID'           => $ticket->ID(),
473
-                        'STS_ID'           => EEM_Registration::status_id_pending_payment,
474
-                        'REG_date'         => time(),
475
-                        'REG_final_price'  => $ticket->get('TKT_price'),
476
-                        'REG_session'      => 'dummy_session_id',
477
-                        'REG_code'         => $regid . '-dummy-generated-code',
478
-                        'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
479
-                        'REG_count'        => $regcnt,
480
-                        'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
481
-                        'REG_att_is_going' => true,
482
-                        'REG_ID'           => $regid
483
-                    );
484
-                    $REG_OBJ                                          = EE_Registration::new_instance($reg_array);
485
-                    $this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
486
-                    $this->_events[ $evtid ]['reg_objs'][]              = $REG_OBJ;
487
-                    $this->reg_objs[]                                 = $REG_OBJ;
488
-                    $this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
421
+	protected function _setup_data()
422
+	{
423
+        
424
+		// need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
425
+		if (EE_Registry::instance()->SSN instanceof EE_Session) {
426
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
427
+			$session = EE_Registry::instance()->SSN;
428
+		} else {
429
+			$session = EE_Registry::instance()->load_core('Session');
430
+		}
431
+		$cart = EE_Cart::instance(null, $session);
432
+        
433
+        
434
+		// add tickets to cart
435
+		foreach ($this->tickets as $ticket) {
436
+			$cart->add_ticket_to_cart($ticket['ticket']);
437
+		}
438
+        
439
+        
440
+		// setup txn property
441
+		$this->txn = EE_Transaction::new_instance(
442
+			array(
443
+				'TXN_timestamp'    => time(), // unix timestamp
444
+				'TXN_total'        => 0, // txn_total
445
+				'TXN_paid'         => 0, // txn_paid
446
+				'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
447
+				'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
448
+				'TXN_hash_salt'    => null, // hash salt blank as well
449
+				'TXN_ID'           => 999999
450
+			)
451
+		);
452
+        
453
+        
454
+		// setup reg_objects
455
+		// note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
456
+		$this->reg_objs = array();
457
+		$regid          = 9999990;
458
+		foreach ($this->_attendees as $key => $attendee) {
459
+			// note we need to setup reg_objects for each event this attendee belongs to
460
+			$regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
461
+			$regtxn = $this->txn->ID();
462
+			$regcnt = 1;
463
+			foreach ($attendee['line_ref'] as $evtid) {
464
+				foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
465
+					if (! $ticket instanceof EE_Ticket) {
466
+						continue;
467
+					}
468
+					$reg_array                                        = array(
469
+						'EVT_ID'           => $evtid,
470
+						'ATT_ID'           => $regatt,
471
+						'TXN_ID'           => $regtxn,
472
+						'TKT_ID'           => $ticket->ID(),
473
+						'STS_ID'           => EEM_Registration::status_id_pending_payment,
474
+						'REG_date'         => time(),
475
+						'REG_final_price'  => $ticket->get('TKT_price'),
476
+						'REG_session'      => 'dummy_session_id',
477
+						'REG_code'         => $regid . '-dummy-generated-code',
478
+						'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
479
+						'REG_count'        => $regcnt,
480
+						'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
481
+						'REG_att_is_going' => true,
482
+						'REG_ID'           => $regid
483
+					);
484
+					$REG_OBJ                                          = EE_Registration::new_instance($reg_array);
485
+					$this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
486
+					$this->_events[ $evtid ]['reg_objs'][]              = $REG_OBJ;
487
+					$this->reg_objs[]                                 = $REG_OBJ;
488
+					$this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
489 489
                     
490
-                    $regcnt++;
491
-                    $regid++;
492
-                }
493
-            }
494
-        }
495
-        
496
-        
497
-        // setup line items!
498
-        $line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
499
-        
500
-        // add tickets
501
-        foreach ($this->tickets as $tktid => $item) {
502
-            $qty    = $item['count'];
503
-            $ticket = $item['ticket'];
504
-            EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
505
-        }
506
-        
507
-        $shipping_line_item = EE_Line_Item::new_instance(array(
508
-            'LIN_name'       => __('Shipping Surcharge', 'event_espresso'),
509
-            'LIN_desc'       => __('Sent via Millenium Falcon', 'event_espresso'),
510
-            'LIN_unit_price' => 20,
511
-            'LIN_quantity'   => 1,
512
-            'LIN_is_taxable' => true,
513
-            'LIN_total'      => 20,
514
-            'LIN_type'       => EEM_Line_Item::type_line_item
515
-        ));
516
-        EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
517
-        $this->additional_line_items = array($shipping_line_item);
518
-        
519
-        // now let's add taxes
520
-        EEH_Line_Item::apply_taxes($line_item_total);
521
-        
522
-        // now we should be able to get the items we need from this object
523
-        $event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
524
-        $line_items       = array();
525
-        foreach ($event_line_items as $line_id => $line_item) {
526
-            if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
527
-                continue;
528
-            }
529
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
530
-            foreach ($ticket_line_items as $ticket_line_id => $ticket_line_item) {
531
-                if (! $ticket_line_item instanceof EE_Line_Item) {
532
-                    continue;
533
-                }
534
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
535
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
536
-                $line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
537
-                $line_items[ $ticket_line_item->ID() ]['EE_Ticket']             = $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
538
-            }
539
-        }
540
-        
541
-        $this->line_items_with_children = $line_items;
542
-        $this->tax_line_items           = $line_item_total->tax_descendants();
543
-        
544
-        // add proper total to transaction object.
545
-        $grand_total                 = $line_item_total->recalculate_total_including_taxes();
546
-        $this->grand_total_line_item = $line_item_total;
547
-        $this->txn->set_total($grand_total);
548
-        
549
-        
550
-        // add additional details for each registration
551
-        foreach ($this->reg_objs as $reg) {
552
-            if (! $reg instanceof EE_Registration) {
553
-                continue;
554
-            }
555
-            $this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
556
-            $this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
557
-            $this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
558
-            $this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
559
-            $this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
560
-            $this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
561
-        }
562
-        
563
-        
564
-        // events and attendees
565
-        $this->events        = $this->_events;
566
-        $this->attendees     = $this->_attendees;
567
-        $this->registrations = $this->_registrations;
568
-        
569
-        $attendees_to_shift = $this->_attendees;
570
-        
571
-        // setup primary attendee property
572
-        $this->primary_attendee_data = array(
573
-            'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
574
-                ? $this->_attendees[999999991]['att_obj']->fname()
575
-                : '',
490
+					$regcnt++;
491
+					$regid++;
492
+				}
493
+			}
494
+		}
495
+        
496
+        
497
+		// setup line items!
498
+		$line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
499
+        
500
+		// add tickets
501
+		foreach ($this->tickets as $tktid => $item) {
502
+			$qty    = $item['count'];
503
+			$ticket = $item['ticket'];
504
+			EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
505
+		}
506
+        
507
+		$shipping_line_item = EE_Line_Item::new_instance(array(
508
+			'LIN_name'       => __('Shipping Surcharge', 'event_espresso'),
509
+			'LIN_desc'       => __('Sent via Millenium Falcon', 'event_espresso'),
510
+			'LIN_unit_price' => 20,
511
+			'LIN_quantity'   => 1,
512
+			'LIN_is_taxable' => true,
513
+			'LIN_total'      => 20,
514
+			'LIN_type'       => EEM_Line_Item::type_line_item
515
+		));
516
+		EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
517
+		$this->additional_line_items = array($shipping_line_item);
518
+        
519
+		// now let's add taxes
520
+		EEH_Line_Item::apply_taxes($line_item_total);
521
+        
522
+		// now we should be able to get the items we need from this object
523
+		$event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
524
+		$line_items       = array();
525
+		foreach ($event_line_items as $line_id => $line_item) {
526
+			if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
527
+				continue;
528
+			}
529
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
530
+			foreach ($ticket_line_items as $ticket_line_id => $ticket_line_item) {
531
+				if (! $ticket_line_item instanceof EE_Line_Item) {
532
+					continue;
533
+				}
534
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
535
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
536
+				$line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
537
+				$line_items[ $ticket_line_item->ID() ]['EE_Ticket']             = $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
538
+			}
539
+		}
540
+        
541
+		$this->line_items_with_children = $line_items;
542
+		$this->tax_line_items           = $line_item_total->tax_descendants();
543
+        
544
+		// add proper total to transaction object.
545
+		$grand_total                 = $line_item_total->recalculate_total_including_taxes();
546
+		$this->grand_total_line_item = $line_item_total;
547
+		$this->txn->set_total($grand_total);
548
+        
549
+        
550
+		// add additional details for each registration
551
+		foreach ($this->reg_objs as $reg) {
552
+			if (! $reg instanceof EE_Registration) {
553
+				continue;
554
+			}
555
+			$this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
556
+			$this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
557
+			$this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
558
+			$this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
559
+			$this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
560
+			$this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
561
+		}
562
+        
563
+        
564
+		// events and attendees
565
+		$this->events        = $this->_events;
566
+		$this->attendees     = $this->_attendees;
567
+		$this->registrations = $this->_registrations;
568
+        
569
+		$attendees_to_shift = $this->_attendees;
570
+        
571
+		// setup primary attendee property
572
+		$this->primary_attendee_data = array(
573
+			'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
574
+				? $this->_attendees[999999991]['att_obj']->fname()
575
+				: '',
576 576
             
577
-            'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
578
-                ? $this->_attendees[999999991]['att_obj']->lname()
579
-                : '',
577
+			'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
578
+				? $this->_attendees[999999991]['att_obj']->lname()
579
+				: '',
580 580
             
581
-            'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
582
-                ? $this->_attendees[999999991]['att_obj']->email()
583
-                : '',
581
+			'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
582
+				? $this->_attendees[999999991]['att_obj']->email()
583
+				: '',
584 584
             
585
-            'att_obj' => $this->_attendees[999999991]['att_obj'],
585
+			'att_obj' => $this->_attendees[999999991]['att_obj'],
586 586
             
587
-            'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs'])
588
-        );
589
-        
590
-        // reg_info property
591
-        // note this isn't referenced by any shortcode parsers so we'll ignore for now.
592
-        $this->reg_info = array();
593
-        
594
-        // let's set a reg_obj for messengers expecting one.
595
-        $this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
596
-        
597
-        // the below are just dummy items.
598
-        $this->user_id     = 1;
599
-        $this->ip_address  = '192.0.2.1';
600
-        $this->user_agent  = '';
601
-        $this->init_access = time();
602
-        $this->last_access = time();
603
-    }
587
+			'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs'])
588
+		);
589
+        
590
+		// reg_info property
591
+		// note this isn't referenced by any shortcode parsers so we'll ignore for now.
592
+		$this->reg_info = array();
593
+        
594
+		// let's set a reg_obj for messengers expecting one.
595
+		$this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
596
+        
597
+		// the below are just dummy items.
598
+		$this->user_id     = 1;
599
+		$this->ip_address  = '192.0.2.1';
600
+		$this->user_agent  = '';
601
+		$this->init_access = time();
602
+		$this->last_access = time();
603
+	}
604 604
 }
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 1 patch
Indentation   +1150 added lines, -1150 removed lines patch added patch discarded remove patch
@@ -16,1154 +16,1154 @@
 block discarded – undo
16 16
 class Payments_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * Variables used for when we're re-sorting the logs results, in case
21
-     * we needed to do two queries and we need to resort
22
-     *
23
-     * @var string
24
-     */
25
-    private $_sort_logs_again_direction;
26
-
27
-
28
-    /**
29
-     * @Constructor
30
-     * @access public
31
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
-     * @throws EE_Error
33
-     * @throws InvalidArgumentException
34
-     * @throws InvalidDataTypeException
35
-     * @throws InvalidInterfaceException
36
-     * @throws ReflectionException
37
-     */
38
-    public function __construct($routing = true)
39
-    {
40
-        parent::__construct($routing);
41
-    }
42
-
43
-
44
-    protected function _init_page_props()
45
-    {
46
-        $this->page_slug = EE_PAYMENTS_PG_SLUG;
47
-        $this->page_label = __('Payment Methods', 'event_espresso');
48
-        $this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
-    }
51
-
52
-
53
-    protected function _ajax_hooks()
54
-    {
55
-        // todo: all hooks for ajax goes here.
56
-    }
57
-
58
-
59
-    protected function _define_page_props()
60
-    {
61
-        $this->_admin_page_title = $this->page_label;
62
-        $this->_labels = array(
63
-            'publishbox' => __('Update Settings', 'event_espresso'),
64
-        );
65
-    }
66
-
67
-
68
-    protected function _set_page_routes()
69
-    {
70
-        /**
71
-         * note that with payment method capabilities, although we've implemented
72
-         * capability mapping which will be used for accessing payment methods owned by
73
-         * other users.  This is not fully implemented yet in the payment method ui.
74
-         * Currently only the "plural" caps are in active use.
75
-         * When cap mapping is implemented, some routes will need to use the singular form of
76
-         * capability method and also include the $id of the payment method for the route.
77
-         **/
78
-        $this->_page_routes = array(
79
-            'default'                   => array(
80
-                'func'       => '_payment_methods_list',
81
-                'capability' => 'ee_edit_payment_methods',
82
-            ),
83
-            'payment_settings'          => array(
84
-                'func'       => '_payment_settings',
85
-                'capability' => 'ee_manage_gateways',
86
-            ),
87
-            'activate_payment_method'   => array(
88
-                'func'       => '_activate_payment_method',
89
-                'noheader'   => true,
90
-                'capability' => 'ee_edit_payment_methods',
91
-            ),
92
-            'deactivate_payment_method' => array(
93
-                'func'       => '_deactivate_payment_method',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_delete_payment_methods',
96
-            ),
97
-            'update_payment_method'     => array(
98
-                'func'               => '_update_payment_method',
99
-                'noheader'           => true,
100
-                'headers_sent_route' => 'default',
101
-                'capability'         => 'ee_edit_payment_methods',
102
-            ),
103
-            'update_payment_settings'   => array(
104
-                'func'       => '_update_payment_settings',
105
-                'noheader'   => true,
106
-                'capability' => 'ee_manage_gateways',
107
-            ),
108
-            'payment_log'               => array(
109
-                'func'       => '_payment_log_overview_list_table',
110
-                'capability' => 'ee_read_payment_methods',
111
-            ),
112
-            'payment_log_details'       => array(
113
-                'func'       => '_payment_log_details',
114
-                'capability' => 'ee_read_payment_methods',
115
-            ),
116
-        );
117
-    }
118
-
119
-
120
-    protected function _set_page_config()
121
-    {
122
-        $payment_method_list_config = array(
123
-            'nav'           => array(
124
-                'label' => __('Payment Methods', 'event_espresso'),
125
-                'order' => 10,
126
-            ),
127
-            'metaboxes'     => $this->_default_espresso_metaboxes,
128
-            'help_tabs'     => array_merge(
129
-                array(
130
-                    'payment_methods_overview_help_tab' => array(
131
-                        'title'    => __('Payment Methods Overview', 'event_espresso'),
132
-                        'filename' => 'payment_methods_overview',
133
-                    ),
134
-                ),
135
-                $this->_add_payment_method_help_tabs()
136
-            ),
137
-            // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
138
-            // 'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
139
-            'require_nonce' => false,
140
-        );
141
-        $this->_page_config = array(
142
-            'default'          => $payment_method_list_config,
143
-            'payment_settings' => array(
144
-                'nav'           => array(
145
-                    'label' => __('Settings', 'event_espresso'),
146
-                    'order' => 20,
147
-                ),
148
-                'help_tabs'     => array(
149
-                    'payment_methods_settings_help_tab' => array(
150
-                        'title'    => __('Payment Method Settings', 'event_espresso'),
151
-                        'filename' => 'payment_methods_settings',
152
-                    ),
153
-                ),
154
-                // 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
155
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
156
-                'require_nonce' => false,
157
-            ),
158
-            'payment_log'      => array(
159
-                'nav'           => array(
160
-                    'label' => __("Logs", 'event_espresso'),
161
-                    'order' => 30,
162
-                ),
163
-                'list_table'    => 'Payment_Log_Admin_List_Table',
164
-                'metaboxes'     => $this->_default_espresso_metaboxes,
165
-                'require_nonce' => false,
166
-            ),
167
-        );
168
-    }
169
-
170
-
171
-    /**
172
-     * @return array
173
-     * @throws DomainException
174
-     * @throws EE_Error
175
-     * @throws InvalidArgumentException
176
-     * @throws InvalidDataTypeException
177
-     * @throws InvalidInterfaceException
178
-     * @throws ReflectionException
179
-     */
180
-    protected function _add_payment_method_help_tabs()
181
-    {
182
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
183
-        $payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
184
-        $all_pmt_help_tabs_config = array();
185
-        foreach ($payment_method_types as $payment_method_type) {
186
-            if (! EE_Registry::instance()->CAP->current_user_can(
187
-                $payment_method_type->cap_name(),
188
-                'specific_payment_method_type_access'
189
-            )
190
-            ) {
191
-                continue;
192
-            }
193
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
194
-                $template_args = isset($config['template_args']) ? $config['template_args'] : array();
195
-                $template_args['admin_page_obj'] = $this;
196
-                $all_pmt_help_tabs_config[ $help_tab_name ] = array(
197
-                    'title'   => $config['title'],
198
-                    'content' => EEH_Template::display_template(
199
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
200
-                        $template_args,
201
-                        true
202
-                    ),
203
-                );
204
-            }
205
-        }
206
-        return $all_pmt_help_tabs_config;
207
-    }
208
-
209
-
210
-    // none of the below group are currently used for Gateway Settings
211
-    protected function _add_screen_options()
212
-    {
213
-    }
214
-
215
-
216
-    protected function _add_feature_pointers()
217
-    {
218
-    }
219
-
220
-
221
-    public function admin_init()
222
-    {
223
-    }
224
-
225
-
226
-    public function admin_notices()
227
-    {
228
-    }
229
-
230
-
231
-    public function admin_footer_scripts()
232
-    {
233
-    }
234
-
235
-
236
-    public function load_scripts_styles()
237
-    {
238
-        // styles
239
-        wp_enqueue_style('espresso-ui-theme');
240
-        // scripts
241
-        wp_enqueue_script('ee_admin_js');
242
-        wp_enqueue_script('ee-text-links');
243
-        wp_enqueue_script(
244
-            'espresso_payments',
245
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
246
-            array('ee-datepicker'),
247
-            EVENT_ESPRESSO_VERSION,
248
-            true
249
-        );
250
-    }
251
-
252
-
253
-    public function load_scripts_styles_default()
254
-    {
255
-        // styles
256
-        wp_register_style(
257
-            'espresso_payments',
258
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
259
-            array(),
260
-            EVENT_ESPRESSO_VERSION
261
-        );
262
-        wp_enqueue_style('espresso_payments');
263
-        wp_enqueue_style('ee-text-links');
264
-        // scripts
265
-    }
266
-
267
-
268
-    protected function _payment_methods_list()
269
-    {
270
-        /**
271
-         * first let's ensure payment methods have been setup. We do this here because when people activate a
272
-         * payment method for the first time (as an addon), it may not setup its capabilities or get registered
273
-         * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
274
-         * safe to do a recheck here.
275
-         */
276
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
277
-        EEM_Payment_Method::instance()->verify_button_urls();
278
-        // setup tabs, one for each payment method type
279
-        $tabs = array();
280
-        $payment_methods = array();
281
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
282
-            // we don't want to show admin-only PMTs for now
283
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
284
-                continue;
285
-            }
286
-            // check access
287
-            if (! EE_Registry::instance()->CAP->current_user_can(
288
-                $pmt_obj->cap_name(),
289
-                'specific_payment_method_type_access'
290
-            )
291
-            ) {
292
-                continue;
293
-            }
294
-            // check for any active pms of that type
295
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
296
-            if (! $payment_method instanceof EE_Payment_Method) {
297
-                $payment_method = EE_Payment_Method::new_instance(
298
-                    array(
299
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
300
-                        'PMD_type'       => $pmt_obj->system_name(),
301
-                        'PMD_name'       => $pmt_obj->pretty_name(),
302
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
303
-                    )
304
-                );
305
-            }
306
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
307
-        }
308
-        $payment_methods = apply_filters(
309
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
310
-            $payment_methods
311
-        );
312
-        foreach ($payment_methods as $payment_method) {
313
-            if ($payment_method instanceof EE_Payment_Method) {
314
-                add_meta_box(
315
-                    // html id
316
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
317
-                    // title
318
-                    sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
319
-                    // callback
320
-                    array($this, 'payment_method_settings_meta_box'),
321
-                    // post type
322
-                    null,
323
-                    // context
324
-                    'normal',
325
-                    // priority
326
-                    'default',
327
-                    // callback args
328
-                    array('payment_method' => $payment_method)
329
-                );
330
-                // setup for tabbed content
331
-                $tabs[ $payment_method->slug() ] = array(
332
-                    'label' => $payment_method->admin_name(),
333
-                    'class' => $payment_method->active() ? 'gateway-active' : '',
334
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
335
-                    'title' => __('Modify this Payment Method', 'event_espresso'),
336
-                    'slug'  => $payment_method->slug(),
337
-                );
338
-            }
339
-        }
340
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
341
-            $tabs,
342
-            'payment_method_links',
343
-            '|',
344
-            $this->_get_active_payment_method_slug()
345
-        );
346
-        $this->display_admin_page_with_sidebar();
347
-    }
348
-
349
-
350
-    /**
351
-     *   _get_active_payment_method_slug
352
-     *
353
-     * @return string
354
-     */
355
-    protected function _get_active_payment_method_slug()
356
-    {
357
-        $payment_method_slug = false;
358
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
359
-        if (isset($this->_req_data['payment_method'])) {
360
-            // if they provided the current payment method, use it
361
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
362
-        }
363
-        $payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
364
-        // if that didn't work or wasn't provided, find another way to select the current pm
365
-        if (! $this->_verify_payment_method($payment_method)) {
366
-            // like, looking for an active one
367
-            $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
368
-            // test that one as well
369
-            if ($this->_verify_payment_method($payment_method)) {
370
-                $payment_method_slug = $payment_method->slug();
371
-            } else {
372
-                $payment_method_slug = 'paypal_standard';
373
-            }
374
-        }
375
-        return $payment_method_slug;
376
-    }
377
-
378
-
379
-    /**
380
-     *    payment_method_settings_meta_box
381
-     *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
382
-     *    capabilities to access it
383
-     *
384
-     * @param EE_Payment_Method $payment_method
385
-     * @return boolean
386
-     */
387
-    protected function _verify_payment_method($payment_method)
388
-    {
389
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
390
-            && EE_Registry::instance()->CAP->current_user_can(
391
-                $payment_method->type_obj()->cap_name(),
392
-                'specific_payment_method_type_access'
393
-            )
394
-        ) {
395
-            return true;
396
-        }
397
-        return false;
398
-    }
399
-
400
-
401
-    /**
402
-     *    payment_method_settings_meta_box
403
-     *
404
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
405
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
406
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
407
-     * @return string
408
-     * @throws EE_Error
409
-     */
410
-    public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
411
-    {
412
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
413
-            ? $metabox['args']['payment_method'] : null;
414
-        if (! $payment_method instanceof EE_Payment_Method) {
415
-            throw new EE_Error(
416
-                sprintf(
417
-                    __(
418
-                        'Payment method metabox setup incorrectly. No Payment method object was supplied',
419
-                        'event_espresso'
420
-                    )
421
-                )
422
-            );
423
-        }
424
-        $payment_method_scopes = $payment_method->active();
425
-        // if the payment method really exists show its form, otherwise the activation template
426
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
427
-            $form = $this->_generate_payment_method_settings_form($payment_method);
428
-            if ($form->form_data_present_in($this->_req_data)) {
429
-                $form->receive_form_submission($this->_req_data);
430
-            }
431
-            echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
432
-        } else {
433
-            echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
434
-        }
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets the form for all the settings related to this payment method type
440
-     *
441
-     * @access protected
442
-     * @param EE_Payment_Method $payment_method
443
-     * @return EE_Form_Section_Proper
444
-     */
445
-    protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
446
-    {
447
-        if (! $payment_method instanceof EE_Payment_Method) {
448
-            return new EE_Form_Section_Proper();
449
-        }
450
-        return new EE_Form_Section_Proper(
451
-            array(
452
-                'name'            => $payment_method->slug() . '_settings_form',
453
-                'html_id'         => $payment_method->slug() . '_settings_form',
454
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
455
-                    array(
456
-                        'action'         => 'update_payment_method',
457
-                        'payment_method' => $payment_method->slug(),
458
-                    ),
459
-                    EE_PAYMENTS_ADMIN_URL
460
-                ),
461
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
462
-                'subsections'     => apply_filters(
463
-                    'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
464
-                    array(
465
-                        'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
466
-                        'currency_support'        => $this->_currency_support($payment_method),
467
-                        'payment_method_settings' => $this->_payment_method_settings($payment_method),
468
-                        'update'                  => $this->_update_payment_method_button($payment_method),
469
-                        'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
470
-                        'fine_print'              => $this->_fine_print(),
471
-                    ),
472
-                    $payment_method
473
-                ),
474
-            )
475
-        );
476
-    }
477
-
478
-
479
-    /**
480
-     * _pci_dss_compliance
481
-     *
482
-     * @access protected
483
-     * @param EE_Payment_Method $payment_method
484
-     * @return EE_Form_Section_Proper
485
-     */
486
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
487
-    {
488
-        if ($payment_method->type_obj()->requires_https()) {
489
-            return new EE_Form_Section_HTML(
490
-                EEH_HTML::table(
491
-                    EEH_HTML::tr(
492
-                        EEH_HTML::th(
493
-                            EEH_HTML::label(
494
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
495
-                            )
496
-                        ) .
497
-                        EEH_HTML::td(
498
-                            EEH_HTML::strong(
499
-                                __(
500
-                                    'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
501
-                                    'event_espresso'
502
-                                )
503
-                            )
504
-                            .
505
-                            EEH_HTML::br()
506
-                            .
507
-                            __('Learn more about ', 'event_espresso')
508
-                            . EEH_HTML::link(
509
-                                'https://www.pcisecuritystandards.org/merchants/index.php',
510
-                                __('PCI DSS compliance', 'event_espresso')
511
-                            )
512
-                        )
513
-                    )
514
-                )
515
-            );
516
-        } else {
517
-            return new EE_Form_Section_HTML('');
518
-        }
519
-    }
520
-
521
-
522
-    /**
523
-     * _currency_support
524
-     *
525
-     * @access protected
526
-     * @param EE_Payment_Method $payment_method
527
-     * @return EE_Form_Section_Proper
528
-     */
529
-    protected function _currency_support(EE_Payment_Method $payment_method)
530
-    {
531
-        if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
532
-            return new EE_Form_Section_HTML(
533
-                EEH_HTML::table(
534
-                    EEH_HTML::tr(
535
-                        EEH_HTML::th(
536
-                            EEH_HTML::label(
537
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
538
-                            )
539
-                        ) .
540
-                        EEH_HTML::td(
541
-                            EEH_HTML::strong(
542
-                                sprintf(
543
-                                    __(
544
-                                        'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
545
-                                        'event_espresso'
546
-                                    ),
547
-                                    EE_Config::instance()->currency->code
548
-                                )
549
-                            )
550
-                        )
551
-                    )
552
-                )
553
-            );
554
-        } else {
555
-            return new EE_Form_Section_HTML('');
556
-        }
557
-    }
558
-
559
-
560
-    /**
561
-     * _update_payment_method_button
562
-     *
563
-     * @access protected
564
-     * @param EE_Payment_Method $payment_method
565
-     * @return EE_Payment_Method_Form
566
-     */
567
-    protected function _payment_method_settings(EE_Payment_Method $payment_method)
568
-    {
569
-        // modify the form so we only have/show fields that will be implemented for this version
570
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
571
-    }
572
-
573
-
574
-    /**
575
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
576
-     *
577
-     * @param EE_Form_Section_Proper $form_section
578
-     * @param string                 $payment_method_name
579
-     * @return EE_Payment_Method_Form
580
-     * @throws EE_Error
581
-     */
582
-    protected function _simplify_form($form_section, $payment_method_name = '')
583
-    {
584
-        if ($form_section instanceof EE_Payment_Method_Form) {
585
-            $form_section->exclude(
586
-                array(
587
-                    'PMD_type', // dont want them changing the type
588
-                    'PMD_slug', // or the slug (probably never)
589
-                    'PMD_wp_user', // or the user's ID
590
-                    'Currency' // or the currency, until the rest of EE supports simultaneous currencies
591
-                )
592
-            );
593
-            return $form_section;
594
-        } else {
595
-            throw new EE_Error(
596
-                sprintf(
597
-                    __(
598
-                        'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
599
-                        'event_espresso'
600
-                    ),
601
-                    $payment_method_name
602
-                )
603
-            );
604
-        }
605
-    }
606
-
607
-
608
-    /**
609
-     * _update_payment_method_button
610
-     *
611
-     * @access protected
612
-     * @param EE_Payment_Method $payment_method
613
-     * @return EE_Form_Section_HTML
614
-     */
615
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method)
616
-    {
617
-        $update_button = new EE_Submit_Input(
618
-            array(
619
-                'name'       => 'submit',
620
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
621
-                'default'    => sprintf(
622
-                    __('Update %s Payment Settings', 'event_espresso'),
623
-                    $payment_method->admin_name()
624
-                ),
625
-                'html_label' => EEH_HTML::nbsp(),
626
-            )
627
-        );
628
-        return new EE_Form_Section_HTML(
629
-            EEH_HTML::table(
630
-                EEH_HTML::no_row(EEH_HTML::br(2)) .
631
-                EEH_HTML::tr(
632
-                    EEH_HTML::th(__('Update Settings', 'event_espresso')) .
633
-                    EEH_HTML::td(
634
-                        $update_button->get_html_for_input()
635
-                    )
636
-                )
637
-            )
638
-        );
639
-    }
640
-
641
-
642
-    /**
643
-     * _deactivate_payment_method_button
644
-     *
645
-     * @access protected
646
-     * @param EE_Payment_Method $payment_method
647
-     * @return EE_Form_Section_Proper
648
-     */
649
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
650
-    {
651
-        $link_text_and_title = sprintf(
652
-            __('Deactivate %1$s Payments?', 'event_espresso'),
653
-            $payment_method->admin_name()
654
-        );
655
-        return new EE_Form_Section_HTML(
656
-            EEH_HTML::table(
657
-                EEH_HTML::tr(
658
-                    EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
659
-                    EEH_HTML::td(
660
-                        EEH_HTML::link(
661
-                            EE_Admin_Page::add_query_args_and_nonce(
662
-                                array(
663
-                                    'action'         => 'deactivate_payment_method',
664
-                                    'payment_method' => $payment_method->slug(),
665
-                                ),
666
-                                EE_PAYMENTS_ADMIN_URL
667
-                            ),
668
-                            $link_text_and_title,
669
-                            $link_text_and_title,
670
-                            'deactivate_' . $payment_method->slug(),
671
-                            'espresso-button button-secondary'
672
-                        )
673
-                    )
674
-                )
675
-            )
676
-        );
677
-    }
678
-
679
-
680
-    /**
681
-     * _activate_payment_method_button
682
-     *
683
-     * @access protected
684
-     * @param EE_Payment_Method $payment_method
685
-     * @return EE_Form_Section_Proper
686
-     */
687
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
688
-    {
689
-        $link_text_and_title = sprintf(
690
-            __('Activate %1$s Payment Method?', 'event_espresso'),
691
-            $payment_method->admin_name()
692
-        );
693
-        return new EE_Form_Section_Proper(
694
-            array(
695
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
696
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
697
-                'action'          => '#',
698
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
699
-                'subsections'     => apply_filters(
700
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
701
-                    array(
702
-                        new EE_Form_Section_HTML(
703
-                            EEH_HTML::table(
704
-                                EEH_HTML::tr(
705
-                                    EEH_HTML::td(
706
-                                        $payment_method->type_obj()->introductory_html(),
707
-                                        '',
708
-                                        '',
709
-                                        '',
710
-                                        'colspan="2"'
711
-                                    )
712
-                                ) .
713
-                                EEH_HTML::tr(
714
-                                    EEH_HTML::th(
715
-                                        EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
716
-                                    ) .
717
-                                    EEH_HTML::td(
718
-                                        EEH_HTML::link(
719
-                                            EE_Admin_Page::add_query_args_and_nonce(
720
-                                                array(
721
-                                                    'action'              => 'activate_payment_method',
722
-                                                    'payment_method_type' => $payment_method->type(),
723
-                                                ),
724
-                                                EE_PAYMENTS_ADMIN_URL
725
-                                            ),
726
-                                            $link_text_and_title,
727
-                                            $link_text_and_title,
728
-                                            'activate_' . $payment_method->slug(),
729
-                                            'espresso-button-green button-primary'
730
-                                        )
731
-                                    )
732
-                                )
733
-                            )
734
-                        ),
735
-                    ),
736
-                    $payment_method
737
-                ),
738
-            )
739
-        );
740
-    }
741
-
742
-
743
-    /**
744
-     * _fine_print
745
-     *
746
-     * @access protected
747
-     * @return EE_Form_Section_HTML
748
-     */
749
-    protected function _fine_print()
750
-    {
751
-        return new EE_Form_Section_HTML(
752
-            EEH_HTML::table(
753
-                EEH_HTML::tr(
754
-                    EEH_HTML::th() .
755
-                    EEH_HTML::td(
756
-                        EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
757
-                    )
758
-                )
759
-            )
760
-        );
761
-    }
762
-
763
-
764
-    /**
765
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
766
-     *
767
-     * @global WP_User $current_user
768
-     */
769
-    protected function _activate_payment_method()
770
-    {
771
-        if (isset($this->_req_data['payment_method_type'])) {
772
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
773
-            // see if one exists
774
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
775
-            $payment_method = EE_Payment_Method_Manager::instance()
776
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
777
-            $this->_redirect_after_action(
778
-                1,
779
-                'Payment Method',
780
-                'activated',
781
-                array('action' => 'default', 'payment_method' => $payment_method->slug())
782
-            );
783
-        } else {
784
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
785
-        }
786
-    }
787
-
788
-
789
-    /**
790
-     * Deactivates the payment method with the specified slug, and redirects.
791
-     */
792
-    protected function _deactivate_payment_method()
793
-    {
794
-        if (isset($this->_req_data['payment_method'])) {
795
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
796
-            // deactivate it
797
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
798
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
799
-            $this->_redirect_after_action(
800
-                $count_updated,
801
-                'Payment Method',
802
-                'deactivated',
803
-                array('action' => 'default', 'payment_method' => $payment_method_slug)
804
-            );
805
-        } else {
806
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
807
-        }
808
-    }
809
-
810
-
811
-    /**
812
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
813
-     * processing because we first need to identify WHICH form was processed and which payment method
814
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
815
-     * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
816
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
817
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
818
-     *
819
-     * @return void
820
-     */
821
-    protected function _update_payment_method()
822
-    {
823
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
824
-            // ok let's find which gateway form to use based on the form input
825
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
826
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
827
-            $correct_pmt_form_to_use = null;
828
-            $payment_method = null;
829
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
830
-                // get the form and simplify it, like what we do when we display it
831
-                $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
832
-                if ($pmt_form->form_data_present_in($this->_req_data)) {
833
-                    $correct_pmt_form_to_use = $pmt_form;
834
-                    break;
835
-                }
836
-            }
837
-            // if we couldn't find the correct payment method type...
838
-            if (! $correct_pmt_form_to_use) {
839
-                EE_Error::add_error(
840
-                    __(
841
-                        "We could not find which payment method type your form submission related to. Please contact support",
842
-                        'event_espresso'
843
-                    ),
844
-                    __FILE__,
845
-                    __FUNCTION__,
846
-                    __LINE__
847
-                );
848
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
849
-            }
850
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
851
-            if ($correct_pmt_form_to_use->is_valid()) {
852
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
853
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
854
-                    throw new EE_Error(
855
-                        sprintf(
856
-                            __(
857
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
858
-                                'event_espresso'
859
-                            ),
860
-                            'payment_method_settings'
861
-                        )
862
-                    );
863
-                }
864
-                $payment_settings_subform->save();
865
-                /** @var $pm EE_Payment_Method */
866
-                $this->_redirect_after_action(
867
-                    true,
868
-                    'Payment Method',
869
-                    'updated',
870
-                    array('action' => 'default', 'payment_method' => $payment_method->slug())
871
-                );
872
-            } else {
873
-                EE_Error::add_error(
874
-                    sprintf(
875
-                        __(
876
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
877
-                            'event_espresso'
878
-                        ),
879
-                        $payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
880
-                            : __('"(unknown)"', 'event_espresso')
881
-                    ),
882
-                    __FILE__,
883
-                    __FUNCTION__,
884
-                    __LINE__
885
-                );
886
-            }
887
-        }
888
-        return;
889
-    }
890
-
891
-
892
-    /**
893
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
894
-     * @throws DomainException
895
-     * @throws EE_Error
896
-     * @throws InvalidArgumentException
897
-     * @throws InvalidDataTypeException
898
-     * @throws InvalidInterfaceException
899
-     */
900
-    protected function _payment_settings()
901
-    {
902
-        $form = $this->getPaymentSettingsForm();
903
-        $this->_set_add_edit_form_tags('update_payment_settings');
904
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
905
-        $this->_template_args['admin_page_content'] =  $form->get_html_and_js();
906
-        $this->display_admin_page_with_sidebar();
907
-    }
908
-
909
-
910
-    /**
911
-     *        _update_payment_settings
912
-     *
913
-     * @access protected
914
-     * @return void
915
-     * @throws EE_Error
916
-     * @throws InvalidArgumentException
917
-     * @throws InvalidDataTypeException
918
-     * @throws InvalidInterfaceException
919
-     */
920
-    protected function _update_payment_settings()
921
-    {
922
-        $form = $this->getPaymentSettingsForm();
923
-        if ($form->was_submitted($this->_req_data)) {
924
-            $form->receive_form_submission($this->_req_data);
925
-            if ($form->is_valid()) {
926
-                /**
927
-                 * @var $reg_config EE_Registration_Config
928
-                 */
929
-                $loader = LoaderFactory::getLoader();
930
-                $reg_config = $loader->getShared('EE_Registration_Config');
931
-                $valid_data = $form->valid_data();
932
-                $reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
933
-                $reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
934
-            }
935
-        }
936
-        EE_Registry::instance()->CFG = apply_filters(
937
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
938
-            EE_Registry::instance()->CFG
939
-        );
940
-
941
-        $cfg =  EE_Registry::instance()->CFG ;
942
-
943
-        $what = __('Payment Settings', 'event_espresso');
944
-        $success = $this->_update_espresso_configuration(
945
-            $what,
946
-            EE_Registry::instance()->CFG,
947
-            __FILE__,
948
-            __FUNCTION__,
949
-            __LINE__
950
-        );
951
-        $this->_redirect_after_action(
952
-            $success,
953
-            $what,
954
-            __('updated', 'event_espresso'),
955
-            array('action' => 'payment_settings')
956
-        );
957
-    }
958
-
959
-
960
-    /**
961
-     * Gets the form used for updating payment settings
962
-     *
963
-     * @return EE_Form_Section_Proper
964
-     * @throws EE_Error
965
-     * @throws InvalidArgumentException
966
-     * @throws InvalidDataTypeException
967
-     * @throws InvalidInterfaceException
968
-     */
969
-    protected function getPaymentSettingsForm()
970
-    {
971
-        /**
972
-         * @var $reg_config EE_Registration_Config
973
-         */
974
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
975
-        return new EE_Form_Section_Proper(
976
-            array(
977
-                'name' => 'payment-settings',
978
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
979
-                'subsections' => array(
980
-                    'show_pending_payment_options' => new EE_Yes_No_Input(
981
-                        array(
982
-                            'html_name' => 'show_pending_payment_options',
983
-                            'default' => $reg_config->show_pending_payment_options,
984
-                            'html_help_text' => esc_html__(
985
-                                "If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
986
-                                'event_espresso'
987
-                            )
988
-                        )
989
-                    ),
990
-                    'gateway_log_lifespan' => new EE_Select_Input(
991
-                        $reg_config->gatewayLogLifespanOptions(),
992
-                        array(
993
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
994
-                            'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
995
-                            'default' => $reg_config->gateway_log_lifespan,
996
-                        )
997
-                    )
998
-                )
999
-            )
1000
-        );
1001
-    }
1002
-
1003
-
1004
-    protected function _payment_log_overview_list_table()
1005
-    {
1006
-        $this->display_admin_list_table_page_with_sidebar();
1007
-    }
1008
-
1009
-
1010
-    protected function _set_list_table_views_payment_log()
1011
-    {
1012
-        $this->_views = array(
1013
-            'all' => array(
1014
-                'slug'  => 'all',
1015
-                'label' => __('View All Logs', 'event_espresso'),
1016
-                'count' => 0,
1017
-            ),
1018
-        );
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * @param int  $per_page
1024
-     * @param int  $current_page
1025
-     * @param bool $count
1026
-     * @return array
1027
-     */
1028
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1029
-    {
1030
-        EE_Registry::instance()->load_model('Change_Log');
1031
-        // we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1032
-        $query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1033
-        // check if they've selected a specific payment method
1034
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1035
-            $query_params[0]['OR*pm_or_pay_pm'] = array(
1036
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1037
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1038
-            );
1039
-        }
1040
-        // take into account search
1041
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1042
-            $similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1043
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1044
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1045
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1046
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1047
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1048
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1049
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1050
-            $query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1051
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1052
-            $query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1053
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1054
-        }
1055
-        if (isset($this->_req_data['payment-filter-start-date'])
1056
-            && isset($this->_req_data['payment-filter-end-date'])
1057
-        ) {
1058
-            // add date
1059
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1060
-            $end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1061
-            // make sure our timestamps start and end right at the boundaries for each day
1062
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1063
-            $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1064
-            // convert to timestamps
1065
-            $start_date = strtotime($start_date);
1066
-            $end_date = strtotime($end_date);
1067
-            // makes sure start date is the lowest value and vice versa
1068
-            $start_date = min($start_date, $end_date);
1069
-            $end_date = max($start_date, $end_date);
1070
-            // convert for query
1071
-            $start_date = EEM_Change_Log::instance()
1072
-                                        ->convert_datetime_for_query(
1073
-                                            'LOG_time',
1074
-                                            date('Y-m-d H:i:s', $start_date),
1075
-                                            'Y-m-d H:i:s'
1076
-                                        );
1077
-            $end_date = EEM_Change_Log::instance()
1078
-                                      ->convert_datetime_for_query(
1079
-                                          'LOG_time',
1080
-                                          date('Y-m-d H:i:s', $end_date),
1081
-                                          'Y-m-d H:i:s'
1082
-                                      );
1083
-            $query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1084
-        }
1085
-        if ($count) {
1086
-            return EEM_Change_Log::instance()->count($query_params);
1087
-        }
1088
-        if (isset($this->_req_data['order'])) {
1089
-            $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1090
-                : 'DESC';
1091
-            $query_params['order_by'] = array('LOG_time' => $sort);
1092
-        } else {
1093
-            $query_params['order_by'] = array('LOG_time' => 'DESC');
1094
-        }
1095
-        $offset = ($current_page - 1) * $per_page;
1096
-        if (! isset($this->_req_data['download_results'])) {
1097
-            $query_params['limit'] = array($offset, $per_page);
1098
-        }
1099
-        // now they've requested to instead just download the file instead of viewing it.
1100
-        if (isset($this->_req_data['download_results'])) {
1101
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1102
-            header('Content-Disposition: attachment');
1103
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1104
-            echo "<h1>Payment Logs for " . site_url() . "</h1>";
1105
-            echo "<h3>Query:</h3>";
1106
-            var_dump($query_params);
1107
-            echo "<h3>Results:</h3>";
1108
-            var_dump($wpdb_results);
1109
-            die;
1110
-        }
1111
-        $results = EEM_Change_Log::instance()->get_all($query_params);
1112
-        return $results;
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * Used by usort to RE-sort log query results, because we lose the ordering
1118
-     * because we're possibly combining the results from two queries
1119
-     *
1120
-     * @param EE_Change_Log $logA
1121
-     * @param EE_Change_Log $logB
1122
-     * @return int
1123
-     */
1124
-    protected function _sort_logs_again($logA, $logB)
1125
-    {
1126
-        $timeA = $logA->get_raw('LOG_time');
1127
-        $timeB = $logB->get_raw('LOG_time');
1128
-        if ($timeA == $timeB) {
1129
-            return 0;
1130
-        }
1131
-        $comparison = $timeA < $timeB ? -1 : 1;
1132
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1133
-            return $comparison * -1;
1134
-        } else {
1135
-            return $comparison;
1136
-        }
1137
-    }
1138
-
1139
-
1140
-    protected function _payment_log_details()
1141
-    {
1142
-        EE_Registry::instance()->load_model('Change_Log');
1143
-        /** @var $payment_log EE_Change_Log */
1144
-        $payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1145
-        $payment_method = null;
1146
-        $transaction = null;
1147
-        if ($payment_log instanceof EE_Change_Log) {
1148
-            if ($payment_log->object() instanceof EE_Payment) {
1149
-                $payment_method = $payment_log->object()->payment_method();
1150
-                $transaction = $payment_log->object()->transaction();
1151
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1152
-                $payment_method = $payment_log->object();
1153
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1154
-                $transaction = $payment_log->object();
1155
-                $payment_method = $transaction->payment_method();
1156
-            }
1157
-        }
1158
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1159
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1160
-            array(
1161
-                'payment_log'    => $payment_log,
1162
-                'payment_method' => $payment_method,
1163
-                'transaction'    => $transaction,
1164
-            ),
1165
-            true
1166
-        );
1167
-        $this->display_admin_page_with_sidebar();
1168
-    }
19
+	/**
20
+	 * Variables used for when we're re-sorting the logs results, in case
21
+	 * we needed to do two queries and we need to resort
22
+	 *
23
+	 * @var string
24
+	 */
25
+	private $_sort_logs_again_direction;
26
+
27
+
28
+	/**
29
+	 * @Constructor
30
+	 * @access public
31
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
+	 * @throws EE_Error
33
+	 * @throws InvalidArgumentException
34
+	 * @throws InvalidDataTypeException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws ReflectionException
37
+	 */
38
+	public function __construct($routing = true)
39
+	{
40
+		parent::__construct($routing);
41
+	}
42
+
43
+
44
+	protected function _init_page_props()
45
+	{
46
+		$this->page_slug = EE_PAYMENTS_PG_SLUG;
47
+		$this->page_label = __('Payment Methods', 'event_espresso');
48
+		$this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
+	}
51
+
52
+
53
+	protected function _ajax_hooks()
54
+	{
55
+		// todo: all hooks for ajax goes here.
56
+	}
57
+
58
+
59
+	protected function _define_page_props()
60
+	{
61
+		$this->_admin_page_title = $this->page_label;
62
+		$this->_labels = array(
63
+			'publishbox' => __('Update Settings', 'event_espresso'),
64
+		);
65
+	}
66
+
67
+
68
+	protected function _set_page_routes()
69
+	{
70
+		/**
71
+		 * note that with payment method capabilities, although we've implemented
72
+		 * capability mapping which will be used for accessing payment methods owned by
73
+		 * other users.  This is not fully implemented yet in the payment method ui.
74
+		 * Currently only the "plural" caps are in active use.
75
+		 * When cap mapping is implemented, some routes will need to use the singular form of
76
+		 * capability method and also include the $id of the payment method for the route.
77
+		 **/
78
+		$this->_page_routes = array(
79
+			'default'                   => array(
80
+				'func'       => '_payment_methods_list',
81
+				'capability' => 'ee_edit_payment_methods',
82
+			),
83
+			'payment_settings'          => array(
84
+				'func'       => '_payment_settings',
85
+				'capability' => 'ee_manage_gateways',
86
+			),
87
+			'activate_payment_method'   => array(
88
+				'func'       => '_activate_payment_method',
89
+				'noheader'   => true,
90
+				'capability' => 'ee_edit_payment_methods',
91
+			),
92
+			'deactivate_payment_method' => array(
93
+				'func'       => '_deactivate_payment_method',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_delete_payment_methods',
96
+			),
97
+			'update_payment_method'     => array(
98
+				'func'               => '_update_payment_method',
99
+				'noheader'           => true,
100
+				'headers_sent_route' => 'default',
101
+				'capability'         => 'ee_edit_payment_methods',
102
+			),
103
+			'update_payment_settings'   => array(
104
+				'func'       => '_update_payment_settings',
105
+				'noheader'   => true,
106
+				'capability' => 'ee_manage_gateways',
107
+			),
108
+			'payment_log'               => array(
109
+				'func'       => '_payment_log_overview_list_table',
110
+				'capability' => 'ee_read_payment_methods',
111
+			),
112
+			'payment_log_details'       => array(
113
+				'func'       => '_payment_log_details',
114
+				'capability' => 'ee_read_payment_methods',
115
+			),
116
+		);
117
+	}
118
+
119
+
120
+	protected function _set_page_config()
121
+	{
122
+		$payment_method_list_config = array(
123
+			'nav'           => array(
124
+				'label' => __('Payment Methods', 'event_espresso'),
125
+				'order' => 10,
126
+			),
127
+			'metaboxes'     => $this->_default_espresso_metaboxes,
128
+			'help_tabs'     => array_merge(
129
+				array(
130
+					'payment_methods_overview_help_tab' => array(
131
+						'title'    => __('Payment Methods Overview', 'event_espresso'),
132
+						'filename' => 'payment_methods_overview',
133
+					),
134
+				),
135
+				$this->_add_payment_method_help_tabs()
136
+			),
137
+			// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
138
+			// 'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
139
+			'require_nonce' => false,
140
+		);
141
+		$this->_page_config = array(
142
+			'default'          => $payment_method_list_config,
143
+			'payment_settings' => array(
144
+				'nav'           => array(
145
+					'label' => __('Settings', 'event_espresso'),
146
+					'order' => 20,
147
+				),
148
+				'help_tabs'     => array(
149
+					'payment_methods_settings_help_tab' => array(
150
+						'title'    => __('Payment Method Settings', 'event_espresso'),
151
+						'filename' => 'payment_methods_settings',
152
+					),
153
+				),
154
+				// 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
155
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
156
+				'require_nonce' => false,
157
+			),
158
+			'payment_log'      => array(
159
+				'nav'           => array(
160
+					'label' => __("Logs", 'event_espresso'),
161
+					'order' => 30,
162
+				),
163
+				'list_table'    => 'Payment_Log_Admin_List_Table',
164
+				'metaboxes'     => $this->_default_espresso_metaboxes,
165
+				'require_nonce' => false,
166
+			),
167
+		);
168
+	}
169
+
170
+
171
+	/**
172
+	 * @return array
173
+	 * @throws DomainException
174
+	 * @throws EE_Error
175
+	 * @throws InvalidArgumentException
176
+	 * @throws InvalidDataTypeException
177
+	 * @throws InvalidInterfaceException
178
+	 * @throws ReflectionException
179
+	 */
180
+	protected function _add_payment_method_help_tabs()
181
+	{
182
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
183
+		$payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
184
+		$all_pmt_help_tabs_config = array();
185
+		foreach ($payment_method_types as $payment_method_type) {
186
+			if (! EE_Registry::instance()->CAP->current_user_can(
187
+				$payment_method_type->cap_name(),
188
+				'specific_payment_method_type_access'
189
+			)
190
+			) {
191
+				continue;
192
+			}
193
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
194
+				$template_args = isset($config['template_args']) ? $config['template_args'] : array();
195
+				$template_args['admin_page_obj'] = $this;
196
+				$all_pmt_help_tabs_config[ $help_tab_name ] = array(
197
+					'title'   => $config['title'],
198
+					'content' => EEH_Template::display_template(
199
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
200
+						$template_args,
201
+						true
202
+					),
203
+				);
204
+			}
205
+		}
206
+		return $all_pmt_help_tabs_config;
207
+	}
208
+
209
+
210
+	// none of the below group are currently used for Gateway Settings
211
+	protected function _add_screen_options()
212
+	{
213
+	}
214
+
215
+
216
+	protected function _add_feature_pointers()
217
+	{
218
+	}
219
+
220
+
221
+	public function admin_init()
222
+	{
223
+	}
224
+
225
+
226
+	public function admin_notices()
227
+	{
228
+	}
229
+
230
+
231
+	public function admin_footer_scripts()
232
+	{
233
+	}
234
+
235
+
236
+	public function load_scripts_styles()
237
+	{
238
+		// styles
239
+		wp_enqueue_style('espresso-ui-theme');
240
+		// scripts
241
+		wp_enqueue_script('ee_admin_js');
242
+		wp_enqueue_script('ee-text-links');
243
+		wp_enqueue_script(
244
+			'espresso_payments',
245
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
246
+			array('ee-datepicker'),
247
+			EVENT_ESPRESSO_VERSION,
248
+			true
249
+		);
250
+	}
251
+
252
+
253
+	public function load_scripts_styles_default()
254
+	{
255
+		// styles
256
+		wp_register_style(
257
+			'espresso_payments',
258
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
259
+			array(),
260
+			EVENT_ESPRESSO_VERSION
261
+		);
262
+		wp_enqueue_style('espresso_payments');
263
+		wp_enqueue_style('ee-text-links');
264
+		// scripts
265
+	}
266
+
267
+
268
+	protected function _payment_methods_list()
269
+	{
270
+		/**
271
+		 * first let's ensure payment methods have been setup. We do this here because when people activate a
272
+		 * payment method for the first time (as an addon), it may not setup its capabilities or get registered
273
+		 * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
274
+		 * safe to do a recheck here.
275
+		 */
276
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
277
+		EEM_Payment_Method::instance()->verify_button_urls();
278
+		// setup tabs, one for each payment method type
279
+		$tabs = array();
280
+		$payment_methods = array();
281
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
282
+			// we don't want to show admin-only PMTs for now
283
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
284
+				continue;
285
+			}
286
+			// check access
287
+			if (! EE_Registry::instance()->CAP->current_user_can(
288
+				$pmt_obj->cap_name(),
289
+				'specific_payment_method_type_access'
290
+			)
291
+			) {
292
+				continue;
293
+			}
294
+			// check for any active pms of that type
295
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
296
+			if (! $payment_method instanceof EE_Payment_Method) {
297
+				$payment_method = EE_Payment_Method::new_instance(
298
+					array(
299
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
300
+						'PMD_type'       => $pmt_obj->system_name(),
301
+						'PMD_name'       => $pmt_obj->pretty_name(),
302
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
303
+					)
304
+				);
305
+			}
306
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
307
+		}
308
+		$payment_methods = apply_filters(
309
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
310
+			$payment_methods
311
+		);
312
+		foreach ($payment_methods as $payment_method) {
313
+			if ($payment_method instanceof EE_Payment_Method) {
314
+				add_meta_box(
315
+					// html id
316
+					'espresso_' . $payment_method->slug() . '_payment_settings',
317
+					// title
318
+					sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
319
+					// callback
320
+					array($this, 'payment_method_settings_meta_box'),
321
+					// post type
322
+					null,
323
+					// context
324
+					'normal',
325
+					// priority
326
+					'default',
327
+					// callback args
328
+					array('payment_method' => $payment_method)
329
+				);
330
+				// setup for tabbed content
331
+				$tabs[ $payment_method->slug() ] = array(
332
+					'label' => $payment_method->admin_name(),
333
+					'class' => $payment_method->active() ? 'gateway-active' : '',
334
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
335
+					'title' => __('Modify this Payment Method', 'event_espresso'),
336
+					'slug'  => $payment_method->slug(),
337
+				);
338
+			}
339
+		}
340
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
341
+			$tabs,
342
+			'payment_method_links',
343
+			'|',
344
+			$this->_get_active_payment_method_slug()
345
+		);
346
+		$this->display_admin_page_with_sidebar();
347
+	}
348
+
349
+
350
+	/**
351
+	 *   _get_active_payment_method_slug
352
+	 *
353
+	 * @return string
354
+	 */
355
+	protected function _get_active_payment_method_slug()
356
+	{
357
+		$payment_method_slug = false;
358
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
359
+		if (isset($this->_req_data['payment_method'])) {
360
+			// if they provided the current payment method, use it
361
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
362
+		}
363
+		$payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
364
+		// if that didn't work or wasn't provided, find another way to select the current pm
365
+		if (! $this->_verify_payment_method($payment_method)) {
366
+			// like, looking for an active one
367
+			$payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
368
+			// test that one as well
369
+			if ($this->_verify_payment_method($payment_method)) {
370
+				$payment_method_slug = $payment_method->slug();
371
+			} else {
372
+				$payment_method_slug = 'paypal_standard';
373
+			}
374
+		}
375
+		return $payment_method_slug;
376
+	}
377
+
378
+
379
+	/**
380
+	 *    payment_method_settings_meta_box
381
+	 *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
382
+	 *    capabilities to access it
383
+	 *
384
+	 * @param EE_Payment_Method $payment_method
385
+	 * @return boolean
386
+	 */
387
+	protected function _verify_payment_method($payment_method)
388
+	{
389
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
390
+			&& EE_Registry::instance()->CAP->current_user_can(
391
+				$payment_method->type_obj()->cap_name(),
392
+				'specific_payment_method_type_access'
393
+			)
394
+		) {
395
+			return true;
396
+		}
397
+		return false;
398
+	}
399
+
400
+
401
+	/**
402
+	 *    payment_method_settings_meta_box
403
+	 *
404
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
405
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
406
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
407
+	 * @return string
408
+	 * @throws EE_Error
409
+	 */
410
+	public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
411
+	{
412
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
413
+			? $metabox['args']['payment_method'] : null;
414
+		if (! $payment_method instanceof EE_Payment_Method) {
415
+			throw new EE_Error(
416
+				sprintf(
417
+					__(
418
+						'Payment method metabox setup incorrectly. No Payment method object was supplied',
419
+						'event_espresso'
420
+					)
421
+				)
422
+			);
423
+		}
424
+		$payment_method_scopes = $payment_method->active();
425
+		// if the payment method really exists show its form, otherwise the activation template
426
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
427
+			$form = $this->_generate_payment_method_settings_form($payment_method);
428
+			if ($form->form_data_present_in($this->_req_data)) {
429
+				$form->receive_form_submission($this->_req_data);
430
+			}
431
+			echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
432
+		} else {
433
+			echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
434
+		}
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets the form for all the settings related to this payment method type
440
+	 *
441
+	 * @access protected
442
+	 * @param EE_Payment_Method $payment_method
443
+	 * @return EE_Form_Section_Proper
444
+	 */
445
+	protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
446
+	{
447
+		if (! $payment_method instanceof EE_Payment_Method) {
448
+			return new EE_Form_Section_Proper();
449
+		}
450
+		return new EE_Form_Section_Proper(
451
+			array(
452
+				'name'            => $payment_method->slug() . '_settings_form',
453
+				'html_id'         => $payment_method->slug() . '_settings_form',
454
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
455
+					array(
456
+						'action'         => 'update_payment_method',
457
+						'payment_method' => $payment_method->slug(),
458
+					),
459
+					EE_PAYMENTS_ADMIN_URL
460
+				),
461
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
462
+				'subsections'     => apply_filters(
463
+					'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
464
+					array(
465
+						'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
466
+						'currency_support'        => $this->_currency_support($payment_method),
467
+						'payment_method_settings' => $this->_payment_method_settings($payment_method),
468
+						'update'                  => $this->_update_payment_method_button($payment_method),
469
+						'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
470
+						'fine_print'              => $this->_fine_print(),
471
+					),
472
+					$payment_method
473
+				),
474
+			)
475
+		);
476
+	}
477
+
478
+
479
+	/**
480
+	 * _pci_dss_compliance
481
+	 *
482
+	 * @access protected
483
+	 * @param EE_Payment_Method $payment_method
484
+	 * @return EE_Form_Section_Proper
485
+	 */
486
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
487
+	{
488
+		if ($payment_method->type_obj()->requires_https()) {
489
+			return new EE_Form_Section_HTML(
490
+				EEH_HTML::table(
491
+					EEH_HTML::tr(
492
+						EEH_HTML::th(
493
+							EEH_HTML::label(
494
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
495
+							)
496
+						) .
497
+						EEH_HTML::td(
498
+							EEH_HTML::strong(
499
+								__(
500
+									'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
501
+									'event_espresso'
502
+								)
503
+							)
504
+							.
505
+							EEH_HTML::br()
506
+							.
507
+							__('Learn more about ', 'event_espresso')
508
+							. EEH_HTML::link(
509
+								'https://www.pcisecuritystandards.org/merchants/index.php',
510
+								__('PCI DSS compliance', 'event_espresso')
511
+							)
512
+						)
513
+					)
514
+				)
515
+			);
516
+		} else {
517
+			return new EE_Form_Section_HTML('');
518
+		}
519
+	}
520
+
521
+
522
+	/**
523
+	 * _currency_support
524
+	 *
525
+	 * @access protected
526
+	 * @param EE_Payment_Method $payment_method
527
+	 * @return EE_Form_Section_Proper
528
+	 */
529
+	protected function _currency_support(EE_Payment_Method $payment_method)
530
+	{
531
+		if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
532
+			return new EE_Form_Section_HTML(
533
+				EEH_HTML::table(
534
+					EEH_HTML::tr(
535
+						EEH_HTML::th(
536
+							EEH_HTML::label(
537
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
538
+							)
539
+						) .
540
+						EEH_HTML::td(
541
+							EEH_HTML::strong(
542
+								sprintf(
543
+									__(
544
+										'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
545
+										'event_espresso'
546
+									),
547
+									EE_Config::instance()->currency->code
548
+								)
549
+							)
550
+						)
551
+					)
552
+				)
553
+			);
554
+		} else {
555
+			return new EE_Form_Section_HTML('');
556
+		}
557
+	}
558
+
559
+
560
+	/**
561
+	 * _update_payment_method_button
562
+	 *
563
+	 * @access protected
564
+	 * @param EE_Payment_Method $payment_method
565
+	 * @return EE_Payment_Method_Form
566
+	 */
567
+	protected function _payment_method_settings(EE_Payment_Method $payment_method)
568
+	{
569
+		// modify the form so we only have/show fields that will be implemented for this version
570
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
571
+	}
572
+
573
+
574
+	/**
575
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
576
+	 *
577
+	 * @param EE_Form_Section_Proper $form_section
578
+	 * @param string                 $payment_method_name
579
+	 * @return EE_Payment_Method_Form
580
+	 * @throws EE_Error
581
+	 */
582
+	protected function _simplify_form($form_section, $payment_method_name = '')
583
+	{
584
+		if ($form_section instanceof EE_Payment_Method_Form) {
585
+			$form_section->exclude(
586
+				array(
587
+					'PMD_type', // dont want them changing the type
588
+					'PMD_slug', // or the slug (probably never)
589
+					'PMD_wp_user', // or the user's ID
590
+					'Currency' // or the currency, until the rest of EE supports simultaneous currencies
591
+				)
592
+			);
593
+			return $form_section;
594
+		} else {
595
+			throw new EE_Error(
596
+				sprintf(
597
+					__(
598
+						'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
599
+						'event_espresso'
600
+					),
601
+					$payment_method_name
602
+				)
603
+			);
604
+		}
605
+	}
606
+
607
+
608
+	/**
609
+	 * _update_payment_method_button
610
+	 *
611
+	 * @access protected
612
+	 * @param EE_Payment_Method $payment_method
613
+	 * @return EE_Form_Section_HTML
614
+	 */
615
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method)
616
+	{
617
+		$update_button = new EE_Submit_Input(
618
+			array(
619
+				'name'       => 'submit',
620
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
621
+				'default'    => sprintf(
622
+					__('Update %s Payment Settings', 'event_espresso'),
623
+					$payment_method->admin_name()
624
+				),
625
+				'html_label' => EEH_HTML::nbsp(),
626
+			)
627
+		);
628
+		return new EE_Form_Section_HTML(
629
+			EEH_HTML::table(
630
+				EEH_HTML::no_row(EEH_HTML::br(2)) .
631
+				EEH_HTML::tr(
632
+					EEH_HTML::th(__('Update Settings', 'event_espresso')) .
633
+					EEH_HTML::td(
634
+						$update_button->get_html_for_input()
635
+					)
636
+				)
637
+			)
638
+		);
639
+	}
640
+
641
+
642
+	/**
643
+	 * _deactivate_payment_method_button
644
+	 *
645
+	 * @access protected
646
+	 * @param EE_Payment_Method $payment_method
647
+	 * @return EE_Form_Section_Proper
648
+	 */
649
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
650
+	{
651
+		$link_text_and_title = sprintf(
652
+			__('Deactivate %1$s Payments?', 'event_espresso'),
653
+			$payment_method->admin_name()
654
+		);
655
+		return new EE_Form_Section_HTML(
656
+			EEH_HTML::table(
657
+				EEH_HTML::tr(
658
+					EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
659
+					EEH_HTML::td(
660
+						EEH_HTML::link(
661
+							EE_Admin_Page::add_query_args_and_nonce(
662
+								array(
663
+									'action'         => 'deactivate_payment_method',
664
+									'payment_method' => $payment_method->slug(),
665
+								),
666
+								EE_PAYMENTS_ADMIN_URL
667
+							),
668
+							$link_text_and_title,
669
+							$link_text_and_title,
670
+							'deactivate_' . $payment_method->slug(),
671
+							'espresso-button button-secondary'
672
+						)
673
+					)
674
+				)
675
+			)
676
+		);
677
+	}
678
+
679
+
680
+	/**
681
+	 * _activate_payment_method_button
682
+	 *
683
+	 * @access protected
684
+	 * @param EE_Payment_Method $payment_method
685
+	 * @return EE_Form_Section_Proper
686
+	 */
687
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
688
+	{
689
+		$link_text_and_title = sprintf(
690
+			__('Activate %1$s Payment Method?', 'event_espresso'),
691
+			$payment_method->admin_name()
692
+		);
693
+		return new EE_Form_Section_Proper(
694
+			array(
695
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
696
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
697
+				'action'          => '#',
698
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
699
+				'subsections'     => apply_filters(
700
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
701
+					array(
702
+						new EE_Form_Section_HTML(
703
+							EEH_HTML::table(
704
+								EEH_HTML::tr(
705
+									EEH_HTML::td(
706
+										$payment_method->type_obj()->introductory_html(),
707
+										'',
708
+										'',
709
+										'',
710
+										'colspan="2"'
711
+									)
712
+								) .
713
+								EEH_HTML::tr(
714
+									EEH_HTML::th(
715
+										EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
716
+									) .
717
+									EEH_HTML::td(
718
+										EEH_HTML::link(
719
+											EE_Admin_Page::add_query_args_and_nonce(
720
+												array(
721
+													'action'              => 'activate_payment_method',
722
+													'payment_method_type' => $payment_method->type(),
723
+												),
724
+												EE_PAYMENTS_ADMIN_URL
725
+											),
726
+											$link_text_and_title,
727
+											$link_text_and_title,
728
+											'activate_' . $payment_method->slug(),
729
+											'espresso-button-green button-primary'
730
+										)
731
+									)
732
+								)
733
+							)
734
+						),
735
+					),
736
+					$payment_method
737
+				),
738
+			)
739
+		);
740
+	}
741
+
742
+
743
+	/**
744
+	 * _fine_print
745
+	 *
746
+	 * @access protected
747
+	 * @return EE_Form_Section_HTML
748
+	 */
749
+	protected function _fine_print()
750
+	{
751
+		return new EE_Form_Section_HTML(
752
+			EEH_HTML::table(
753
+				EEH_HTML::tr(
754
+					EEH_HTML::th() .
755
+					EEH_HTML::td(
756
+						EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
757
+					)
758
+				)
759
+			)
760
+		);
761
+	}
762
+
763
+
764
+	/**
765
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
766
+	 *
767
+	 * @global WP_User $current_user
768
+	 */
769
+	protected function _activate_payment_method()
770
+	{
771
+		if (isset($this->_req_data['payment_method_type'])) {
772
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
773
+			// see if one exists
774
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
775
+			$payment_method = EE_Payment_Method_Manager::instance()
776
+													   ->activate_a_payment_method_of_type($payment_method_type);
777
+			$this->_redirect_after_action(
778
+				1,
779
+				'Payment Method',
780
+				'activated',
781
+				array('action' => 'default', 'payment_method' => $payment_method->slug())
782
+			);
783
+		} else {
784
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
785
+		}
786
+	}
787
+
788
+
789
+	/**
790
+	 * Deactivates the payment method with the specified slug, and redirects.
791
+	 */
792
+	protected function _deactivate_payment_method()
793
+	{
794
+		if (isset($this->_req_data['payment_method'])) {
795
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
796
+			// deactivate it
797
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
798
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
799
+			$this->_redirect_after_action(
800
+				$count_updated,
801
+				'Payment Method',
802
+				'deactivated',
803
+				array('action' => 'default', 'payment_method' => $payment_method_slug)
804
+			);
805
+		} else {
806
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
807
+		}
808
+	}
809
+
810
+
811
+	/**
812
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
813
+	 * processing because we first need to identify WHICH form was processed and which payment method
814
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
815
+	 * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
816
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
817
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
818
+	 *
819
+	 * @return void
820
+	 */
821
+	protected function _update_payment_method()
822
+	{
823
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
824
+			// ok let's find which gateway form to use based on the form input
825
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
826
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
827
+			$correct_pmt_form_to_use = null;
828
+			$payment_method = null;
829
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
830
+				// get the form and simplify it, like what we do when we display it
831
+				$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
832
+				if ($pmt_form->form_data_present_in($this->_req_data)) {
833
+					$correct_pmt_form_to_use = $pmt_form;
834
+					break;
835
+				}
836
+			}
837
+			// if we couldn't find the correct payment method type...
838
+			if (! $correct_pmt_form_to_use) {
839
+				EE_Error::add_error(
840
+					__(
841
+						"We could not find which payment method type your form submission related to. Please contact support",
842
+						'event_espresso'
843
+					),
844
+					__FILE__,
845
+					__FUNCTION__,
846
+					__LINE__
847
+				);
848
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
849
+			}
850
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
851
+			if ($correct_pmt_form_to_use->is_valid()) {
852
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
853
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
854
+					throw new EE_Error(
855
+						sprintf(
856
+							__(
857
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
858
+								'event_espresso'
859
+							),
860
+							'payment_method_settings'
861
+						)
862
+					);
863
+				}
864
+				$payment_settings_subform->save();
865
+				/** @var $pm EE_Payment_Method */
866
+				$this->_redirect_after_action(
867
+					true,
868
+					'Payment Method',
869
+					'updated',
870
+					array('action' => 'default', 'payment_method' => $payment_method->slug())
871
+				);
872
+			} else {
873
+				EE_Error::add_error(
874
+					sprintf(
875
+						__(
876
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
877
+							'event_espresso'
878
+						),
879
+						$payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
880
+							: __('"(unknown)"', 'event_espresso')
881
+					),
882
+					__FILE__,
883
+					__FUNCTION__,
884
+					__LINE__
885
+				);
886
+			}
887
+		}
888
+		return;
889
+	}
890
+
891
+
892
+	/**
893
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
894
+	 * @throws DomainException
895
+	 * @throws EE_Error
896
+	 * @throws InvalidArgumentException
897
+	 * @throws InvalidDataTypeException
898
+	 * @throws InvalidInterfaceException
899
+	 */
900
+	protected function _payment_settings()
901
+	{
902
+		$form = $this->getPaymentSettingsForm();
903
+		$this->_set_add_edit_form_tags('update_payment_settings');
904
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
905
+		$this->_template_args['admin_page_content'] =  $form->get_html_and_js();
906
+		$this->display_admin_page_with_sidebar();
907
+	}
908
+
909
+
910
+	/**
911
+	 *        _update_payment_settings
912
+	 *
913
+	 * @access protected
914
+	 * @return void
915
+	 * @throws EE_Error
916
+	 * @throws InvalidArgumentException
917
+	 * @throws InvalidDataTypeException
918
+	 * @throws InvalidInterfaceException
919
+	 */
920
+	protected function _update_payment_settings()
921
+	{
922
+		$form = $this->getPaymentSettingsForm();
923
+		if ($form->was_submitted($this->_req_data)) {
924
+			$form->receive_form_submission($this->_req_data);
925
+			if ($form->is_valid()) {
926
+				/**
927
+				 * @var $reg_config EE_Registration_Config
928
+				 */
929
+				$loader = LoaderFactory::getLoader();
930
+				$reg_config = $loader->getShared('EE_Registration_Config');
931
+				$valid_data = $form->valid_data();
932
+				$reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
933
+				$reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
934
+			}
935
+		}
936
+		EE_Registry::instance()->CFG = apply_filters(
937
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
938
+			EE_Registry::instance()->CFG
939
+		);
940
+
941
+		$cfg =  EE_Registry::instance()->CFG ;
942
+
943
+		$what = __('Payment Settings', 'event_espresso');
944
+		$success = $this->_update_espresso_configuration(
945
+			$what,
946
+			EE_Registry::instance()->CFG,
947
+			__FILE__,
948
+			__FUNCTION__,
949
+			__LINE__
950
+		);
951
+		$this->_redirect_after_action(
952
+			$success,
953
+			$what,
954
+			__('updated', 'event_espresso'),
955
+			array('action' => 'payment_settings')
956
+		);
957
+	}
958
+
959
+
960
+	/**
961
+	 * Gets the form used for updating payment settings
962
+	 *
963
+	 * @return EE_Form_Section_Proper
964
+	 * @throws EE_Error
965
+	 * @throws InvalidArgumentException
966
+	 * @throws InvalidDataTypeException
967
+	 * @throws InvalidInterfaceException
968
+	 */
969
+	protected function getPaymentSettingsForm()
970
+	{
971
+		/**
972
+		 * @var $reg_config EE_Registration_Config
973
+		 */
974
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
975
+		return new EE_Form_Section_Proper(
976
+			array(
977
+				'name' => 'payment-settings',
978
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
979
+				'subsections' => array(
980
+					'show_pending_payment_options' => new EE_Yes_No_Input(
981
+						array(
982
+							'html_name' => 'show_pending_payment_options',
983
+							'default' => $reg_config->show_pending_payment_options,
984
+							'html_help_text' => esc_html__(
985
+								"If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
986
+								'event_espresso'
987
+							)
988
+						)
989
+					),
990
+					'gateway_log_lifespan' => new EE_Select_Input(
991
+						$reg_config->gatewayLogLifespanOptions(),
992
+						array(
993
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
994
+							'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
995
+							'default' => $reg_config->gateway_log_lifespan,
996
+						)
997
+					)
998
+				)
999
+			)
1000
+		);
1001
+	}
1002
+
1003
+
1004
+	protected function _payment_log_overview_list_table()
1005
+	{
1006
+		$this->display_admin_list_table_page_with_sidebar();
1007
+	}
1008
+
1009
+
1010
+	protected function _set_list_table_views_payment_log()
1011
+	{
1012
+		$this->_views = array(
1013
+			'all' => array(
1014
+				'slug'  => 'all',
1015
+				'label' => __('View All Logs', 'event_espresso'),
1016
+				'count' => 0,
1017
+			),
1018
+		);
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * @param int  $per_page
1024
+	 * @param int  $current_page
1025
+	 * @param bool $count
1026
+	 * @return array
1027
+	 */
1028
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1029
+	{
1030
+		EE_Registry::instance()->load_model('Change_Log');
1031
+		// we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1032
+		$query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1033
+		// check if they've selected a specific payment method
1034
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1035
+			$query_params[0]['OR*pm_or_pay_pm'] = array(
1036
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1037
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1038
+			);
1039
+		}
1040
+		// take into account search
1041
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1042
+			$similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1043
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1044
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1045
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1046
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1047
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1048
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1049
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1050
+			$query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1051
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1052
+			$query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1053
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1054
+		}
1055
+		if (isset($this->_req_data['payment-filter-start-date'])
1056
+			&& isset($this->_req_data['payment-filter-end-date'])
1057
+		) {
1058
+			// add date
1059
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1060
+			$end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1061
+			// make sure our timestamps start and end right at the boundaries for each day
1062
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1063
+			$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1064
+			// convert to timestamps
1065
+			$start_date = strtotime($start_date);
1066
+			$end_date = strtotime($end_date);
1067
+			// makes sure start date is the lowest value and vice versa
1068
+			$start_date = min($start_date, $end_date);
1069
+			$end_date = max($start_date, $end_date);
1070
+			// convert for query
1071
+			$start_date = EEM_Change_Log::instance()
1072
+										->convert_datetime_for_query(
1073
+											'LOG_time',
1074
+											date('Y-m-d H:i:s', $start_date),
1075
+											'Y-m-d H:i:s'
1076
+										);
1077
+			$end_date = EEM_Change_Log::instance()
1078
+									  ->convert_datetime_for_query(
1079
+										  'LOG_time',
1080
+										  date('Y-m-d H:i:s', $end_date),
1081
+										  'Y-m-d H:i:s'
1082
+									  );
1083
+			$query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1084
+		}
1085
+		if ($count) {
1086
+			return EEM_Change_Log::instance()->count($query_params);
1087
+		}
1088
+		if (isset($this->_req_data['order'])) {
1089
+			$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1090
+				: 'DESC';
1091
+			$query_params['order_by'] = array('LOG_time' => $sort);
1092
+		} else {
1093
+			$query_params['order_by'] = array('LOG_time' => 'DESC');
1094
+		}
1095
+		$offset = ($current_page - 1) * $per_page;
1096
+		if (! isset($this->_req_data['download_results'])) {
1097
+			$query_params['limit'] = array($offset, $per_page);
1098
+		}
1099
+		// now they've requested to instead just download the file instead of viewing it.
1100
+		if (isset($this->_req_data['download_results'])) {
1101
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1102
+			header('Content-Disposition: attachment');
1103
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1104
+			echo "<h1>Payment Logs for " . site_url() . "</h1>";
1105
+			echo "<h3>Query:</h3>";
1106
+			var_dump($query_params);
1107
+			echo "<h3>Results:</h3>";
1108
+			var_dump($wpdb_results);
1109
+			die;
1110
+		}
1111
+		$results = EEM_Change_Log::instance()->get_all($query_params);
1112
+		return $results;
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1118
+	 * because we're possibly combining the results from two queries
1119
+	 *
1120
+	 * @param EE_Change_Log $logA
1121
+	 * @param EE_Change_Log $logB
1122
+	 * @return int
1123
+	 */
1124
+	protected function _sort_logs_again($logA, $logB)
1125
+	{
1126
+		$timeA = $logA->get_raw('LOG_time');
1127
+		$timeB = $logB->get_raw('LOG_time');
1128
+		if ($timeA == $timeB) {
1129
+			return 0;
1130
+		}
1131
+		$comparison = $timeA < $timeB ? -1 : 1;
1132
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1133
+			return $comparison * -1;
1134
+		} else {
1135
+			return $comparison;
1136
+		}
1137
+	}
1138
+
1139
+
1140
+	protected function _payment_log_details()
1141
+	{
1142
+		EE_Registry::instance()->load_model('Change_Log');
1143
+		/** @var $payment_log EE_Change_Log */
1144
+		$payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1145
+		$payment_method = null;
1146
+		$transaction = null;
1147
+		if ($payment_log instanceof EE_Change_Log) {
1148
+			if ($payment_log->object() instanceof EE_Payment) {
1149
+				$payment_method = $payment_log->object()->payment_method();
1150
+				$transaction = $payment_log->object()->transaction();
1151
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1152
+				$payment_method = $payment_log->object();
1153
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1154
+				$transaction = $payment_log->object();
1155
+				$payment_method = $transaction->payment_method();
1156
+			}
1157
+		}
1158
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1159
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1160
+			array(
1161
+				'payment_log'    => $payment_log,
1162
+				'payment_method' => $payment_method,
1163
+				'transaction'    => $transaction,
1164
+			),
1165
+			true
1166
+		);
1167
+		$this->display_admin_page_with_sidebar();
1168
+	}
1169 1169
 }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page.core.php 1 patch
Indentation   +4541 added lines, -4541 removed lines patch added patch discarded remove patch
@@ -19,2642 +19,2642 @@  discard block
 block discarded – undo
19 19
 class Messages_Admin_Page extends EE_Admin_Page
20 20
 {
21 21
 
22
-    /**
23
-     * @type EE_Message_Resource_Manager $_message_resource_manager
24
-     */
25
-    protected $_message_resource_manager;
26
-
27
-    /**
28
-     * @type string $_active_message_type_name
29
-     */
30
-    protected $_active_message_type_name = '';
31
-
32
-    /**
33
-     * @type EE_messenger $_active_messenger
34
-     */
35
-    protected $_active_messenger;
36
-    protected $_activate_state;
37
-    protected $_activate_meta_box_type;
38
-    protected $_current_message_meta_box;
39
-    protected $_current_message_meta_box_object;
40
-    protected $_context_switcher;
41
-    protected $_shortcodes = array();
42
-    protected $_active_messengers = array();
43
-    protected $_active_message_types = array();
44
-
45
-    /**
46
-     * @var EE_Message_Template_Group $_message_template_group
47
-     */
48
-    protected $_message_template_group;
49
-    protected $_m_mt_settings = array();
50
-
51
-
52
-    /**
53
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
-     * IF there is no group then it gets automatically set to the Default template pack.
55
-     *
56
-     * @since 4.5.0
57
-     *
58
-     * @var EE_Messages_Template_Pack
59
-     */
60
-    protected $_template_pack;
61
-
62
-
63
-    /**
64
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
-     * group is.  If there is no group then it automatically gets set to default.
66
-     *
67
-     * @since 4.5.0
68
-     *
69
-     * @var string
70
-     */
71
-    protected $_variation;
72
-
73
-
74
-    /**
75
-     * @param bool $routing
76
-     * @throws EE_Error
77
-     */
78
-    public function __construct($routing = true)
79
-    {
80
-        // make sure messages autoloader is running
81
-        EED_Messages::set_autoloaders();
82
-        parent::__construct($routing);
83
-    }
84
-
85
-
86
-    protected function _init_page_props()
87
-    {
88
-        $this->page_slug = EE_MSG_PG_SLUG;
89
-        $this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
-        $this->_admin_base_url = EE_MSG_ADMIN_URL;
91
-        $this->_admin_base_path = EE_MSG_ADMIN;
92
-
93
-        $this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
-            : array();
95
-
96
-        $this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
-        $this->_load_message_resource_manager();
98
-    }
99
-
100
-
101
-    /**
102
-     * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
-     *
104
-     * @throws EE_Error
105
-     * @throws InvalidDataTypeException
106
-     * @throws InvalidInterfaceException
107
-     * @throws InvalidArgumentException
108
-     * @throws ReflectionException
109
-     */
110
-    protected function _load_message_resource_manager()
111
-    {
112
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
-    }
114
-
115
-
116
-    /**
117
-     * @deprecated 4.9.9.rc.014
118
-     * @return array
119
-     * @throws EE_Error
120
-     * @throws InvalidArgumentException
121
-     * @throws InvalidDataTypeException
122
-     * @throws InvalidInterfaceException
123
-     */
124
-    public function get_messengers_for_list_table()
125
-    {
126
-        EE_Error::doing_it_wrong(
127
-            __METHOD__,
128
-            sprintf(
129
-                esc_html__(
130
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
-                    'event_espresso'
132
-                ),
133
-                'Messages_Admin_Page::get_messengers_select_input()'
134
-            ),
135
-            '4.9.9.rc.014'
136
-        );
137
-
138
-        $m_values = array();
139
-        $active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
-        // setup messengers for selects
141
-        $i = 1;
142
-        foreach ($active_messengers as $active_messenger) {
143
-            if ($active_messenger instanceof EE_Message) {
144
-                $m_values[ $i ]['id'] = $active_messenger->messenger();
145
-                $m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
-                $i++;
147
-            }
148
-        }
149
-
150
-        return $m_values;
151
-    }
152
-
153
-
154
-    /**
155
-     * @deprecated 4.9.9.rc.014
156
-     * @return array
157
-     * @throws EE_Error
158
-     * @throws InvalidArgumentException
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     */
162
-    public function get_message_types_for_list_table()
163
-    {
164
-        EE_Error::doing_it_wrong(
165
-            __METHOD__,
166
-            sprintf(
167
-                esc_html__(
168
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
-                    'event_espresso'
170
-                ),
171
-                'Messages_Admin_Page::get_message_types_select_input()'
172
-            ),
173
-            '4.9.9.rc.014'
174
-        );
175
-
176
-        $mt_values = array();
177
-        $active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
-        $i = 1;
179
-        foreach ($active_messages as $active_message) {
180
-            if ($active_message instanceof EE_Message) {
181
-                $mt_values[ $i ]['id'] = $active_message->message_type();
182
-                $mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
-                $i++;
184
-            }
185
-        }
186
-
187
-        return $mt_values;
188
-    }
189
-
190
-
191
-    /**
192
-     * @deprecated 4.9.9.rc.014
193
-     * @return array
194
-     * @throws EE_Error
195
-     * @throws InvalidArgumentException
196
-     * @throws InvalidDataTypeException
197
-     * @throws InvalidInterfaceException
198
-     */
199
-    public function get_contexts_for_message_types_for_list_table()
200
-    {
201
-        EE_Error::doing_it_wrong(
202
-            __METHOD__,
203
-            sprintf(
204
-                esc_html__(
205
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
-                    'event_espresso'
207
-                ),
208
-                'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
-            ),
210
-            '4.9.9.rc.014'
211
-        );
212
-
213
-        $contexts = array();
214
-        $active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
-        foreach ($active_message_contexts as $active_message) {
216
-            if ($active_message instanceof EE_Message) {
217
-                $message_type = $active_message->message_type_object();
218
-                if ($message_type instanceof EE_message_type) {
219
-                    $message_type_contexts = $message_type->get_contexts();
220
-                    foreach ($message_type_contexts as $context => $context_details) {
221
-                        $contexts[ $context ] = $context_details['label'];
222
-                    }
223
-                }
224
-            }
225
-        }
226
-
227
-        return $contexts;
228
-    }
229
-
230
-
231
-    /**
232
-     * Generate select input with provided messenger options array.
233
-     *
234
-     * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
-     *                                 labels.
236
-     * @return string
237
-     * @throws EE_Error
238
-     */
239
-    public function get_messengers_select_input($messenger_options)
240
-    {
241
-        // if empty or just one value then just return an empty string
242
-        if (empty($messenger_options)
243
-            || ! is_array($messenger_options)
244
-            || count($messenger_options) === 1
245
-        ) {
246
-            return '';
247
-        }
248
-        // merge in default
249
-        $messenger_options = array_merge(
250
-            array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
251
-            $messenger_options
252
-        );
253
-        $input = new EE_Select_Input(
254
-            $messenger_options,
255
-            array(
256
-                'html_name'  => 'ee_messenger_filter_by',
257
-                'html_id'    => 'ee_messenger_filter_by',
258
-                'html_class' => 'wide',
259
-                'default'    => isset($this->_req_data['ee_messenger_filter_by'])
260
-                    ? sanitize_title($this->_req_data['ee_messenger_filter_by'])
261
-                    : 'none_selected',
262
-            )
263
-        );
264
-
265
-        return $input->get_html_for_input();
266
-    }
267
-
268
-
269
-    /**
270
-     * Generate select input with provided message type options array.
271
-     *
272
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
273
-     *                                    message type labels
274
-     * @return string
275
-     * @throws EE_Error
276
-     */
277
-    public function get_message_types_select_input($message_type_options)
278
-    {
279
-        // if empty or count of options is 1 then just return an empty string
280
-        if (empty($message_type_options)
281
-            || ! is_array($message_type_options)
282
-            || count($message_type_options) === 1
283
-        ) {
284
-            return '';
285
-        }
286
-        // merge in default
287
-        $message_type_options = array_merge(
288
-            array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
289
-            $message_type_options
290
-        );
291
-        $input = new EE_Select_Input(
292
-            $message_type_options,
293
-            array(
294
-                'html_name'  => 'ee_message_type_filter_by',
295
-                'html_id'    => 'ee_message_type_filter_by',
296
-                'html_class' => 'wide',
297
-                'default'    => isset($this->_req_data['ee_message_type_filter_by'])
298
-                    ? sanitize_title($this->_req_data['ee_message_type_filter_by'])
299
-                    : 'none_selected',
300
-            )
301
-        );
302
-
303
-        return $input->get_html_for_input();
304
-    }
305
-
306
-
307
-    /**
308
-     * Generate select input with provide message type contexts array.
309
-     *
310
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
311
-     *                               context label.
312
-     * @return string
313
-     * @throws EE_Error
314
-     */
315
-    public function get_contexts_for_message_types_select_input($context_options)
316
-    {
317
-        // if empty or count of options is one then just return empty string
318
-        if (empty($context_options)
319
-            || ! is_array($context_options)
320
-            || count($context_options) === 1
321
-        ) {
322
-            return '';
323
-        }
324
-        // merge in default
325
-        $context_options = array_merge(
326
-            array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
327
-            $context_options
328
-        );
329
-        $input = new EE_Select_Input(
330
-            $context_options,
331
-            array(
332
-                'html_name'  => 'ee_context_filter_by',
333
-                'html_id'    => 'ee_context_filter_by',
334
-                'html_class' => 'wide',
335
-                'default'    => isset($this->_req_data['ee_context_filter_by'])
336
-                    ? sanitize_title($this->_req_data['ee_context_filter_by'])
337
-                    : 'none_selected',
338
-            )
339
-        );
340
-
341
-        return $input->get_html_for_input();
342
-    }
343
-
344
-
345
-    protected function _ajax_hooks()
346
-    {
347
-        add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
348
-        add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
349
-        add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
350
-        add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
351
-        add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
352
-        add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
353
-    }
354
-
355
-
356
-    protected function _define_page_props()
357
-    {
358
-        $this->_admin_page_title = $this->page_label;
359
-        $this->_labels = array(
360
-            'buttons'    => array(
361
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
362
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
363
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
364
-            ),
365
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
366
-        );
367
-    }
368
-
369
-
370
-    /**
371
-     *        an array for storing key => value pairs of request actions and their corresponding methods
372
-     *
373
-     * @access protected
374
-     * @return void
375
-     */
376
-    protected function _set_page_routes()
377
-    {
378
-        $grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
379
-            ? $this->_req_data['GRP_ID']
380
-            : 0;
381
-        $grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
382
-            ? $this->_req_data['id']
383
-            : $grp_id;
384
-        $msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
385
-            ? $this->_req_data['MSG_ID']
386
-            : 0;
387
-
388
-        $this->_page_routes = array(
389
-            'default'                          => array(
390
-                'func'       => '_message_queue_list_table',
391
-                'capability' => 'ee_read_global_messages',
392
-            ),
393
-            'global_mtps'                      => array(
394
-                'func'       => '_ee_default_messages_overview_list_table',
395
-                'capability' => 'ee_read_global_messages',
396
-            ),
397
-            'custom_mtps'                      => array(
398
-                'func'       => '_custom_mtps_preview',
399
-                'capability' => 'ee_read_messages',
400
-            ),
401
-            'add_new_message_template'         => array(
402
-                'func'       => '_add_message_template',
403
-                'capability' => 'ee_edit_messages',
404
-                'noheader'   => true,
405
-            ),
406
-            'edit_message_template'            => array(
407
-                'func'       => '_edit_message_template',
408
-                'capability' => 'ee_edit_message',
409
-                'obj_id'     => $grp_id,
410
-            ),
411
-            'preview_message'                  => array(
412
-                'func'               => '_preview_message',
413
-                'capability'         => 'ee_read_message',
414
-                'obj_id'             => $grp_id,
415
-                'noheader'           => true,
416
-                'headers_sent_route' => 'display_preview_message',
417
-            ),
418
-            'display_preview_message'          => array(
419
-                'func'       => '_display_preview_message',
420
-                'capability' => 'ee_read_message',
421
-                'obj_id'     => $grp_id,
422
-            ),
423
-            'insert_message_template'          => array(
424
-                'func'       => '_insert_or_update_message_template',
425
-                'capability' => 'ee_edit_messages',
426
-                'args'       => array('new_template' => true),
427
-                'noheader'   => true,
428
-            ),
429
-            'update_message_template'          => array(
430
-                'func'       => '_insert_or_update_message_template',
431
-                'capability' => 'ee_edit_message',
432
-                'obj_id'     => $grp_id,
433
-                'args'       => array('new_template' => false),
434
-                'noheader'   => true,
435
-            ),
436
-            'trash_message_template'           => array(
437
-                'func'       => '_trash_or_restore_message_template',
438
-                'capability' => 'ee_delete_message',
439
-                'obj_id'     => $grp_id,
440
-                'args'       => array('trash' => true, 'all' => true),
441
-                'noheader'   => true,
442
-            ),
443
-            'trash_message_template_context'   => array(
444
-                'func'       => '_trash_or_restore_message_template',
445
-                'capability' => 'ee_delete_message',
446
-                'obj_id'     => $grp_id,
447
-                'args'       => array('trash' => true),
448
-                'noheader'   => true,
449
-            ),
450
-            'restore_message_template'         => array(
451
-                'func'       => '_trash_or_restore_message_template',
452
-                'capability' => 'ee_delete_message',
453
-                'obj_id'     => $grp_id,
454
-                'args'       => array('trash' => false, 'all' => true),
455
-                'noheader'   => true,
456
-            ),
457
-            'restore_message_template_context' => array(
458
-                'func'       => '_trash_or_restore_message_template',
459
-                'capability' => 'ee_delete_message',
460
-                'obj_id'     => $grp_id,
461
-                'args'       => array('trash' => false),
462
-                'noheader'   => true,
463
-            ),
464
-            'delete_message_template'          => array(
465
-                'func'       => '_delete_message_template',
466
-                'capability' => 'ee_delete_message',
467
-                'obj_id'     => $grp_id,
468
-                'noheader'   => true,
469
-            ),
470
-            'reset_to_default'                 => array(
471
-                'func'       => '_reset_to_default_template',
472
-                'capability' => 'ee_edit_message',
473
-                'obj_id'     => $grp_id,
474
-                'noheader'   => true,
475
-            ),
476
-            'settings'                         => array(
477
-                'func'       => '_settings',
478
-                'capability' => 'manage_options',
479
-            ),
480
-            'update_global_settings'           => array(
481
-                'func'       => '_update_global_settings',
482
-                'capability' => 'manage_options',
483
-                'noheader'   => true,
484
-            ),
485
-            'generate_now'                     => array(
486
-                'func'       => '_generate_now',
487
-                'capability' => 'ee_send_message',
488
-                'noheader'   => true,
489
-            ),
490
-            'generate_and_send_now'            => array(
491
-                'func'       => '_generate_and_send_now',
492
-                'capability' => 'ee_send_message',
493
-                'noheader'   => true,
494
-            ),
495
-            'queue_for_resending'              => array(
496
-                'func'       => '_queue_for_resending',
497
-                'capability' => 'ee_send_message',
498
-                'noheader'   => true,
499
-            ),
500
-            'send_now'                         => array(
501
-                'func'       => '_send_now',
502
-                'capability' => 'ee_send_message',
503
-                'noheader'   => true,
504
-            ),
505
-            'delete_ee_message'                => array(
506
-                'func'       => '_delete_ee_messages',
507
-                'capability' => 'ee_delete_messages',
508
-                'noheader'   => true,
509
-            ),
510
-            'delete_ee_messages'               => array(
511
-                'func'       => '_delete_ee_messages',
512
-                'capability' => 'ee_delete_messages',
513
-                'noheader'   => true,
514
-                'obj_id'     => $msg_id,
515
-            ),
516
-        );
517
-    }
518
-
519
-
520
-    protected function _set_page_config()
521
-    {
522
-        $this->_page_config = array(
523
-            'default'                  => array(
524
-                'nav'           => array(
525
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
526
-                    'order' => 10,
527
-                ),
528
-                'list_table'    => 'EE_Message_List_Table',
529
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
530
-                'require_nonce' => false,
531
-            ),
532
-            'global_mtps'              => array(
533
-                'nav'           => array(
534
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
535
-                    'order' => 20,
536
-                ),
537
-                'list_table'    => 'Messages_Template_List_Table',
538
-                'help_tabs'     => array(
539
-                    'messages_overview_help_tab'                                => array(
540
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
541
-                        'filename' => 'messages_overview',
542
-                    ),
543
-                    'messages_overview_messages_table_column_headings_help_tab' => array(
544
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
545
-                        'filename' => 'messages_overview_table_column_headings',
546
-                    ),
547
-                    'messages_overview_messages_filters_help_tab'               => array(
548
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
549
-                        'filename' => 'messages_overview_filters',
550
-                    ),
551
-                    'messages_overview_messages_views_help_tab'                 => array(
552
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
553
-                        'filename' => 'messages_overview_views',
554
-                    ),
555
-                    'message_overview_message_types_help_tab'                   => array(
556
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
557
-                        'filename' => 'messages_overview_types',
558
-                    ),
559
-                    'messages_overview_messengers_help_tab'                     => array(
560
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
561
-                        'filename' => 'messages_overview_messengers',
562
-                    ),
563
-                ),
564
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
565
-                // 'help_tour'     => array('Messages_Overview_Help_Tour'),
566
-                'require_nonce' => false,
567
-            ),
568
-            'custom_mtps'              => array(
569
-                'nav'           => array(
570
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
571
-                    'order' => 30,
572
-                ),
573
-                'help_tabs'     => array(),
574
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
575
-                // 'help_tour'     => array(),
576
-                'require_nonce' => false,
577
-            ),
578
-            'add_new_message_template' => array(
579
-                'nav'           => array(
580
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
581
-                    'order'      => 5,
582
-                    'persistent' => false,
583
-                ),
584
-                'require_nonce' => false,
585
-            ),
586
-            'edit_message_template'    => array(
587
-                'labels'        => array(
588
-                    'buttons'    => array(
589
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
590
-                    ),
591
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
592
-                ),
593
-                'nav'           => array(
594
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
595
-                    'order'      => 5,
596
-                    'persistent' => false,
597
-                    'url'        => '',
598
-                ),
599
-                'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
600
-                'has_metaboxes' => true,
601
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
602
-                // 'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
603
-                'help_tabs'     => array(
604
-                    'edit_message_template'            => array(
605
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
606
-                        'callback' => 'edit_message_template_help_tab',
607
-                    ),
608
-                    'message_templates_help_tab'       => array(
609
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
610
-                        'filename' => 'messages_templates',
611
-                    ),
612
-                    'message_template_shortcodes'      => array(
613
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
614
-                        'callback' => 'message_template_shortcodes_help_tab',
615
-                    ),
616
-                    'message_preview_help_tab'         => array(
617
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
618
-                        'filename' => 'messages_preview',
619
-                    ),
620
-                    'messages_overview_other_help_tab' => array(
621
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
622
-                        'filename' => 'messages_overview_other',
623
-                    ),
624
-                ),
625
-                'require_nonce' => false,
626
-            ),
627
-            'display_preview_message'  => array(
628
-                'nav'           => array(
629
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
630
-                    'order'      => 5,
631
-                    'url'        => '',
632
-                    'persistent' => false,
633
-                ),
634
-                'help_tabs'     => array(
635
-                    'preview_message' => array(
636
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
637
-                        'callback' => 'preview_message_help_tab',
638
-                    ),
639
-                ),
640
-                'require_nonce' => false,
641
-            ),
642
-            'settings'                 => array(
643
-                'nav'           => array(
644
-                    'label' => esc_html__('Settings', 'event_espresso'),
645
-                    'order' => 40,
646
-                ),
647
-                'metaboxes'     => array('_messages_settings_metaboxes'),
648
-                'help_tabs'     => array(
649
-                    'messages_settings_help_tab'               => array(
650
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
651
-                        'filename' => 'messages_settings',
652
-                    ),
653
-                    'messages_settings_message_types_help_tab' => array(
654
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
655
-                        'filename' => 'messages_settings_message_types',
656
-                    ),
657
-                    'messages_settings_messengers_help_tab'    => array(
658
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
659
-                        'filename' => 'messages_settings_messengers',
660
-                    ),
661
-                ),
662
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
663
-                // 'help_tour'     => array('Messages_Settings_Help_Tour'),
664
-                'require_nonce' => false,
665
-            ),
666
-        );
667
-    }
668
-
669
-
670
-    protected function _add_screen_options()
671
-    {
672
-        // todo
673
-    }
674
-
675
-
676
-    protected function _add_screen_options_global_mtps()
677
-    {
678
-        /**
679
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
680
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
681
-         */
682
-        $page_title = $this->_admin_page_title;
683
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
684
-        $this->_per_page_screen_option();
685
-        $this->_admin_page_title = $page_title;
686
-    }
687
-
688
-
689
-    protected function _add_screen_options_default()
690
-    {
691
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
692
-        $this->_per_page_screen_option();
693
-    }
694
-
695
-
696
-    // none of the below group are currently used for Messages
697
-    protected function _add_feature_pointers()
698
-    {
699
-    }
700
-
701
-    public function admin_init()
702
-    {
703
-    }
704
-
705
-    public function admin_notices()
706
-    {
707
-    }
708
-
709
-    public function admin_footer_scripts()
710
-    {
711
-    }
712
-
713
-
714
-    public function messages_help_tab()
715
-    {
716
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
717
-    }
718
-
719
-
720
-    public function messengers_help_tab()
721
-    {
722
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
723
-    }
724
-
725
-
726
-    public function message_types_help_tab()
727
-    {
728
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
729
-    }
730
-
731
-
732
-    public function messages_overview_help_tab()
733
-    {
734
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
735
-    }
736
-
737
-
738
-    public function message_templates_help_tab()
739
-    {
740
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
741
-    }
742
-
743
-
744
-    public function edit_message_template_help_tab()
745
-    {
746
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
747
-                        . esc_attr__('Editor Title', 'event_espresso')
748
-                        . '" />';
749
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
750
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
751
-                        . '" />';
752
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
753
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
754
-                        . '" />';
755
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
756
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
757
-                        . '" />';
758
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
759
-                        . esc_attr__('Publish Metabox', 'event_espresso')
760
-                        . '" />';
761
-        EEH_Template::display_template(
762
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
763
-            $args
764
-        );
765
-    }
766
-
767
-
768
-    public function message_template_shortcodes_help_tab()
769
-    {
770
-        $this->_set_shortcodes();
771
-        $args['shortcodes'] = $this->_shortcodes;
772
-        EEH_Template::display_template(
773
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
774
-            $args
775
-        );
776
-    }
777
-
778
-
779
-    public function preview_message_help_tab()
780
-    {
781
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
782
-    }
783
-
784
-
785
-    public function settings_help_tab()
786
-    {
787
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
788
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
789
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
790
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
791
-        $args['img3'] = '<div class="switch">'
792
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
793
-                        . ' type="checkbox" checked="checked">'
794
-                        . '<label for="ee-on-off-toggle-on"></label>'
795
-                        . '</div>';
796
-        $args['img4'] = '<div class="switch">'
797
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
798
-                        . ' type="checkbox">'
799
-                        . '<label for="ee-on-off-toggle-on"></label>'
800
-                        . '</div>';
801
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
802
-    }
803
-
804
-
805
-    public function load_scripts_styles()
806
-    {
807
-        wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
808
-        wp_enqueue_style('espresso_ee_msg');
809
-
810
-        wp_register_script(
811
-            'ee-messages-settings',
812
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
813
-            array('jquery-ui-droppable', 'ee-serialize-full-array'),
814
-            EVENT_ESPRESSO_VERSION,
815
-            true
816
-        );
817
-        wp_register_script(
818
-            'ee-msg-list-table-js',
819
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
820
-            array('ee-dialog'),
821
-            EVENT_ESPRESSO_VERSION
822
-        );
823
-    }
824
-
825
-
826
-    public function load_scripts_styles_default()
827
-    {
828
-        wp_enqueue_script('ee-msg-list-table-js');
829
-    }
830
-
831
-
832
-    public function wp_editor_css($mce_css)
833
-    {
834
-        // if we're on the edit_message_template route
835
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
836
-            $message_type_name = $this->_active_message_type_name;
837
-
838
-            // we're going to REPLACE the existing mce css
839
-            // we need to get the css file location from the active messenger
840
-            $mce_css = $this->_active_messenger->get_variation(
841
-                $this->_template_pack,
842
-                $message_type_name,
843
-                true,
844
-                'wpeditor',
845
-                $this->_variation
846
-            );
847
-        }
848
-
849
-        return $mce_css;
850
-    }
851
-
852
-
853
-    public function load_scripts_styles_edit_message_template()
854
-    {
855
-
856
-        $this->_set_shortcodes();
857
-
858
-        EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
859
-            esc_html__(
860
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
861
-                'event_espresso'
862
-            ),
863
-            $this->_message_template_group->messenger_obj()->label['singular'],
864
-            $this->_message_template_group->message_type_obj()->label['singular']
865
-        );
866
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
867
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
868
-            'event_espresso'
869
-        );
870
-        EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
871
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
872
-            'event_espresso'
873
-        );
874
-
875
-        wp_register_script(
876
-            'ee_msgs_edit_js',
877
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
878
-            array('jquery'),
879
-            EVENT_ESPRESSO_VERSION
880
-        );
881
-
882
-        wp_enqueue_script('ee_admin_js');
883
-        wp_enqueue_script('ee_msgs_edit_js');
884
-
885
-        // add in special css for tiny_mce
886
-        add_filter('mce_css', array($this, 'wp_editor_css'));
887
-    }
888
-
889
-
890
-    public function load_scripts_styles_display_preview_message()
891
-    {
892
-
893
-        $this->_set_message_template_group();
894
-
895
-        if (isset($this->_req_data['messenger'])) {
896
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
897
-                $this->_req_data['messenger']
898
-            );
899
-        }
900
-
901
-        $message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
902
-
903
-
904
-        wp_enqueue_style(
905
-            'espresso_preview_css',
906
-            $this->_active_messenger->get_variation(
907
-                $this->_template_pack,
908
-                $message_type_name,
909
-                true,
910
-                'preview',
911
-                $this->_variation
912
-            )
913
-        );
914
-    }
915
-
916
-
917
-    public function load_scripts_styles_settings()
918
-    {
919
-        wp_register_style(
920
-            'ee-message-settings',
921
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
922
-            array(),
923
-            EVENT_ESPRESSO_VERSION
924
-        );
925
-        wp_enqueue_style('ee-text-links');
926
-        wp_enqueue_style('ee-message-settings');
927
-        wp_enqueue_script('ee-messages-settings');
928
-    }
929
-
930
-
931
-    /**
932
-     * set views array for List Table
933
-     */
934
-    public function _set_list_table_views_global_mtps()
935
-    {
936
-        $this->_views = array(
937
-            'in_use' => array(
938
-                'slug'  => 'in_use',
939
-                'label' => esc_html__('In Use', 'event_espresso'),
940
-                'count' => 0,
941
-            ),
942
-        );
943
-    }
944
-
945
-
946
-    /**
947
-     * Set views array for the Custom Template List Table
948
-     */
949
-    public function _set_list_table_views_custom_mtps()
950
-    {
951
-        $this->_set_list_table_views_global_mtps();
952
-        $this->_views['in_use']['bulk_action'] = array(
953
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
954
-        );
955
-    }
956
-
957
-
958
-    /**
959
-     * set views array for message queue list table
960
-     *
961
-     * @throws InvalidDataTypeException
962
-     * @throws InvalidInterfaceException
963
-     * @throws InvalidArgumentException
964
-     * @throws EE_Error
965
-     * @throws ReflectionException
966
-     */
967
-    public function _set_list_table_views_default()
968
-    {
969
-        EE_Registry::instance()->load_helper('Template');
970
-
971
-        $common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
972
-            'ee_send_message',
973
-            'message_list_table_bulk_actions'
974
-        )
975
-            ? array(
976
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
977
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
978
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
979
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
980
-            )
981
-            : array();
982
-
983
-        $delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
984
-            'ee_delete_messages',
985
-            'message_list_table_bulk_actions'
986
-        )
987
-            ? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
988
-            : array();
989
-
990
-
991
-        $this->_views = array(
992
-            'all' => array(
993
-                'slug'        => 'all',
994
-                'label'       => esc_html__('All', 'event_espresso'),
995
-                'count'       => 0,
996
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
997
-            ),
998
-        );
999
-
1000
-
1001
-        foreach (EEM_Message::instance()->all_statuses() as $status) {
1002
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1003
-                continue;
1004
-            }
1005
-            $status_bulk_actions = $common_bulk_actions;
1006
-            // unset bulk actions not applying to status
1007
-            if (! empty($status_bulk_actions)) {
1008
-                switch ($status) {
1009
-                    case EEM_Message::status_idle:
1010
-                    case EEM_Message::status_resend:
1011
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1012
-                        break;
1013
-
1014
-                    case EEM_Message::status_failed:
1015
-                    case EEM_Message::status_debug_only:
1016
-                    case EEM_Message::status_messenger_executing:
1017
-                        $status_bulk_actions = array();
1018
-                        break;
1019
-
1020
-                    case EEM_Message::status_incomplete:
1021
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1022
-                        break;
1023
-
1024
-                    case EEM_Message::status_retry:
1025
-                    case EEM_Message::status_sent:
1026
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1027
-                        break;
1028
-                }
1029
-            }
1030
-
1031
-            // skip adding messenger executing status to views because it will be included with the Failed view.
1032
-            if ($status === EEM_Message::status_messenger_executing) {
1033
-                continue;
1034
-            }
1035
-
1036
-            $this->_views[ strtolower($status) ] = array(
1037
-                'slug'        => strtolower($status),
1038
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1039
-                'count'       => 0,
1040
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1041
-            );
1042
-        }
1043
-    }
1044
-
1045
-
1046
-    protected function _ee_default_messages_overview_list_table()
1047
-    {
1048
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1049
-        $this->display_admin_list_table_page_with_no_sidebar();
1050
-    }
1051
-
1052
-
1053
-    protected function _message_queue_list_table()
1054
-    {
1055
-        $this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1056
-        $this->_template_args['per_column'] = 6;
1057
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1058
-        $this->_template_args['before_list_table'] = '<h3>'
1059
-                                                     . EEM_Message::instance()->get_pretty_label_for_results()
1060
-                                                     . '</h3>';
1061
-        $this->display_admin_list_table_page_with_no_sidebar();
1062
-    }
1063
-
1064
-
1065
-    protected function _message_legend_items()
1066
-    {
1067
-
1068
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1069
-        $action_items = array();
1070
-
1071
-        foreach ($action_css_classes as $action_item => $action_details) {
1072
-            if ($action_item === 'see_notifications_for') {
1073
-                continue;
1074
-            }
1075
-            $action_items[ $action_item ] = array(
1076
-                'class' => $action_details['css_class'],
1077
-                'desc'  => $action_details['label'],
1078
-            );
1079
-        }
1080
-
1081
-        /** @type array $status_items status legend setup */
1082
-        $status_items = array(
1083
-            'sent_status'                => array(
1084
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1085
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1086
-            ),
1087
-            'idle_status'                => array(
1088
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1089
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1090
-            ),
1091
-            'failed_status'              => array(
1092
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1093
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1094
-            ),
1095
-            'messenger_executing_status' => array(
1096
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1097
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1098
-            ),
1099
-            'resend_status'              => array(
1100
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1101
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1102
-            ),
1103
-            'incomplete_status'          => array(
1104
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1105
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1106
-            ),
1107
-            'retry_status'               => array(
1108
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1109
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1110
-            ),
1111
-        );
1112
-        if (EEM_Message::debug()) {
1113
-            $status_items['debug_only_status'] = array(
1114
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1115
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1116
-            );
1117
-        }
1118
-
1119
-        return array_merge($action_items, $status_items);
1120
-    }
1121
-
1122
-
1123
-    protected function _custom_mtps_preview()
1124
-    {
1125
-        $this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1126
-        $this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1127
-                                               . ' alt="' . esc_attr__(
1128
-                                                   'Preview Custom Message Templates screenshot',
1129
-                                                   'event_espresso'
1130
-                                               ) . '" />';
1131
-        $this->_template_args['preview_text'] = '<strong>'
1132
-                                                . esc_html__(
1133
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1134
-                                                    'event_espresso'
1135
-                                                )
1136
-                                                . '</strong>';
1137
-
1138
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * get_message_templates
1144
-     * This gets all the message templates for listing on the overview list.
1145
-     *
1146
-     * @access public
1147
-     * @param int    $perpage the amount of templates groups to show per page
1148
-     * @param string $type    the current _view we're getting templates for
1149
-     * @param bool   $count   return count?
1150
-     * @param bool   $all     disregard any paging info (get all data);
1151
-     * @param bool   $global  whether to return just global (true) or custom templates (false)
1152
-     * @return array
1153
-     * @throws EE_Error
1154
-     * @throws InvalidArgumentException
1155
-     * @throws InvalidDataTypeException
1156
-     * @throws InvalidInterfaceException
1157
-     */
1158
-    public function get_message_templates(
1159
-        $perpage = 10,
1160
-        $type = 'in_use',
1161
-        $count = false,
1162
-        $all = false,
1163
-        $global = true
1164
-    ) {
1165
-
1166
-        $MTP = EEM_Message_Template_Group::instance();
1167
-
1168
-        $this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1169
-        $orderby = $this->_req_data['orderby'];
1170
-
1171
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1172
-            ? $this->_req_data['order']
1173
-            : 'ASC';
1174
-
1175
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1176
-            ? $this->_req_data['paged']
1177
-            : 1;
1178
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1179
-            ? $this->_req_data['perpage']
1180
-            : $perpage;
1181
-
1182
-        $offset = ($current_page - 1) * $per_page;
1183
-        $limit = $all ? null : array($offset, $per_page);
1184
-
1185
-
1186
-        // options will match what is in the _views array property
1187
-        switch ($type) {
1188
-            case 'in_use':
1189
-                $templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1190
-                break;
1191
-            default:
1192
-                $templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1193
-        }
1194
-
1195
-        return $templates;
1196
-    }
1197
-
1198
-
1199
-    /**
1200
-     * filters etc might need a list of installed message_types
1201
-     *
1202
-     * @return array an array of message type objects
1203
-     */
1204
-    public function get_installed_message_types()
1205
-    {
1206
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1207
-        $installed = array();
1208
-
1209
-        foreach ($installed_message_types as $message_type) {
1210
-            $installed[ $message_type->name ] = $message_type;
1211
-        }
1212
-
1213
-        return $installed;
1214
-    }
1215
-
1216
-
1217
-    /**
1218
-     * _add_message_template
1219
-     *
1220
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1221
-     *
1222
-     * @param string $message_type
1223
-     * @param string $messenger
1224
-     * @param string $GRP_ID
1225
-     *
1226
-     * @throws EE_error
1227
-     */
1228
-    protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1229
-    {
1230
-        // set values override any request data
1231
-        $message_type = ! empty($message_type) ? $message_type : '';
1232
-        $message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1233
-            ? $this->_req_data['message_type']
1234
-            : $message_type;
1235
-
1236
-        $messenger = ! empty($messenger) ? $messenger : '';
1237
-        $messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1238
-            ? $this->_req_data['messenger']
1239
-            : $messenger;
1240
-
1241
-        $GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1242
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1243
-
1244
-        // we need messenger and message type.  They should be coming from the event editor. If not here then return error
1245
-        if (empty($message_type) || empty($messenger)) {
1246
-            throw new EE_Error(
1247
-                esc_html__(
1248
-                    'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1249
-                    'event_espresso'
1250
-                )
1251
-            );
1252
-        }
1253
-
1254
-        // we need the GRP_ID for the template being used as the base for the new template
1255
-        if (empty($GRP_ID)) {
1256
-            throw new EE_Error(
1257
-                esc_html__(
1258
-                    'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1259
-                    'event_espresso'
1260
-                )
1261
-            );
1262
-        }
1263
-
1264
-        // let's just make sure the template gets generated!
1265
-
1266
-        // we need to reassign some variables for what the insert is expecting
1267
-        $this->_req_data['MTP_messenger'] = $messenger;
1268
-        $this->_req_data['MTP_message_type'] = $message_type;
1269
-        $this->_req_data['GRP_ID'] = $GRP_ID;
1270
-        $this->_insert_or_update_message_template(true);
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * public wrapper for the _add_message_template method
1276
-     *
1277
-     * @param string $message_type     message type slug
1278
-     * @param string $messenger        messenger slug
1279
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1280
-     *                                 off of.
1281
-     * @throws EE_error
1282
-     */
1283
-    public function add_message_template($message_type, $messenger, $GRP_ID)
1284
-    {
1285
-        $this->_add_message_template($message_type, $messenger, $GRP_ID);
1286
-    }
1287
-
1288
-
1289
-    /**
1290
-     * _edit_message_template
1291
-     *
1292
-     * @access protected
1293
-     * @return void
1294
-     * @throws InvalidIdentifierException
1295
-     * @throws DomainException
1296
-     * @throws EE_Error
1297
-     * @throws InvalidArgumentException
1298
-     * @throws ReflectionException
1299
-     * @throws InvalidDataTypeException
1300
-     * @throws InvalidInterfaceException
1301
-     */
1302
-    protected function _edit_message_template()
1303
-    {
1304
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1305
-        $template_fields = '';
1306
-        $sidebar_fields = '';
1307
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1308
-        // valid html in the templates.
1309
-        add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1310
-
1311
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1312
-            ? absint($this->_req_data['id'])
1313
-            : false;
1314
-
1315
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1316
-        ? absint($this->_req_data['evt_id'])
1317
-        : false;
1318
-
1319
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1320
-        $message_template_group = $this->_message_template_group;
1321
-        $c_label = $message_template_group->context_label();
1322
-        $c_config = $message_template_group->contexts_config();
1323
-
1324
-        reset($c_config);
1325
-        $context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1326
-            ? strtolower($this->_req_data['context'])
1327
-            : key($c_config);
1328
-
1329
-
1330
-        if (empty($GRP_ID)) {
1331
-            $action = 'insert_message_template';
1332
-            $edit_message_template_form_url = add_query_arg(
1333
-                array('action' => $action, 'noheader' => true),
1334
-                EE_MSG_ADMIN_URL
1335
-            );
1336
-        } else {
1337
-            $action = 'update_message_template';
1338
-            $edit_message_template_form_url = add_query_arg(
1339
-                array('action' => $action, 'noheader' => true),
1340
-                EE_MSG_ADMIN_URL
1341
-            );
1342
-        }
1343
-
1344
-        // set active messenger for this view
1345
-        $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1346
-            $message_template_group->messenger()
1347
-        );
1348
-        $this->_active_message_type_name = $message_template_group->message_type();
1349
-
1350
-
1351
-        // Do we have any validation errors?
1352
-        $validators = $this->_get_transient();
1353
-        $v_fields = ! empty($validators) ? array_keys($validators) : array();
1354
-
1355
-
1356
-        // we need to assemble the title from Various details
1357
-        $context_label = sprintf(
1358
-            esc_html__('(%s %s)', 'event_espresso'),
1359
-            $c_config[ $context ]['label'],
1360
-            ucwords($c_label['label'])
1361
-        );
1362
-
1363
-        $title = sprintf(
1364
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1365
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1366
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1367
-            $context_label
1368
-        );
1369
-
1370
-        $this->_template_args['GRP_ID'] = $GRP_ID;
1371
-        $this->_template_args['message_template'] = $message_template_group;
1372
-        $this->_template_args['is_extra_fields'] = false;
1373
-
1374
-
1375
-        // let's get EEH_MSG_Template so we can get template form fields
1376
-        $template_field_structure = EEH_MSG_Template::get_fields(
1377
-            $message_template_group->messenger(),
1378
-            $message_template_group->message_type()
1379
-        );
1380
-
1381
-        if (! $template_field_structure) {
1382
-            $template_field_structure = false;
1383
-            $template_fields = esc_html__(
1384
-                'There was an error in assembling the fields for this display (you should see an error message)',
1385
-                'event_espresso'
1386
-            );
1387
-        }
1388
-
1389
-
1390
-        $message_templates = $message_template_group->context_templates();
1391
-
1392
-
1393
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1394
-        // will get handled in the "extra" array.
1395
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1396
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1397
-                unset($template_field_structure[ $context ][ $reference_field ]);
1398
-            }
1399
-        }
1400
-
1401
-        // let's loop through the template_field_structure and actually assemble the input fields!
1402
-        if (! empty($template_field_structure)) {
1403
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1404
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1405
-                // the extra array and reset them.
1406
-                if ($template_field === 'extra') {
1407
-                    $this->_template_args['is_extra_fields'] = true;
1408
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1409
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1410
-                        $content = $message_template instanceof EE_Message_Template
1411
-                            ? $message_template->get('MTP_content')
1412
-                            : '';
1413
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1414
-                            // let's verify if we need this extra field via the shortcodes parameter.
1415
-                            $continue = false;
1416
-                            if (isset($extra_array['shortcodes_required'])) {
1417
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1418
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1419
-                                        $continue = true;
1420
-                                    }
1421
-                                }
1422
-                                if ($continue) {
1423
-                                    continue;
1424
-                                }
1425
-                            }
1426
-
1427
-                            $field_id = $reference_field
1428
-                                        . '-'
1429
-                                        . $extra_field
1430
-                                        . '-content';
1431
-                            $template_form_fields[ $field_id ] = $extra_array;
1432
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1433
-                                                                         . $reference_field
1434
-                                                                         . '][content]['
1435
-                                                                         . $extra_field . ']';
1436
-                            $css_class = isset($extra_array['css_class'])
1437
-                                ? $extra_array['css_class']
1438
-                                : '';
1439
-
1440
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1441
-                                                                              && in_array($extra_field, $v_fields, true)
1442
-                                                                              &&
1443
-                                                                              (
1444
-                                                                                  is_array($validators[ $extra_field ])
1445
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1446
-                                                                              )
1447
-                                ? 'validate-error ' . $css_class
1448
-                                : $css_class;
1449
-
1450
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1451
-                                                                          && isset($content[ $extra_field ])
1452
-                                ? $content[ $extra_field ]
1453
-                                : '';
1454
-
1455
-                            // do we have a validation error?  if we do then let's use that value instead
1456
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1457
-                                ? $validators[ $extra_field ]['value']
1458
-                                : $template_form_fields[ $field_id ]['value'];
1459
-
1460
-
1461
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1462
-
1463
-                            // shortcode selector
1464
-                            $field_name_to_use = $extra_field === 'main'
1465
-                                ? 'content'
1466
-                                : $extra_field;
1467
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1468
-                                $field_name_to_use,
1469
-                                $field_id
1470
-                            );
1471
-
1472
-                            if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1473
-                                // we want to decode the entities
1474
-                                $template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1475
-                            }/**/
1476
-                        }
1477
-                        $templatefield_MTP_id = $reference_field . '-MTP_ID';
1478
-                        $templatefield_templatename_id = $reference_field . '-name';
1479
-
1480
-                        $template_form_fields[ $templatefield_MTP_id ] = array(
1481
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1482
-                            'label'      => null,
1483
-                            'input'      => 'hidden',
1484
-                            'type'       => 'int',
1485
-                            'required'   => false,
1486
-                            'validation' => false,
1487
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1488
-                            'css_class'  => '',
1489
-                            'format'     => '%d',
1490
-                            'db-col'     => 'MTP_ID',
1491
-                        );
1492
-
1493
-                        $template_form_fields[ $templatefield_templatename_id ] = array(
1494
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1495
-                            'label'      => null,
1496
-                            'input'      => 'hidden',
1497
-                            'type'       => 'string',
1498
-                            'required'   => false,
1499
-                            'validation' => true,
1500
-                            'value'      => $reference_field,
1501
-                            'css_class'  => '',
1502
-                            'format'     => '%s',
1503
-                            'db-col'     => 'MTP_template_field',
1504
-                        );
1505
-                    }
1506
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1507
-                } else {
1508
-                    $field_id = $template_field . '-content';
1509
-                    $template_form_fields[ $field_id ] = $field_setup_array;
1510
-                    $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1511
-                    $message_template = isset($message_templates[ $context ][ $template_field ])
1512
-                        ? $message_templates[ $context ][ $template_field ]
1513
-                        : null;
1514
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1515
-                                                                  && is_array($message_templates[ $context ])
1516
-                                                                  && $message_template instanceof EE_Message_Template
1517
-                        ? $message_template->get('MTP_content')
1518
-                        : '';
1519
-
1520
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1521
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1522
-                        ? $validators[ $template_field ]['value']
1523
-                        : $template_form_fields[ $field_id ]['value'];
1524
-
1525
-
1526
-                    $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1527
-                    $css_class = isset($field_setup_array['css_class'])
1528
-                        ? $field_setup_array['css_class']
1529
-                        : '';
1530
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1531
-                                                                      && in_array($template_field, $v_fields, true)
1532
-                                                                      && isset($validators[ $template_field ]['msg'])
1533
-                        ? 'validate-error ' . $css_class
1534
-                        : $css_class;
1535
-
1536
-                    // shortcode selector
1537
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1538
-                        $template_field,
1539
-                        $field_id
1540
-                    );
1541
-                }
1542
-
1543
-                // k took care of content field(s) now let's take care of others.
1544
-
1545
-                $templatefield_MTP_id = $template_field . '-MTP_ID';
1546
-                $templatefield_field_templatename_id = $template_field . '-name';
1547
-
1548
-                // foreach template field there are actually two form fields created
1549
-                $template_form_fields[ $templatefield_MTP_id ] = array(
1550
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1551
-                    'label'      => null,
1552
-                    'input'      => 'hidden',
1553
-                    'type'       => 'int',
1554
-                    'required'   => false,
1555
-                    'validation' => true,
1556
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1557
-                    'css_class'  => '',
1558
-                    'format'     => '%d',
1559
-                    'db-col'     => 'MTP_ID',
1560
-                );
1561
-
1562
-                $template_form_fields[ $templatefield_field_templatename_id ] = array(
1563
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1564
-                    'label'      => null,
1565
-                    'input'      => 'hidden',
1566
-                    'type'       => 'string',
1567
-                    'required'   => false,
1568
-                    'validation' => true,
1569
-                    'value'      => $template_field,
1570
-                    'css_class'  => '',
1571
-                    'format'     => '%s',
1572
-                    'db-col'     => 'MTP_template_field',
1573
-                );
1574
-            }
1575
-
1576
-            // add other fields
1577
-            $template_form_fields['ee-msg-current-context'] = array(
1578
-                'name'       => 'MTP_context',
1579
-                'label'      => null,
1580
-                'input'      => 'hidden',
1581
-                'type'       => 'string',
1582
-                'required'   => false,
1583
-                'validation' => true,
1584
-                'value'      => $context,
1585
-                'css_class'  => '',
1586
-                'format'     => '%s',
1587
-                'db-col'     => 'MTP_context',
1588
-            );
1589
-
1590
-            $template_form_fields['ee-msg-grp-id'] = array(
1591
-                'name'       => 'GRP_ID',
1592
-                'label'      => null,
1593
-                'input'      => 'hidden',
1594
-                'type'       => 'int',
1595
-                'required'   => false,
1596
-                'validation' => true,
1597
-                'value'      => $GRP_ID,
1598
-                'css_class'  => '',
1599
-                'format'     => '%d',
1600
-                'db-col'     => 'GRP_ID',
1601
-            );
1602
-
1603
-            $template_form_fields['ee-msg-messenger'] = array(
1604
-                'name'       => 'MTP_messenger',
1605
-                'label'      => null,
1606
-                'input'      => 'hidden',
1607
-                'type'       => 'string',
1608
-                'required'   => false,
1609
-                'validation' => true,
1610
-                'value'      => $message_template_group->messenger(),
1611
-                'css_class'  => '',
1612
-                'format'     => '%s',
1613
-                'db-col'     => 'MTP_messenger',
1614
-            );
1615
-
1616
-            $template_form_fields['ee-msg-message-type'] = array(
1617
-                'name'       => 'MTP_message_type',
1618
-                'label'      => null,
1619
-                'input'      => 'hidden',
1620
-                'type'       => 'string',
1621
-                'required'   => false,
1622
-                'validation' => true,
1623
-                'value'      => $message_template_group->message_type(),
1624
-                'css_class'  => '',
1625
-                'format'     => '%s',
1626
-                'db-col'     => 'MTP_message_type',
1627
-            );
1628
-
1629
-            $sidebar_form_fields['ee-msg-is-global'] = array(
1630
-                'name'       => 'MTP_is_global',
1631
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1632
-                'input'      => 'hidden',
1633
-                'type'       => 'int',
1634
-                'required'   => false,
1635
-                'validation' => true,
1636
-                'value'      => $message_template_group->get('MTP_is_global'),
1637
-                'css_class'  => '',
1638
-                'format'     => '%d',
1639
-                'db-col'     => 'MTP_is_global',
1640
-            );
1641
-
1642
-            $sidebar_form_fields['ee-msg-is-override'] = array(
1643
-                'name'       => 'MTP_is_override',
1644
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1645
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1646
-                'type'       => 'int',
1647
-                'required'   => false,
1648
-                'validation' => true,
1649
-                'value'      => $message_template_group->get('MTP_is_override'),
1650
-                'css_class'  => '',
1651
-                'format'     => '%d',
1652
-                'db-col'     => 'MTP_is_override',
1653
-            );
1654
-
1655
-            $sidebar_form_fields['ee-msg-is-active'] = array(
1656
-                'name'       => 'MTP_is_active',
1657
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1658
-                'input'      => 'hidden',
1659
-                'type'       => 'int',
1660
-                'required'   => false,
1661
-                'validation' => true,
1662
-                'value'      => $message_template_group->is_active(),
1663
-                'css_class'  => '',
1664
-                'format'     => '%d',
1665
-                'db-col'     => 'MTP_is_active',
1666
-            );
1667
-
1668
-            $sidebar_form_fields['ee-msg-deleted'] = array(
1669
-                'name'       => 'MTP_deleted',
1670
-                'label'      => null,
1671
-                'input'      => 'hidden',
1672
-                'type'       => 'int',
1673
-                'required'   => false,
1674
-                'validation' => true,
1675
-                'value'      => $message_template_group->get('MTP_deleted'),
1676
-                'css_class'  => '',
1677
-                'format'     => '%d',
1678
-                'db-col'     => 'MTP_deleted',
1679
-            );
1680
-            $sidebar_form_fields['ee-msg-author'] = array(
1681
-                'name'       => 'MTP_user_id',
1682
-                'label'      => esc_html__('Author', 'event_espresso'),
1683
-                'input'      => 'hidden',
1684
-                'type'       => 'int',
1685
-                'required'   => false,
1686
-                'validation' => false,
1687
-                'value'      => $message_template_group->user(),
1688
-                'format'     => '%d',
1689
-                'db-col'     => 'MTP_user_id',
1690
-            );
1691
-
1692
-            $sidebar_form_fields['ee-msg-route'] = array(
1693
-                'name'  => 'action',
1694
-                'input' => 'hidden',
1695
-                'type'  => 'string',
1696
-                'value' => $action,
1697
-            );
1698
-
1699
-            $sidebar_form_fields['ee-msg-id'] = array(
1700
-                'name'  => 'id',
1701
-                'input' => 'hidden',
1702
-                'type'  => 'int',
1703
-                'value' => $GRP_ID,
1704
-            );
1705
-            $sidebar_form_fields['ee-msg-evt-nonce'] = array(
1706
-                'name'  => $action . '_nonce',
1707
-                'input' => 'hidden',
1708
-                'type'  => 'string',
1709
-                'value' => wp_create_nonce($action . '_nonce'),
1710
-            );
1711
-
1712
-            if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1713
-                $sidebar_form_fields['ee-msg-template-switch'] = array(
1714
-                    'name'  => 'template_switch',
1715
-                    'input' => 'hidden',
1716
-                    'type'  => 'int',
1717
-                    'value' => 1,
1718
-                );
1719
-            }
1720
-
1721
-
1722
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1723
-            $sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1724
-        } //end if ( !empty($template_field_structure) )
1725
-
1726
-        // set extra content for publish box
1727
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1728
-        $this->_set_publish_post_box_vars(
1729
-            'id',
1730
-            $GRP_ID,
1731
-            false,
1732
-            add_query_arg(
1733
-                array('action' => 'global_mtps'),
1734
-                $this->_admin_base_url
1735
-            )
1736
-        );
1737
-
1738
-        // add preview button
1739
-        $preview_url = parent::add_query_args_and_nonce(
1740
-            array(
1741
-                'message_type' => $message_template_group->message_type(),
1742
-                'messenger'    => $message_template_group->messenger(),
1743
-                'context'      => $context,
1744
-                'GRP_ID'       => $GRP_ID,
1745
-                'evt_id'       => $EVT_ID,
1746
-                'action'       => 'preview_message',
1747
-            ),
1748
-            $this->_admin_base_url
1749
-        );
1750
-        $preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1751
-                          . esc_html__('Preview', 'event_espresso')
1752
-                          . '</a>';
1753
-
1754
-
1755
-        // setup context switcher
1756
-        $context_switcher_args = array(
1757
-            'page'    => 'espresso_messages',
1758
-            'action'  => 'edit_message_template',
1759
-            'id'      => $GRP_ID,
1760
-            'evt_id'  => $EVT_ID,
1761
-            'context' => $context,
1762
-            'extra'   => $preview_button,
1763
-        );
1764
-        $this->_set_context_switcher($message_template_group, $context_switcher_args);
1765
-
1766
-
1767
-        // main box
1768
-        $this->_template_args['template_fields'] = $template_fields;
1769
-        $this->_template_args['sidebar_box_id'] = 'details';
1770
-        $this->_template_args['action'] = $action;
1771
-        $this->_template_args['context'] = $context;
1772
-        $this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1773
-        $this->_template_args['learn_more_about_message_templates_link'] =
1774
-            $this->_learn_more_about_message_templates_link();
1775
-
1776
-
1777
-        $this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1778
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1779
-            $message_template_group,
1780
-            $context,
1781
-            $context_label
1782
-        );
1783
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1784
-        $this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1785
-
1786
-        $this->_template_path = $this->_template_args['GRP_ID']
1787
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1788
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1789
-
1790
-        // send along EE_Message_Template_Group object for further template use.
1791
-        $this->_template_args['MTP'] = $message_template_group;
1792
-
1793
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1794
-            $this->_template_path,
1795
-            $this->_template_args,
1796
-            true
1797
-        );
1798
-
1799
-
1800
-        // finally, let's set the admin_page title
1801
-        $this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1802
-
1803
-
1804
-        // we need to take care of setting the shortcodes property for use elsewhere.
1805
-        $this->_set_shortcodes();
1806
-
1807
-
1808
-        // final template wrapper
1809
-        $this->display_admin_page_with_sidebar();
1810
-    }
1811
-
1812
-
1813
-    public function filter_tinymce_init($mceInit, $editor_id)
1814
-    {
1815
-        return $mceInit;
1816
-    }
1817
-
1818
-
1819
-    public function add_context_switcher()
1820
-    {
1821
-        return $this->_context_switcher;
1822
-    }
1823
-
1824
-
1825
-    /**
1826
-     * Adds the activation/deactivation toggle for the message template context.
1827
-     *
1828
-     * @param EE_Message_Template_Group $message_template_group
1829
-     * @param string                    $context
1830
-     * @param string                    $context_label
1831
-     * @return string
1832
-     * @throws DomainException
1833
-     * @throws EE_Error
1834
-     * @throws InvalidIdentifierException
1835
-     */
1836
-    protected function add_active_context_element(
1837
-        EE_Message_Template_Group $message_template_group,
1838
-        $context,
1839
-        $context_label
1840
-    ) {
1841
-        $template_args = array(
1842
-            'context'                   => $context,
1843
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1844
-            'is_active'                 => $message_template_group->is_context_active($context),
1845
-            'on_off_action'             => $message_template_group->is_context_active($context)
1846
-                ? 'context-off'
1847
-                : 'context-on',
1848
-            'context_label'             => str_replace(array('(', ')'), '', $context_label),
1849
-            'message_template_group_id' => $message_template_group->ID(),
1850
-        );
1851
-        return EEH_Template::display_template(
1852
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1853
-            $template_args,
1854
-            true
1855
-        );
1856
-    }
1857
-
1858
-
1859
-    /**
1860
-     * Ajax callback for `toggle_context_template` ajax action.
1861
-     * Handles toggling the message context on or off.
1862
-     *
1863
-     * @throws EE_Error
1864
-     * @throws InvalidArgumentException
1865
-     * @throws InvalidDataTypeException
1866
-     * @throws InvalidIdentifierException
1867
-     * @throws InvalidInterfaceException
1868
-     */
1869
-    public function toggle_context_template()
1870
-    {
1871
-        $success = true;
1872
-        // check for required data
1873
-        if (! isset(
1874
-            $this->_req_data['message_template_group_id'],
1875
-            $this->_req_data['context'],
1876
-            $this->_req_data['status']
1877
-        )) {
1878
-            EE_Error::add_error(
1879
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1880
-                __FILE__,
1881
-                __FUNCTION__,
1882
-                __LINE__
1883
-            );
1884
-            $success = false;
1885
-        }
1886
-
1887
-        $nonce = isset($this->_req_data['toggle_context_nonce'])
1888
-            ? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1889
-            : '';
1890
-        $nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1891
-        $this->_verify_nonce($nonce, $nonce_ref);
1892
-        $status = $this->_req_data['status'];
1893
-        if ($status !== 'off' && $status !== 'on') {
1894
-            EE_Error::add_error(
1895
-                sprintf(
1896
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1897
-                    $this->_req_data['status']
1898
-                ),
1899
-                __FILE__,
1900
-                __FUNCTION__,
1901
-                __LINE__
1902
-            );
1903
-            $success = false;
1904
-        }
1905
-        $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1906
-            $this->_req_data['message_template_group_id']
1907
-        );
1908
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1909
-            EE_Error::add_error(
1910
-                sprintf(
1911
-                    esc_html__(
1912
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1913
-                        'event_espresso'
1914
-                    ),
1915
-                    $this->_req_data['message_template_group_id'],
1916
-                    'EE_Message_Template_Group'
1917
-                ),
1918
-                __FILE__,
1919
-                __FUNCTION__,
1920
-                __LINE__
1921
-            );
1922
-            $success = false;
1923
-        }
1924
-        if ($success) {
1925
-            $success = $status === 'off'
1926
-                ? $message_template_group->deactivate_context($this->_req_data['context'])
1927
-                : $message_template_group->activate_context($this->_req_data['context']);
1928
-        }
1929
-        $this->_template_args['success'] = $success;
1930
-        $this->_return_json();
1931
-    }
1932
-
1933
-
1934
-    public function _add_form_element_before()
1935
-    {
1936
-        return '<form method="post" action="'
1937
-               . $this->_template_args["edit_message_template_form_url"]
1938
-               . '" id="ee-msg-edit-frm">';
1939
-    }
1940
-
1941
-    public function _add_form_element_after()
1942
-    {
1943
-        return '</form>';
1944
-    }
1945
-
1946
-
1947
-    /**
1948
-     * This executes switching the template pack for a message template.
1949
-     *
1950
-     * @since 4.5.0
1951
-     * @throws EE_Error
1952
-     * @throws InvalidDataTypeException
1953
-     * @throws InvalidInterfaceException
1954
-     * @throws InvalidArgumentException
1955
-     * @throws ReflectionException
1956
-     */
1957
-    public function switch_template_pack()
1958
-    {
1959
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1960
-        $template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1961
-
1962
-        // verify we have needed values.
1963
-        if (empty($GRP_ID) || empty($template_pack)) {
1964
-            $this->_template_args['error'] = true;
1965
-            EE_Error::add_error(
1966
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1967
-                __FILE__,
1968
-                __FUNCTION__,
1969
-                __LINE__
1970
-            );
1971
-        } else {
1972
-            // get template, set the new template_pack and then reset to default
1973
-            /** @type EE_Message_Template_Group $message_template_group */
1974
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1975
-
1976
-            $message_template_group->set_template_pack_name($template_pack);
1977
-            $this->_req_data['msgr'] = $message_template_group->messenger();
1978
-            $this->_req_data['mt'] = $message_template_group->message_type();
1979
-
1980
-            $query_args = $this->_reset_to_default_template();
1981
-
1982
-            if (empty($query_args['id'])) {
1983
-                EE_Error::add_error(
1984
-                    esc_html__(
1985
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
1986
-                        'event_espresso'
1987
-                    ),
1988
-                    __FILE__,
1989
-                    __FUNCTION__,
1990
-                    __LINE__
1991
-                );
1992
-                $this->_template_args['error'] = true;
1993
-            } else {
1994
-                $template_label = $message_template_group->get_template_pack()->label;
1995
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1996
-                EE_Error::add_success(
1997
-                    sprintf(
1998
-                        esc_html__(
1999
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2000
-                            'event_espresso'
2001
-                        ),
2002
-                        $template_label,
2003
-                        $template_pack_labels->template_pack
2004
-                    )
2005
-                );
2006
-                // generate the redirect url for js.
2007
-                $url = self::add_query_args_and_nonce(
2008
-                    $query_args,
2009
-                    $this->_admin_base_url
2010
-                );
2011
-                $this->_template_args['data']['redirect_url'] = $url;
2012
-                $this->_template_args['success'] = true;
2013
-            }
2014
-
2015
-            $this->_return_json();
2016
-        }
2017
-    }
2018
-
2019
-
2020
-    /**
2021
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2022
-     * they want.
2023
-     *
2024
-     * @access protected
2025
-     * @return array|null
2026
-     * @throws EE_Error
2027
-     * @throws InvalidArgumentException
2028
-     * @throws InvalidDataTypeException
2029
-     * @throws InvalidInterfaceException
2030
-     */
2031
-    protected function _reset_to_default_template()
2032
-    {
2033
-
2034
-        $templates = array();
2035
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2036
-        // we need to make sure we've got the info we need.
2037
-        if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2038
-            EE_Error::add_error(
2039
-                esc_html__(
2040
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2041
-                    'event_espresso'
2042
-                ),
2043
-                __FILE__,
2044
-                __FUNCTION__,
2045
-                __LINE__
2046
-            );
2047
-        }
2048
-
2049
-        // all templates will be reset to whatever the defaults are
2050
-        // for the global template matching the messenger and message type.
2051
-        $success = ! empty($GRP_ID) ? true : false;
2052
-
2053
-        if ($success) {
2054
-            // let's first determine if the incoming template is a global template,
2055
-            // if it isn't then we need to get the global template matching messenger and message type.
2056
-            // $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2057
-
2058
-
2059
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2060
-            $success = $this->_delete_mtp_permanently($GRP_ID, false);
2061
-
2062
-            if ($success) {
2063
-                // if successfully deleted, lets generate the new ones.
2064
-                // Note. We set GLOBAL to true, because resets on ANY template
2065
-                // will use the related global template defaults for regeneration.
2066
-                // This means that if a custom template is reset it resets to whatever the related global template is.
2067
-                // HOWEVER, we DO keep the template pack and template variation set
2068
-                // for the current custom template when resetting.
2069
-                $templates = $this->_generate_new_templates(
2070
-                    $this->_req_data['msgr'],
2071
-                    $this->_req_data['mt'],
2072
-                    $GRP_ID,
2073
-                    true
2074
-                );
2075
-            }
2076
-        }
2077
-
2078
-        // any error messages?
2079
-        if (! $success) {
2080
-            EE_Error::add_error(
2081
-                esc_html__(
2082
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
2083
-                    'event_espresso'
2084
-                ),
2085
-                __FILE__,
2086
-                __FUNCTION__,
2087
-                __LINE__
2088
-            );
2089
-        }
2090
-
2091
-        // all good, let's add a success message!
2092
-        if ($success && ! empty($templates)) {
2093
-            // the info for the template we generated is the first element in the returned array
2094
-            // $templates = $templates[0];
2095
-            EE_Error::overwrite_success();
2096
-            EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2097
-        }
2098
-
2099
-
2100
-        $query_args = array(
2101
-            'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2102
-            'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2103
-            'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2104
-        );
2105
-
2106
-        // if called via ajax then we return query args otherwise redirect
2107
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2108
-            return $query_args;
2109
-        } else {
2110
-            $this->_redirect_after_action(false, '', '', $query_args, true);
2111
-
2112
-            return null;
2113
-        }
2114
-    }
2115
-
2116
-
2117
-    /**
2118
-     * Retrieve and set the message preview for display.
2119
-     *
2120
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2121
-     * @return string
2122
-     * @throws ReflectionException
2123
-     * @throws EE_Error
2124
-     * @throws InvalidArgumentException
2125
-     * @throws InvalidDataTypeException
2126
-     * @throws InvalidInterfaceException
2127
-     */
2128
-    public function _preview_message($send = false)
2129
-    {
2130
-        // first make sure we've got the necessary parameters
2131
-        if (! isset(
2132
-            $this->_req_data['message_type'],
2133
-            $this->_req_data['messenger'],
2134
-            $this->_req_data['messenger'],
2135
-            $this->_req_data['GRP_ID']
2136
-        )) {
2137
-            EE_Error::add_error(
2138
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2139
-                __FILE__,
2140
-                __FUNCTION__,
2141
-                __LINE__
2142
-            );
2143
-        }
2144
-
2145
-        EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
22
+	/**
23
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
24
+	 */
25
+	protected $_message_resource_manager;
26
+
27
+	/**
28
+	 * @type string $_active_message_type_name
29
+	 */
30
+	protected $_active_message_type_name = '';
31
+
32
+	/**
33
+	 * @type EE_messenger $_active_messenger
34
+	 */
35
+	protected $_active_messenger;
36
+	protected $_activate_state;
37
+	protected $_activate_meta_box_type;
38
+	protected $_current_message_meta_box;
39
+	protected $_current_message_meta_box_object;
40
+	protected $_context_switcher;
41
+	protected $_shortcodes = array();
42
+	protected $_active_messengers = array();
43
+	protected $_active_message_types = array();
44
+
45
+	/**
46
+	 * @var EE_Message_Template_Group $_message_template_group
47
+	 */
48
+	protected $_message_template_group;
49
+	protected $_m_mt_settings = array();
50
+
51
+
52
+	/**
53
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
+	 * IF there is no group then it gets automatically set to the Default template pack.
55
+	 *
56
+	 * @since 4.5.0
57
+	 *
58
+	 * @var EE_Messages_Template_Pack
59
+	 */
60
+	protected $_template_pack;
61
+
62
+
63
+	/**
64
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
+	 * group is.  If there is no group then it automatically gets set to default.
66
+	 *
67
+	 * @since 4.5.0
68
+	 *
69
+	 * @var string
70
+	 */
71
+	protected $_variation;
72
+
73
+
74
+	/**
75
+	 * @param bool $routing
76
+	 * @throws EE_Error
77
+	 */
78
+	public function __construct($routing = true)
79
+	{
80
+		// make sure messages autoloader is running
81
+		EED_Messages::set_autoloaders();
82
+		parent::__construct($routing);
83
+	}
84
+
85
+
86
+	protected function _init_page_props()
87
+	{
88
+		$this->page_slug = EE_MSG_PG_SLUG;
89
+		$this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
+		$this->_admin_base_url = EE_MSG_ADMIN_URL;
91
+		$this->_admin_base_path = EE_MSG_ADMIN;
92
+
93
+		$this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
+			: array();
95
+
96
+		$this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
+		$this->_load_message_resource_manager();
98
+	}
99
+
100
+
101
+	/**
102
+	 * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
+	 *
104
+	 * @throws EE_Error
105
+	 * @throws InvalidDataTypeException
106
+	 * @throws InvalidInterfaceException
107
+	 * @throws InvalidArgumentException
108
+	 * @throws ReflectionException
109
+	 */
110
+	protected function _load_message_resource_manager()
111
+	{
112
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
+	}
114
+
115
+
116
+	/**
117
+	 * @deprecated 4.9.9.rc.014
118
+	 * @return array
119
+	 * @throws EE_Error
120
+	 * @throws InvalidArgumentException
121
+	 * @throws InvalidDataTypeException
122
+	 * @throws InvalidInterfaceException
123
+	 */
124
+	public function get_messengers_for_list_table()
125
+	{
126
+		EE_Error::doing_it_wrong(
127
+			__METHOD__,
128
+			sprintf(
129
+				esc_html__(
130
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
+					'event_espresso'
132
+				),
133
+				'Messages_Admin_Page::get_messengers_select_input()'
134
+			),
135
+			'4.9.9.rc.014'
136
+		);
137
+
138
+		$m_values = array();
139
+		$active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
+		// setup messengers for selects
141
+		$i = 1;
142
+		foreach ($active_messengers as $active_messenger) {
143
+			if ($active_messenger instanceof EE_Message) {
144
+				$m_values[ $i ]['id'] = $active_messenger->messenger();
145
+				$m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
+				$i++;
147
+			}
148
+		}
149
+
150
+		return $m_values;
151
+	}
152
+
153
+
154
+	/**
155
+	 * @deprecated 4.9.9.rc.014
156
+	 * @return array
157
+	 * @throws EE_Error
158
+	 * @throws InvalidArgumentException
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 */
162
+	public function get_message_types_for_list_table()
163
+	{
164
+		EE_Error::doing_it_wrong(
165
+			__METHOD__,
166
+			sprintf(
167
+				esc_html__(
168
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
+					'event_espresso'
170
+				),
171
+				'Messages_Admin_Page::get_message_types_select_input()'
172
+			),
173
+			'4.9.9.rc.014'
174
+		);
175
+
176
+		$mt_values = array();
177
+		$active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
+		$i = 1;
179
+		foreach ($active_messages as $active_message) {
180
+			if ($active_message instanceof EE_Message) {
181
+				$mt_values[ $i ]['id'] = $active_message->message_type();
182
+				$mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
+				$i++;
184
+			}
185
+		}
186
+
187
+		return $mt_values;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @deprecated 4.9.9.rc.014
193
+	 * @return array
194
+	 * @throws EE_Error
195
+	 * @throws InvalidArgumentException
196
+	 * @throws InvalidDataTypeException
197
+	 * @throws InvalidInterfaceException
198
+	 */
199
+	public function get_contexts_for_message_types_for_list_table()
200
+	{
201
+		EE_Error::doing_it_wrong(
202
+			__METHOD__,
203
+			sprintf(
204
+				esc_html__(
205
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
+					'event_espresso'
207
+				),
208
+				'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
+			),
210
+			'4.9.9.rc.014'
211
+		);
212
+
213
+		$contexts = array();
214
+		$active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
+		foreach ($active_message_contexts as $active_message) {
216
+			if ($active_message instanceof EE_Message) {
217
+				$message_type = $active_message->message_type_object();
218
+				if ($message_type instanceof EE_message_type) {
219
+					$message_type_contexts = $message_type->get_contexts();
220
+					foreach ($message_type_contexts as $context => $context_details) {
221
+						$contexts[ $context ] = $context_details['label'];
222
+					}
223
+				}
224
+			}
225
+		}
226
+
227
+		return $contexts;
228
+	}
229
+
230
+
231
+	/**
232
+	 * Generate select input with provided messenger options array.
233
+	 *
234
+	 * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
+	 *                                 labels.
236
+	 * @return string
237
+	 * @throws EE_Error
238
+	 */
239
+	public function get_messengers_select_input($messenger_options)
240
+	{
241
+		// if empty or just one value then just return an empty string
242
+		if (empty($messenger_options)
243
+			|| ! is_array($messenger_options)
244
+			|| count($messenger_options) === 1
245
+		) {
246
+			return '';
247
+		}
248
+		// merge in default
249
+		$messenger_options = array_merge(
250
+			array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
251
+			$messenger_options
252
+		);
253
+		$input = new EE_Select_Input(
254
+			$messenger_options,
255
+			array(
256
+				'html_name'  => 'ee_messenger_filter_by',
257
+				'html_id'    => 'ee_messenger_filter_by',
258
+				'html_class' => 'wide',
259
+				'default'    => isset($this->_req_data['ee_messenger_filter_by'])
260
+					? sanitize_title($this->_req_data['ee_messenger_filter_by'])
261
+					: 'none_selected',
262
+			)
263
+		);
264
+
265
+		return $input->get_html_for_input();
266
+	}
267
+
268
+
269
+	/**
270
+	 * Generate select input with provided message type options array.
271
+	 *
272
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
273
+	 *                                    message type labels
274
+	 * @return string
275
+	 * @throws EE_Error
276
+	 */
277
+	public function get_message_types_select_input($message_type_options)
278
+	{
279
+		// if empty or count of options is 1 then just return an empty string
280
+		if (empty($message_type_options)
281
+			|| ! is_array($message_type_options)
282
+			|| count($message_type_options) === 1
283
+		) {
284
+			return '';
285
+		}
286
+		// merge in default
287
+		$message_type_options = array_merge(
288
+			array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
289
+			$message_type_options
290
+		);
291
+		$input = new EE_Select_Input(
292
+			$message_type_options,
293
+			array(
294
+				'html_name'  => 'ee_message_type_filter_by',
295
+				'html_id'    => 'ee_message_type_filter_by',
296
+				'html_class' => 'wide',
297
+				'default'    => isset($this->_req_data['ee_message_type_filter_by'])
298
+					? sanitize_title($this->_req_data['ee_message_type_filter_by'])
299
+					: 'none_selected',
300
+			)
301
+		);
302
+
303
+		return $input->get_html_for_input();
304
+	}
305
+
306
+
307
+	/**
308
+	 * Generate select input with provide message type contexts array.
309
+	 *
310
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
311
+	 *                               context label.
312
+	 * @return string
313
+	 * @throws EE_Error
314
+	 */
315
+	public function get_contexts_for_message_types_select_input($context_options)
316
+	{
317
+		// if empty or count of options is one then just return empty string
318
+		if (empty($context_options)
319
+			|| ! is_array($context_options)
320
+			|| count($context_options) === 1
321
+		) {
322
+			return '';
323
+		}
324
+		// merge in default
325
+		$context_options = array_merge(
326
+			array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
327
+			$context_options
328
+		);
329
+		$input = new EE_Select_Input(
330
+			$context_options,
331
+			array(
332
+				'html_name'  => 'ee_context_filter_by',
333
+				'html_id'    => 'ee_context_filter_by',
334
+				'html_class' => 'wide',
335
+				'default'    => isset($this->_req_data['ee_context_filter_by'])
336
+					? sanitize_title($this->_req_data['ee_context_filter_by'])
337
+					: 'none_selected',
338
+			)
339
+		);
340
+
341
+		return $input->get_html_for_input();
342
+	}
343
+
344
+
345
+	protected function _ajax_hooks()
346
+	{
347
+		add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
348
+		add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
349
+		add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
350
+		add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
351
+		add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
352
+		add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
353
+	}
354
+
355
+
356
+	protected function _define_page_props()
357
+	{
358
+		$this->_admin_page_title = $this->page_label;
359
+		$this->_labels = array(
360
+			'buttons'    => array(
361
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
362
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
363
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
364
+			),
365
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
366
+		);
367
+	}
368
+
369
+
370
+	/**
371
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
372
+	 *
373
+	 * @access protected
374
+	 * @return void
375
+	 */
376
+	protected function _set_page_routes()
377
+	{
378
+		$grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
379
+			? $this->_req_data['GRP_ID']
380
+			: 0;
381
+		$grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
382
+			? $this->_req_data['id']
383
+			: $grp_id;
384
+		$msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
385
+			? $this->_req_data['MSG_ID']
386
+			: 0;
387
+
388
+		$this->_page_routes = array(
389
+			'default'                          => array(
390
+				'func'       => '_message_queue_list_table',
391
+				'capability' => 'ee_read_global_messages',
392
+			),
393
+			'global_mtps'                      => array(
394
+				'func'       => '_ee_default_messages_overview_list_table',
395
+				'capability' => 'ee_read_global_messages',
396
+			),
397
+			'custom_mtps'                      => array(
398
+				'func'       => '_custom_mtps_preview',
399
+				'capability' => 'ee_read_messages',
400
+			),
401
+			'add_new_message_template'         => array(
402
+				'func'       => '_add_message_template',
403
+				'capability' => 'ee_edit_messages',
404
+				'noheader'   => true,
405
+			),
406
+			'edit_message_template'            => array(
407
+				'func'       => '_edit_message_template',
408
+				'capability' => 'ee_edit_message',
409
+				'obj_id'     => $grp_id,
410
+			),
411
+			'preview_message'                  => array(
412
+				'func'               => '_preview_message',
413
+				'capability'         => 'ee_read_message',
414
+				'obj_id'             => $grp_id,
415
+				'noheader'           => true,
416
+				'headers_sent_route' => 'display_preview_message',
417
+			),
418
+			'display_preview_message'          => array(
419
+				'func'       => '_display_preview_message',
420
+				'capability' => 'ee_read_message',
421
+				'obj_id'     => $grp_id,
422
+			),
423
+			'insert_message_template'          => array(
424
+				'func'       => '_insert_or_update_message_template',
425
+				'capability' => 'ee_edit_messages',
426
+				'args'       => array('new_template' => true),
427
+				'noheader'   => true,
428
+			),
429
+			'update_message_template'          => array(
430
+				'func'       => '_insert_or_update_message_template',
431
+				'capability' => 'ee_edit_message',
432
+				'obj_id'     => $grp_id,
433
+				'args'       => array('new_template' => false),
434
+				'noheader'   => true,
435
+			),
436
+			'trash_message_template'           => array(
437
+				'func'       => '_trash_or_restore_message_template',
438
+				'capability' => 'ee_delete_message',
439
+				'obj_id'     => $grp_id,
440
+				'args'       => array('trash' => true, 'all' => true),
441
+				'noheader'   => true,
442
+			),
443
+			'trash_message_template_context'   => array(
444
+				'func'       => '_trash_or_restore_message_template',
445
+				'capability' => 'ee_delete_message',
446
+				'obj_id'     => $grp_id,
447
+				'args'       => array('trash' => true),
448
+				'noheader'   => true,
449
+			),
450
+			'restore_message_template'         => array(
451
+				'func'       => '_trash_or_restore_message_template',
452
+				'capability' => 'ee_delete_message',
453
+				'obj_id'     => $grp_id,
454
+				'args'       => array('trash' => false, 'all' => true),
455
+				'noheader'   => true,
456
+			),
457
+			'restore_message_template_context' => array(
458
+				'func'       => '_trash_or_restore_message_template',
459
+				'capability' => 'ee_delete_message',
460
+				'obj_id'     => $grp_id,
461
+				'args'       => array('trash' => false),
462
+				'noheader'   => true,
463
+			),
464
+			'delete_message_template'          => array(
465
+				'func'       => '_delete_message_template',
466
+				'capability' => 'ee_delete_message',
467
+				'obj_id'     => $grp_id,
468
+				'noheader'   => true,
469
+			),
470
+			'reset_to_default'                 => array(
471
+				'func'       => '_reset_to_default_template',
472
+				'capability' => 'ee_edit_message',
473
+				'obj_id'     => $grp_id,
474
+				'noheader'   => true,
475
+			),
476
+			'settings'                         => array(
477
+				'func'       => '_settings',
478
+				'capability' => 'manage_options',
479
+			),
480
+			'update_global_settings'           => array(
481
+				'func'       => '_update_global_settings',
482
+				'capability' => 'manage_options',
483
+				'noheader'   => true,
484
+			),
485
+			'generate_now'                     => array(
486
+				'func'       => '_generate_now',
487
+				'capability' => 'ee_send_message',
488
+				'noheader'   => true,
489
+			),
490
+			'generate_and_send_now'            => array(
491
+				'func'       => '_generate_and_send_now',
492
+				'capability' => 'ee_send_message',
493
+				'noheader'   => true,
494
+			),
495
+			'queue_for_resending'              => array(
496
+				'func'       => '_queue_for_resending',
497
+				'capability' => 'ee_send_message',
498
+				'noheader'   => true,
499
+			),
500
+			'send_now'                         => array(
501
+				'func'       => '_send_now',
502
+				'capability' => 'ee_send_message',
503
+				'noheader'   => true,
504
+			),
505
+			'delete_ee_message'                => array(
506
+				'func'       => '_delete_ee_messages',
507
+				'capability' => 'ee_delete_messages',
508
+				'noheader'   => true,
509
+			),
510
+			'delete_ee_messages'               => array(
511
+				'func'       => '_delete_ee_messages',
512
+				'capability' => 'ee_delete_messages',
513
+				'noheader'   => true,
514
+				'obj_id'     => $msg_id,
515
+			),
516
+		);
517
+	}
518
+
519
+
520
+	protected function _set_page_config()
521
+	{
522
+		$this->_page_config = array(
523
+			'default'                  => array(
524
+				'nav'           => array(
525
+					'label' => esc_html__('Message Activity', 'event_espresso'),
526
+					'order' => 10,
527
+				),
528
+				'list_table'    => 'EE_Message_List_Table',
529
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
530
+				'require_nonce' => false,
531
+			),
532
+			'global_mtps'              => array(
533
+				'nav'           => array(
534
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
535
+					'order' => 20,
536
+				),
537
+				'list_table'    => 'Messages_Template_List_Table',
538
+				'help_tabs'     => array(
539
+					'messages_overview_help_tab'                                => array(
540
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
541
+						'filename' => 'messages_overview',
542
+					),
543
+					'messages_overview_messages_table_column_headings_help_tab' => array(
544
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
545
+						'filename' => 'messages_overview_table_column_headings',
546
+					),
547
+					'messages_overview_messages_filters_help_tab'               => array(
548
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
549
+						'filename' => 'messages_overview_filters',
550
+					),
551
+					'messages_overview_messages_views_help_tab'                 => array(
552
+						'title'    => esc_html__('Message Views', 'event_espresso'),
553
+						'filename' => 'messages_overview_views',
554
+					),
555
+					'message_overview_message_types_help_tab'                   => array(
556
+						'title'    => esc_html__('Message Types', 'event_espresso'),
557
+						'filename' => 'messages_overview_types',
558
+					),
559
+					'messages_overview_messengers_help_tab'                     => array(
560
+						'title'    => esc_html__('Messengers', 'event_espresso'),
561
+						'filename' => 'messages_overview_messengers',
562
+					),
563
+				),
564
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
565
+				// 'help_tour'     => array('Messages_Overview_Help_Tour'),
566
+				'require_nonce' => false,
567
+			),
568
+			'custom_mtps'              => array(
569
+				'nav'           => array(
570
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
571
+					'order' => 30,
572
+				),
573
+				'help_tabs'     => array(),
574
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
575
+				// 'help_tour'     => array(),
576
+				'require_nonce' => false,
577
+			),
578
+			'add_new_message_template' => array(
579
+				'nav'           => array(
580
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
581
+					'order'      => 5,
582
+					'persistent' => false,
583
+				),
584
+				'require_nonce' => false,
585
+			),
586
+			'edit_message_template'    => array(
587
+				'labels'        => array(
588
+					'buttons'    => array(
589
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
590
+					),
591
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
592
+				),
593
+				'nav'           => array(
594
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
595
+					'order'      => 5,
596
+					'persistent' => false,
597
+					'url'        => '',
598
+				),
599
+				'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
600
+				'has_metaboxes' => true,
601
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
602
+				// 'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
603
+				'help_tabs'     => array(
604
+					'edit_message_template'            => array(
605
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
606
+						'callback' => 'edit_message_template_help_tab',
607
+					),
608
+					'message_templates_help_tab'       => array(
609
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
610
+						'filename' => 'messages_templates',
611
+					),
612
+					'message_template_shortcodes'      => array(
613
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
614
+						'callback' => 'message_template_shortcodes_help_tab',
615
+					),
616
+					'message_preview_help_tab'         => array(
617
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
618
+						'filename' => 'messages_preview',
619
+					),
620
+					'messages_overview_other_help_tab' => array(
621
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
622
+						'filename' => 'messages_overview_other',
623
+					),
624
+				),
625
+				'require_nonce' => false,
626
+			),
627
+			'display_preview_message'  => array(
628
+				'nav'           => array(
629
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
630
+					'order'      => 5,
631
+					'url'        => '',
632
+					'persistent' => false,
633
+				),
634
+				'help_tabs'     => array(
635
+					'preview_message' => array(
636
+						'title'    => esc_html__('About Previews', 'event_espresso'),
637
+						'callback' => 'preview_message_help_tab',
638
+					),
639
+				),
640
+				'require_nonce' => false,
641
+			),
642
+			'settings'                 => array(
643
+				'nav'           => array(
644
+					'label' => esc_html__('Settings', 'event_espresso'),
645
+					'order' => 40,
646
+				),
647
+				'metaboxes'     => array('_messages_settings_metaboxes'),
648
+				'help_tabs'     => array(
649
+					'messages_settings_help_tab'               => array(
650
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
651
+						'filename' => 'messages_settings',
652
+					),
653
+					'messages_settings_message_types_help_tab' => array(
654
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
655
+						'filename' => 'messages_settings_message_types',
656
+					),
657
+					'messages_settings_messengers_help_tab'    => array(
658
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
659
+						'filename' => 'messages_settings_messengers',
660
+					),
661
+				),
662
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
663
+				// 'help_tour'     => array('Messages_Settings_Help_Tour'),
664
+				'require_nonce' => false,
665
+			),
666
+		);
667
+	}
668
+
669
+
670
+	protected function _add_screen_options()
671
+	{
672
+		// todo
673
+	}
674
+
675
+
676
+	protected function _add_screen_options_global_mtps()
677
+	{
678
+		/**
679
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
680
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
681
+		 */
682
+		$page_title = $this->_admin_page_title;
683
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
684
+		$this->_per_page_screen_option();
685
+		$this->_admin_page_title = $page_title;
686
+	}
687
+
688
+
689
+	protected function _add_screen_options_default()
690
+	{
691
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
692
+		$this->_per_page_screen_option();
693
+	}
694
+
695
+
696
+	// none of the below group are currently used for Messages
697
+	protected function _add_feature_pointers()
698
+	{
699
+	}
700
+
701
+	public function admin_init()
702
+	{
703
+	}
704
+
705
+	public function admin_notices()
706
+	{
707
+	}
708
+
709
+	public function admin_footer_scripts()
710
+	{
711
+	}
712
+
713
+
714
+	public function messages_help_tab()
715
+	{
716
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
717
+	}
718
+
719
+
720
+	public function messengers_help_tab()
721
+	{
722
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
723
+	}
724
+
725
+
726
+	public function message_types_help_tab()
727
+	{
728
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
729
+	}
730
+
731
+
732
+	public function messages_overview_help_tab()
733
+	{
734
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
735
+	}
736
+
737
+
738
+	public function message_templates_help_tab()
739
+	{
740
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
741
+	}
742
+
743
+
744
+	public function edit_message_template_help_tab()
745
+	{
746
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
747
+						. esc_attr__('Editor Title', 'event_espresso')
748
+						. '" />';
749
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
750
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
751
+						. '" />';
752
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
753
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
754
+						. '" />';
755
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
756
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
757
+						. '" />';
758
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
759
+						. esc_attr__('Publish Metabox', 'event_espresso')
760
+						. '" />';
761
+		EEH_Template::display_template(
762
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
763
+			$args
764
+		);
765
+	}
766
+
767
+
768
+	public function message_template_shortcodes_help_tab()
769
+	{
770
+		$this->_set_shortcodes();
771
+		$args['shortcodes'] = $this->_shortcodes;
772
+		EEH_Template::display_template(
773
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
774
+			$args
775
+		);
776
+	}
777
+
778
+
779
+	public function preview_message_help_tab()
780
+	{
781
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
782
+	}
783
+
784
+
785
+	public function settings_help_tab()
786
+	{
787
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
788
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
789
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
790
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
791
+		$args['img3'] = '<div class="switch">'
792
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
793
+						. ' type="checkbox" checked="checked">'
794
+						. '<label for="ee-on-off-toggle-on"></label>'
795
+						. '</div>';
796
+		$args['img4'] = '<div class="switch">'
797
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
798
+						. ' type="checkbox">'
799
+						. '<label for="ee-on-off-toggle-on"></label>'
800
+						. '</div>';
801
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
802
+	}
803
+
804
+
805
+	public function load_scripts_styles()
806
+	{
807
+		wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
808
+		wp_enqueue_style('espresso_ee_msg');
809
+
810
+		wp_register_script(
811
+			'ee-messages-settings',
812
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
813
+			array('jquery-ui-droppable', 'ee-serialize-full-array'),
814
+			EVENT_ESPRESSO_VERSION,
815
+			true
816
+		);
817
+		wp_register_script(
818
+			'ee-msg-list-table-js',
819
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
820
+			array('ee-dialog'),
821
+			EVENT_ESPRESSO_VERSION
822
+		);
823
+	}
824
+
825
+
826
+	public function load_scripts_styles_default()
827
+	{
828
+		wp_enqueue_script('ee-msg-list-table-js');
829
+	}
830
+
831
+
832
+	public function wp_editor_css($mce_css)
833
+	{
834
+		// if we're on the edit_message_template route
835
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
836
+			$message_type_name = $this->_active_message_type_name;
837
+
838
+			// we're going to REPLACE the existing mce css
839
+			// we need to get the css file location from the active messenger
840
+			$mce_css = $this->_active_messenger->get_variation(
841
+				$this->_template_pack,
842
+				$message_type_name,
843
+				true,
844
+				'wpeditor',
845
+				$this->_variation
846
+			);
847
+		}
848
+
849
+		return $mce_css;
850
+	}
851
+
852
+
853
+	public function load_scripts_styles_edit_message_template()
854
+	{
855
+
856
+		$this->_set_shortcodes();
857
+
858
+		EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
859
+			esc_html__(
860
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
861
+				'event_espresso'
862
+			),
863
+			$this->_message_template_group->messenger_obj()->label['singular'],
864
+			$this->_message_template_group->message_type_obj()->label['singular']
865
+		);
866
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
867
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
868
+			'event_espresso'
869
+		);
870
+		EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
871
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
872
+			'event_espresso'
873
+		);
874
+
875
+		wp_register_script(
876
+			'ee_msgs_edit_js',
877
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
878
+			array('jquery'),
879
+			EVENT_ESPRESSO_VERSION
880
+		);
881
+
882
+		wp_enqueue_script('ee_admin_js');
883
+		wp_enqueue_script('ee_msgs_edit_js');
884
+
885
+		// add in special css for tiny_mce
886
+		add_filter('mce_css', array($this, 'wp_editor_css'));
887
+	}
888
+
889
+
890
+	public function load_scripts_styles_display_preview_message()
891
+	{
892
+
893
+		$this->_set_message_template_group();
894
+
895
+		if (isset($this->_req_data['messenger'])) {
896
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
897
+				$this->_req_data['messenger']
898
+			);
899
+		}
900
+
901
+		$message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
902
+
903
+
904
+		wp_enqueue_style(
905
+			'espresso_preview_css',
906
+			$this->_active_messenger->get_variation(
907
+				$this->_template_pack,
908
+				$message_type_name,
909
+				true,
910
+				'preview',
911
+				$this->_variation
912
+			)
913
+		);
914
+	}
915
+
916
+
917
+	public function load_scripts_styles_settings()
918
+	{
919
+		wp_register_style(
920
+			'ee-message-settings',
921
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
922
+			array(),
923
+			EVENT_ESPRESSO_VERSION
924
+		);
925
+		wp_enqueue_style('ee-text-links');
926
+		wp_enqueue_style('ee-message-settings');
927
+		wp_enqueue_script('ee-messages-settings');
928
+	}
929
+
930
+
931
+	/**
932
+	 * set views array for List Table
933
+	 */
934
+	public function _set_list_table_views_global_mtps()
935
+	{
936
+		$this->_views = array(
937
+			'in_use' => array(
938
+				'slug'  => 'in_use',
939
+				'label' => esc_html__('In Use', 'event_espresso'),
940
+				'count' => 0,
941
+			),
942
+		);
943
+	}
944
+
945
+
946
+	/**
947
+	 * Set views array for the Custom Template List Table
948
+	 */
949
+	public function _set_list_table_views_custom_mtps()
950
+	{
951
+		$this->_set_list_table_views_global_mtps();
952
+		$this->_views['in_use']['bulk_action'] = array(
953
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
954
+		);
955
+	}
956
+
957
+
958
+	/**
959
+	 * set views array for message queue list table
960
+	 *
961
+	 * @throws InvalidDataTypeException
962
+	 * @throws InvalidInterfaceException
963
+	 * @throws InvalidArgumentException
964
+	 * @throws EE_Error
965
+	 * @throws ReflectionException
966
+	 */
967
+	public function _set_list_table_views_default()
968
+	{
969
+		EE_Registry::instance()->load_helper('Template');
970
+
971
+		$common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
972
+			'ee_send_message',
973
+			'message_list_table_bulk_actions'
974
+		)
975
+			? array(
976
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
977
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
978
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
979
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
980
+			)
981
+			: array();
982
+
983
+		$delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
984
+			'ee_delete_messages',
985
+			'message_list_table_bulk_actions'
986
+		)
987
+			? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
988
+			: array();
989
+
990
+
991
+		$this->_views = array(
992
+			'all' => array(
993
+				'slug'        => 'all',
994
+				'label'       => esc_html__('All', 'event_espresso'),
995
+				'count'       => 0,
996
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
997
+			),
998
+		);
999
+
1000
+
1001
+		foreach (EEM_Message::instance()->all_statuses() as $status) {
1002
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1003
+				continue;
1004
+			}
1005
+			$status_bulk_actions = $common_bulk_actions;
1006
+			// unset bulk actions not applying to status
1007
+			if (! empty($status_bulk_actions)) {
1008
+				switch ($status) {
1009
+					case EEM_Message::status_idle:
1010
+					case EEM_Message::status_resend:
1011
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1012
+						break;
1013
+
1014
+					case EEM_Message::status_failed:
1015
+					case EEM_Message::status_debug_only:
1016
+					case EEM_Message::status_messenger_executing:
1017
+						$status_bulk_actions = array();
1018
+						break;
1019
+
1020
+					case EEM_Message::status_incomplete:
1021
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1022
+						break;
1023
+
1024
+					case EEM_Message::status_retry:
1025
+					case EEM_Message::status_sent:
1026
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1027
+						break;
1028
+				}
1029
+			}
1030
+
1031
+			// skip adding messenger executing status to views because it will be included with the Failed view.
1032
+			if ($status === EEM_Message::status_messenger_executing) {
1033
+				continue;
1034
+			}
1035
+
1036
+			$this->_views[ strtolower($status) ] = array(
1037
+				'slug'        => strtolower($status),
1038
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1039
+				'count'       => 0,
1040
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1041
+			);
1042
+		}
1043
+	}
1044
+
1045
+
1046
+	protected function _ee_default_messages_overview_list_table()
1047
+	{
1048
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1049
+		$this->display_admin_list_table_page_with_no_sidebar();
1050
+	}
1051
+
1052
+
1053
+	protected function _message_queue_list_table()
1054
+	{
1055
+		$this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1056
+		$this->_template_args['per_column'] = 6;
1057
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1058
+		$this->_template_args['before_list_table'] = '<h3>'
1059
+													 . EEM_Message::instance()->get_pretty_label_for_results()
1060
+													 . '</h3>';
1061
+		$this->display_admin_list_table_page_with_no_sidebar();
1062
+	}
1063
+
1064
+
1065
+	protected function _message_legend_items()
1066
+	{
1067
+
1068
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1069
+		$action_items = array();
1070
+
1071
+		foreach ($action_css_classes as $action_item => $action_details) {
1072
+			if ($action_item === 'see_notifications_for') {
1073
+				continue;
1074
+			}
1075
+			$action_items[ $action_item ] = array(
1076
+				'class' => $action_details['css_class'],
1077
+				'desc'  => $action_details['label'],
1078
+			);
1079
+		}
1080
+
1081
+		/** @type array $status_items status legend setup */
1082
+		$status_items = array(
1083
+			'sent_status'                => array(
1084
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1085
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1086
+			),
1087
+			'idle_status'                => array(
1088
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1089
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1090
+			),
1091
+			'failed_status'              => array(
1092
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1093
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1094
+			),
1095
+			'messenger_executing_status' => array(
1096
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1097
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1098
+			),
1099
+			'resend_status'              => array(
1100
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1101
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1102
+			),
1103
+			'incomplete_status'          => array(
1104
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1105
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1106
+			),
1107
+			'retry_status'               => array(
1108
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1109
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1110
+			),
1111
+		);
1112
+		if (EEM_Message::debug()) {
1113
+			$status_items['debug_only_status'] = array(
1114
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1115
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1116
+			);
1117
+		}
1118
+
1119
+		return array_merge($action_items, $status_items);
1120
+	}
1121
+
1122
+
1123
+	protected function _custom_mtps_preview()
1124
+	{
1125
+		$this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1126
+		$this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1127
+											   . ' alt="' . esc_attr__(
1128
+												   'Preview Custom Message Templates screenshot',
1129
+												   'event_espresso'
1130
+											   ) . '" />';
1131
+		$this->_template_args['preview_text'] = '<strong>'
1132
+												. esc_html__(
1133
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1134
+													'event_espresso'
1135
+												)
1136
+												. '</strong>';
1137
+
1138
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * get_message_templates
1144
+	 * This gets all the message templates for listing on the overview list.
1145
+	 *
1146
+	 * @access public
1147
+	 * @param int    $perpage the amount of templates groups to show per page
1148
+	 * @param string $type    the current _view we're getting templates for
1149
+	 * @param bool   $count   return count?
1150
+	 * @param bool   $all     disregard any paging info (get all data);
1151
+	 * @param bool   $global  whether to return just global (true) or custom templates (false)
1152
+	 * @return array
1153
+	 * @throws EE_Error
1154
+	 * @throws InvalidArgumentException
1155
+	 * @throws InvalidDataTypeException
1156
+	 * @throws InvalidInterfaceException
1157
+	 */
1158
+	public function get_message_templates(
1159
+		$perpage = 10,
1160
+		$type = 'in_use',
1161
+		$count = false,
1162
+		$all = false,
1163
+		$global = true
1164
+	) {
1165
+
1166
+		$MTP = EEM_Message_Template_Group::instance();
1167
+
1168
+		$this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1169
+		$orderby = $this->_req_data['orderby'];
1170
+
1171
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1172
+			? $this->_req_data['order']
1173
+			: 'ASC';
1174
+
1175
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1176
+			? $this->_req_data['paged']
1177
+			: 1;
1178
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1179
+			? $this->_req_data['perpage']
1180
+			: $perpage;
1181
+
1182
+		$offset = ($current_page - 1) * $per_page;
1183
+		$limit = $all ? null : array($offset, $per_page);
1184
+
1185
+
1186
+		// options will match what is in the _views array property
1187
+		switch ($type) {
1188
+			case 'in_use':
1189
+				$templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1190
+				break;
1191
+			default:
1192
+				$templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1193
+		}
1194
+
1195
+		return $templates;
1196
+	}
1197
+
1198
+
1199
+	/**
1200
+	 * filters etc might need a list of installed message_types
1201
+	 *
1202
+	 * @return array an array of message type objects
1203
+	 */
1204
+	public function get_installed_message_types()
1205
+	{
1206
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1207
+		$installed = array();
1208
+
1209
+		foreach ($installed_message_types as $message_type) {
1210
+			$installed[ $message_type->name ] = $message_type;
1211
+		}
1212
+
1213
+		return $installed;
1214
+	}
1215
+
1216
+
1217
+	/**
1218
+	 * _add_message_template
1219
+	 *
1220
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1221
+	 *
1222
+	 * @param string $message_type
1223
+	 * @param string $messenger
1224
+	 * @param string $GRP_ID
1225
+	 *
1226
+	 * @throws EE_error
1227
+	 */
1228
+	protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1229
+	{
1230
+		// set values override any request data
1231
+		$message_type = ! empty($message_type) ? $message_type : '';
1232
+		$message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1233
+			? $this->_req_data['message_type']
1234
+			: $message_type;
1235
+
1236
+		$messenger = ! empty($messenger) ? $messenger : '';
1237
+		$messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1238
+			? $this->_req_data['messenger']
1239
+			: $messenger;
1240
+
1241
+		$GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1242
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1243
+
1244
+		// we need messenger and message type.  They should be coming from the event editor. If not here then return error
1245
+		if (empty($message_type) || empty($messenger)) {
1246
+			throw new EE_Error(
1247
+				esc_html__(
1248
+					'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1249
+					'event_espresso'
1250
+				)
1251
+			);
1252
+		}
1253
+
1254
+		// we need the GRP_ID for the template being used as the base for the new template
1255
+		if (empty($GRP_ID)) {
1256
+			throw new EE_Error(
1257
+				esc_html__(
1258
+					'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1259
+					'event_espresso'
1260
+				)
1261
+			);
1262
+		}
1263
+
1264
+		// let's just make sure the template gets generated!
1265
+
1266
+		// we need to reassign some variables for what the insert is expecting
1267
+		$this->_req_data['MTP_messenger'] = $messenger;
1268
+		$this->_req_data['MTP_message_type'] = $message_type;
1269
+		$this->_req_data['GRP_ID'] = $GRP_ID;
1270
+		$this->_insert_or_update_message_template(true);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * public wrapper for the _add_message_template method
1276
+	 *
1277
+	 * @param string $message_type     message type slug
1278
+	 * @param string $messenger        messenger slug
1279
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1280
+	 *                                 off of.
1281
+	 * @throws EE_error
1282
+	 */
1283
+	public function add_message_template($message_type, $messenger, $GRP_ID)
1284
+	{
1285
+		$this->_add_message_template($message_type, $messenger, $GRP_ID);
1286
+	}
1287
+
1288
+
1289
+	/**
1290
+	 * _edit_message_template
1291
+	 *
1292
+	 * @access protected
1293
+	 * @return void
1294
+	 * @throws InvalidIdentifierException
1295
+	 * @throws DomainException
1296
+	 * @throws EE_Error
1297
+	 * @throws InvalidArgumentException
1298
+	 * @throws ReflectionException
1299
+	 * @throws InvalidDataTypeException
1300
+	 * @throws InvalidInterfaceException
1301
+	 */
1302
+	protected function _edit_message_template()
1303
+	{
1304
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1305
+		$template_fields = '';
1306
+		$sidebar_fields = '';
1307
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1308
+		// valid html in the templates.
1309
+		add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1310
+
1311
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1312
+			? absint($this->_req_data['id'])
1313
+			: false;
1314
+
1315
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1316
+		? absint($this->_req_data['evt_id'])
1317
+		: false;
1318
+
1319
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1320
+		$message_template_group = $this->_message_template_group;
1321
+		$c_label = $message_template_group->context_label();
1322
+		$c_config = $message_template_group->contexts_config();
1323
+
1324
+		reset($c_config);
1325
+		$context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1326
+			? strtolower($this->_req_data['context'])
1327
+			: key($c_config);
1328
+
1329
+
1330
+		if (empty($GRP_ID)) {
1331
+			$action = 'insert_message_template';
1332
+			$edit_message_template_form_url = add_query_arg(
1333
+				array('action' => $action, 'noheader' => true),
1334
+				EE_MSG_ADMIN_URL
1335
+			);
1336
+		} else {
1337
+			$action = 'update_message_template';
1338
+			$edit_message_template_form_url = add_query_arg(
1339
+				array('action' => $action, 'noheader' => true),
1340
+				EE_MSG_ADMIN_URL
1341
+			);
1342
+		}
1343
+
1344
+		// set active messenger for this view
1345
+		$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1346
+			$message_template_group->messenger()
1347
+		);
1348
+		$this->_active_message_type_name = $message_template_group->message_type();
1349
+
1350
+
1351
+		// Do we have any validation errors?
1352
+		$validators = $this->_get_transient();
1353
+		$v_fields = ! empty($validators) ? array_keys($validators) : array();
1354
+
1355
+
1356
+		// we need to assemble the title from Various details
1357
+		$context_label = sprintf(
1358
+			esc_html__('(%s %s)', 'event_espresso'),
1359
+			$c_config[ $context ]['label'],
1360
+			ucwords($c_label['label'])
1361
+		);
1362
+
1363
+		$title = sprintf(
1364
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1365
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1366
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1367
+			$context_label
1368
+		);
1369
+
1370
+		$this->_template_args['GRP_ID'] = $GRP_ID;
1371
+		$this->_template_args['message_template'] = $message_template_group;
1372
+		$this->_template_args['is_extra_fields'] = false;
1373
+
1374
+
1375
+		// let's get EEH_MSG_Template so we can get template form fields
1376
+		$template_field_structure = EEH_MSG_Template::get_fields(
1377
+			$message_template_group->messenger(),
1378
+			$message_template_group->message_type()
1379
+		);
1380
+
1381
+		if (! $template_field_structure) {
1382
+			$template_field_structure = false;
1383
+			$template_fields = esc_html__(
1384
+				'There was an error in assembling the fields for this display (you should see an error message)',
1385
+				'event_espresso'
1386
+			);
1387
+		}
1388
+
1389
+
1390
+		$message_templates = $message_template_group->context_templates();
1391
+
1392
+
1393
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1394
+		// will get handled in the "extra" array.
1395
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1396
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1397
+				unset($template_field_structure[ $context ][ $reference_field ]);
1398
+			}
1399
+		}
1400
+
1401
+		// let's loop through the template_field_structure and actually assemble the input fields!
1402
+		if (! empty($template_field_structure)) {
1403
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1404
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1405
+				// the extra array and reset them.
1406
+				if ($template_field === 'extra') {
1407
+					$this->_template_args['is_extra_fields'] = true;
1408
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1409
+						$message_template = $message_templates[ $context ][ $reference_field ];
1410
+						$content = $message_template instanceof EE_Message_Template
1411
+							? $message_template->get('MTP_content')
1412
+							: '';
1413
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1414
+							// let's verify if we need this extra field via the shortcodes parameter.
1415
+							$continue = false;
1416
+							if (isset($extra_array['shortcodes_required'])) {
1417
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1418
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1419
+										$continue = true;
1420
+									}
1421
+								}
1422
+								if ($continue) {
1423
+									continue;
1424
+								}
1425
+							}
1426
+
1427
+							$field_id = $reference_field
1428
+										. '-'
1429
+										. $extra_field
1430
+										. '-content';
1431
+							$template_form_fields[ $field_id ] = $extra_array;
1432
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1433
+																		 . $reference_field
1434
+																		 . '][content]['
1435
+																		 . $extra_field . ']';
1436
+							$css_class = isset($extra_array['css_class'])
1437
+								? $extra_array['css_class']
1438
+								: '';
1439
+
1440
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1441
+																			  && in_array($extra_field, $v_fields, true)
1442
+																			  &&
1443
+																			  (
1444
+																				  is_array($validators[ $extra_field ])
1445
+																				  && isset($validators[ $extra_field ]['msg'])
1446
+																			  )
1447
+								? 'validate-error ' . $css_class
1448
+								: $css_class;
1449
+
1450
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1451
+																		  && isset($content[ $extra_field ])
1452
+								? $content[ $extra_field ]
1453
+								: '';
1454
+
1455
+							// do we have a validation error?  if we do then let's use that value instead
1456
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1457
+								? $validators[ $extra_field ]['value']
1458
+								: $template_form_fields[ $field_id ]['value'];
1459
+
1460
+
1461
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1462
+
1463
+							// shortcode selector
1464
+							$field_name_to_use = $extra_field === 'main'
1465
+								? 'content'
1466
+								: $extra_field;
1467
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1468
+								$field_name_to_use,
1469
+								$field_id
1470
+							);
1471
+
1472
+							if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1473
+								// we want to decode the entities
1474
+								$template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1475
+							}/**/
1476
+						}
1477
+						$templatefield_MTP_id = $reference_field . '-MTP_ID';
1478
+						$templatefield_templatename_id = $reference_field . '-name';
1479
+
1480
+						$template_form_fields[ $templatefield_MTP_id ] = array(
1481
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1482
+							'label'      => null,
1483
+							'input'      => 'hidden',
1484
+							'type'       => 'int',
1485
+							'required'   => false,
1486
+							'validation' => false,
1487
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1488
+							'css_class'  => '',
1489
+							'format'     => '%d',
1490
+							'db-col'     => 'MTP_ID',
1491
+						);
1492
+
1493
+						$template_form_fields[ $templatefield_templatename_id ] = array(
1494
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1495
+							'label'      => null,
1496
+							'input'      => 'hidden',
1497
+							'type'       => 'string',
1498
+							'required'   => false,
1499
+							'validation' => true,
1500
+							'value'      => $reference_field,
1501
+							'css_class'  => '',
1502
+							'format'     => '%s',
1503
+							'db-col'     => 'MTP_template_field',
1504
+						);
1505
+					}
1506
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1507
+				} else {
1508
+					$field_id = $template_field . '-content';
1509
+					$template_form_fields[ $field_id ] = $field_setup_array;
1510
+					$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1511
+					$message_template = isset($message_templates[ $context ][ $template_field ])
1512
+						? $message_templates[ $context ][ $template_field ]
1513
+						: null;
1514
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1515
+																  && is_array($message_templates[ $context ])
1516
+																  && $message_template instanceof EE_Message_Template
1517
+						? $message_template->get('MTP_content')
1518
+						: '';
1519
+
1520
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1521
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1522
+						? $validators[ $template_field ]['value']
1523
+						: $template_form_fields[ $field_id ]['value'];
1524
+
1525
+
1526
+					$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1527
+					$css_class = isset($field_setup_array['css_class'])
1528
+						? $field_setup_array['css_class']
1529
+						: '';
1530
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1531
+																	  && in_array($template_field, $v_fields, true)
1532
+																	  && isset($validators[ $template_field ]['msg'])
1533
+						? 'validate-error ' . $css_class
1534
+						: $css_class;
1535
+
1536
+					// shortcode selector
1537
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1538
+						$template_field,
1539
+						$field_id
1540
+					);
1541
+				}
1542
+
1543
+				// k took care of content field(s) now let's take care of others.
1544
+
1545
+				$templatefield_MTP_id = $template_field . '-MTP_ID';
1546
+				$templatefield_field_templatename_id = $template_field . '-name';
1547
+
1548
+				// foreach template field there are actually two form fields created
1549
+				$template_form_fields[ $templatefield_MTP_id ] = array(
1550
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1551
+					'label'      => null,
1552
+					'input'      => 'hidden',
1553
+					'type'       => 'int',
1554
+					'required'   => false,
1555
+					'validation' => true,
1556
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1557
+					'css_class'  => '',
1558
+					'format'     => '%d',
1559
+					'db-col'     => 'MTP_ID',
1560
+				);
1561
+
1562
+				$template_form_fields[ $templatefield_field_templatename_id ] = array(
1563
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1564
+					'label'      => null,
1565
+					'input'      => 'hidden',
1566
+					'type'       => 'string',
1567
+					'required'   => false,
1568
+					'validation' => true,
1569
+					'value'      => $template_field,
1570
+					'css_class'  => '',
1571
+					'format'     => '%s',
1572
+					'db-col'     => 'MTP_template_field',
1573
+				);
1574
+			}
1575
+
1576
+			// add other fields
1577
+			$template_form_fields['ee-msg-current-context'] = array(
1578
+				'name'       => 'MTP_context',
1579
+				'label'      => null,
1580
+				'input'      => 'hidden',
1581
+				'type'       => 'string',
1582
+				'required'   => false,
1583
+				'validation' => true,
1584
+				'value'      => $context,
1585
+				'css_class'  => '',
1586
+				'format'     => '%s',
1587
+				'db-col'     => 'MTP_context',
1588
+			);
1589
+
1590
+			$template_form_fields['ee-msg-grp-id'] = array(
1591
+				'name'       => 'GRP_ID',
1592
+				'label'      => null,
1593
+				'input'      => 'hidden',
1594
+				'type'       => 'int',
1595
+				'required'   => false,
1596
+				'validation' => true,
1597
+				'value'      => $GRP_ID,
1598
+				'css_class'  => '',
1599
+				'format'     => '%d',
1600
+				'db-col'     => 'GRP_ID',
1601
+			);
1602
+
1603
+			$template_form_fields['ee-msg-messenger'] = array(
1604
+				'name'       => 'MTP_messenger',
1605
+				'label'      => null,
1606
+				'input'      => 'hidden',
1607
+				'type'       => 'string',
1608
+				'required'   => false,
1609
+				'validation' => true,
1610
+				'value'      => $message_template_group->messenger(),
1611
+				'css_class'  => '',
1612
+				'format'     => '%s',
1613
+				'db-col'     => 'MTP_messenger',
1614
+			);
1615
+
1616
+			$template_form_fields['ee-msg-message-type'] = array(
1617
+				'name'       => 'MTP_message_type',
1618
+				'label'      => null,
1619
+				'input'      => 'hidden',
1620
+				'type'       => 'string',
1621
+				'required'   => false,
1622
+				'validation' => true,
1623
+				'value'      => $message_template_group->message_type(),
1624
+				'css_class'  => '',
1625
+				'format'     => '%s',
1626
+				'db-col'     => 'MTP_message_type',
1627
+			);
1628
+
1629
+			$sidebar_form_fields['ee-msg-is-global'] = array(
1630
+				'name'       => 'MTP_is_global',
1631
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1632
+				'input'      => 'hidden',
1633
+				'type'       => 'int',
1634
+				'required'   => false,
1635
+				'validation' => true,
1636
+				'value'      => $message_template_group->get('MTP_is_global'),
1637
+				'css_class'  => '',
1638
+				'format'     => '%d',
1639
+				'db-col'     => 'MTP_is_global',
1640
+			);
1641
+
1642
+			$sidebar_form_fields['ee-msg-is-override'] = array(
1643
+				'name'       => 'MTP_is_override',
1644
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1645
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1646
+				'type'       => 'int',
1647
+				'required'   => false,
1648
+				'validation' => true,
1649
+				'value'      => $message_template_group->get('MTP_is_override'),
1650
+				'css_class'  => '',
1651
+				'format'     => '%d',
1652
+				'db-col'     => 'MTP_is_override',
1653
+			);
1654
+
1655
+			$sidebar_form_fields['ee-msg-is-active'] = array(
1656
+				'name'       => 'MTP_is_active',
1657
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1658
+				'input'      => 'hidden',
1659
+				'type'       => 'int',
1660
+				'required'   => false,
1661
+				'validation' => true,
1662
+				'value'      => $message_template_group->is_active(),
1663
+				'css_class'  => '',
1664
+				'format'     => '%d',
1665
+				'db-col'     => 'MTP_is_active',
1666
+			);
1667
+
1668
+			$sidebar_form_fields['ee-msg-deleted'] = array(
1669
+				'name'       => 'MTP_deleted',
1670
+				'label'      => null,
1671
+				'input'      => 'hidden',
1672
+				'type'       => 'int',
1673
+				'required'   => false,
1674
+				'validation' => true,
1675
+				'value'      => $message_template_group->get('MTP_deleted'),
1676
+				'css_class'  => '',
1677
+				'format'     => '%d',
1678
+				'db-col'     => 'MTP_deleted',
1679
+			);
1680
+			$sidebar_form_fields['ee-msg-author'] = array(
1681
+				'name'       => 'MTP_user_id',
1682
+				'label'      => esc_html__('Author', 'event_espresso'),
1683
+				'input'      => 'hidden',
1684
+				'type'       => 'int',
1685
+				'required'   => false,
1686
+				'validation' => false,
1687
+				'value'      => $message_template_group->user(),
1688
+				'format'     => '%d',
1689
+				'db-col'     => 'MTP_user_id',
1690
+			);
1691
+
1692
+			$sidebar_form_fields['ee-msg-route'] = array(
1693
+				'name'  => 'action',
1694
+				'input' => 'hidden',
1695
+				'type'  => 'string',
1696
+				'value' => $action,
1697
+			);
1698
+
1699
+			$sidebar_form_fields['ee-msg-id'] = array(
1700
+				'name'  => 'id',
1701
+				'input' => 'hidden',
1702
+				'type'  => 'int',
1703
+				'value' => $GRP_ID,
1704
+			);
1705
+			$sidebar_form_fields['ee-msg-evt-nonce'] = array(
1706
+				'name'  => $action . '_nonce',
1707
+				'input' => 'hidden',
1708
+				'type'  => 'string',
1709
+				'value' => wp_create_nonce($action . '_nonce'),
1710
+			);
1711
+
1712
+			if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1713
+				$sidebar_form_fields['ee-msg-template-switch'] = array(
1714
+					'name'  => 'template_switch',
1715
+					'input' => 'hidden',
1716
+					'type'  => 'int',
1717
+					'value' => 1,
1718
+				);
1719
+			}
1720
+
1721
+
1722
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1723
+			$sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1724
+		} //end if ( !empty($template_field_structure) )
1725
+
1726
+		// set extra content for publish box
1727
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1728
+		$this->_set_publish_post_box_vars(
1729
+			'id',
1730
+			$GRP_ID,
1731
+			false,
1732
+			add_query_arg(
1733
+				array('action' => 'global_mtps'),
1734
+				$this->_admin_base_url
1735
+			)
1736
+		);
1737
+
1738
+		// add preview button
1739
+		$preview_url = parent::add_query_args_and_nonce(
1740
+			array(
1741
+				'message_type' => $message_template_group->message_type(),
1742
+				'messenger'    => $message_template_group->messenger(),
1743
+				'context'      => $context,
1744
+				'GRP_ID'       => $GRP_ID,
1745
+				'evt_id'       => $EVT_ID,
1746
+				'action'       => 'preview_message',
1747
+			),
1748
+			$this->_admin_base_url
1749
+		);
1750
+		$preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1751
+						  . esc_html__('Preview', 'event_espresso')
1752
+						  . '</a>';
1753
+
1754
+
1755
+		// setup context switcher
1756
+		$context_switcher_args = array(
1757
+			'page'    => 'espresso_messages',
1758
+			'action'  => 'edit_message_template',
1759
+			'id'      => $GRP_ID,
1760
+			'evt_id'  => $EVT_ID,
1761
+			'context' => $context,
1762
+			'extra'   => $preview_button,
1763
+		);
1764
+		$this->_set_context_switcher($message_template_group, $context_switcher_args);
1765
+
1766
+
1767
+		// main box
1768
+		$this->_template_args['template_fields'] = $template_fields;
1769
+		$this->_template_args['sidebar_box_id'] = 'details';
1770
+		$this->_template_args['action'] = $action;
1771
+		$this->_template_args['context'] = $context;
1772
+		$this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1773
+		$this->_template_args['learn_more_about_message_templates_link'] =
1774
+			$this->_learn_more_about_message_templates_link();
1775
+
1776
+
1777
+		$this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1778
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1779
+			$message_template_group,
1780
+			$context,
1781
+			$context_label
1782
+		);
1783
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1784
+		$this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1785
+
1786
+		$this->_template_path = $this->_template_args['GRP_ID']
1787
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1788
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1789
+
1790
+		// send along EE_Message_Template_Group object for further template use.
1791
+		$this->_template_args['MTP'] = $message_template_group;
1792
+
1793
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1794
+			$this->_template_path,
1795
+			$this->_template_args,
1796
+			true
1797
+		);
1798
+
1799
+
1800
+		// finally, let's set the admin_page title
1801
+		$this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1802
+
1803
+
1804
+		// we need to take care of setting the shortcodes property for use elsewhere.
1805
+		$this->_set_shortcodes();
1806
+
1807
+
1808
+		// final template wrapper
1809
+		$this->display_admin_page_with_sidebar();
1810
+	}
1811
+
1812
+
1813
+	public function filter_tinymce_init($mceInit, $editor_id)
1814
+	{
1815
+		return $mceInit;
1816
+	}
1817
+
1818
+
1819
+	public function add_context_switcher()
1820
+	{
1821
+		return $this->_context_switcher;
1822
+	}
1823
+
1824
+
1825
+	/**
1826
+	 * Adds the activation/deactivation toggle for the message template context.
1827
+	 *
1828
+	 * @param EE_Message_Template_Group $message_template_group
1829
+	 * @param string                    $context
1830
+	 * @param string                    $context_label
1831
+	 * @return string
1832
+	 * @throws DomainException
1833
+	 * @throws EE_Error
1834
+	 * @throws InvalidIdentifierException
1835
+	 */
1836
+	protected function add_active_context_element(
1837
+		EE_Message_Template_Group $message_template_group,
1838
+		$context,
1839
+		$context_label
1840
+	) {
1841
+		$template_args = array(
1842
+			'context'                   => $context,
1843
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1844
+			'is_active'                 => $message_template_group->is_context_active($context),
1845
+			'on_off_action'             => $message_template_group->is_context_active($context)
1846
+				? 'context-off'
1847
+				: 'context-on',
1848
+			'context_label'             => str_replace(array('(', ')'), '', $context_label),
1849
+			'message_template_group_id' => $message_template_group->ID(),
1850
+		);
1851
+		return EEH_Template::display_template(
1852
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1853
+			$template_args,
1854
+			true
1855
+		);
1856
+	}
1857
+
1858
+
1859
+	/**
1860
+	 * Ajax callback for `toggle_context_template` ajax action.
1861
+	 * Handles toggling the message context on or off.
1862
+	 *
1863
+	 * @throws EE_Error
1864
+	 * @throws InvalidArgumentException
1865
+	 * @throws InvalidDataTypeException
1866
+	 * @throws InvalidIdentifierException
1867
+	 * @throws InvalidInterfaceException
1868
+	 */
1869
+	public function toggle_context_template()
1870
+	{
1871
+		$success = true;
1872
+		// check for required data
1873
+		if (! isset(
1874
+			$this->_req_data['message_template_group_id'],
1875
+			$this->_req_data['context'],
1876
+			$this->_req_data['status']
1877
+		)) {
1878
+			EE_Error::add_error(
1879
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1880
+				__FILE__,
1881
+				__FUNCTION__,
1882
+				__LINE__
1883
+			);
1884
+			$success = false;
1885
+		}
1886
+
1887
+		$nonce = isset($this->_req_data['toggle_context_nonce'])
1888
+			? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1889
+			: '';
1890
+		$nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1891
+		$this->_verify_nonce($nonce, $nonce_ref);
1892
+		$status = $this->_req_data['status'];
1893
+		if ($status !== 'off' && $status !== 'on') {
1894
+			EE_Error::add_error(
1895
+				sprintf(
1896
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1897
+					$this->_req_data['status']
1898
+				),
1899
+				__FILE__,
1900
+				__FUNCTION__,
1901
+				__LINE__
1902
+			);
1903
+			$success = false;
1904
+		}
1905
+		$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1906
+			$this->_req_data['message_template_group_id']
1907
+		);
1908
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1909
+			EE_Error::add_error(
1910
+				sprintf(
1911
+					esc_html__(
1912
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1913
+						'event_espresso'
1914
+					),
1915
+					$this->_req_data['message_template_group_id'],
1916
+					'EE_Message_Template_Group'
1917
+				),
1918
+				__FILE__,
1919
+				__FUNCTION__,
1920
+				__LINE__
1921
+			);
1922
+			$success = false;
1923
+		}
1924
+		if ($success) {
1925
+			$success = $status === 'off'
1926
+				? $message_template_group->deactivate_context($this->_req_data['context'])
1927
+				: $message_template_group->activate_context($this->_req_data['context']);
1928
+		}
1929
+		$this->_template_args['success'] = $success;
1930
+		$this->_return_json();
1931
+	}
1932
+
1933
+
1934
+	public function _add_form_element_before()
1935
+	{
1936
+		return '<form method="post" action="'
1937
+			   . $this->_template_args["edit_message_template_form_url"]
1938
+			   . '" id="ee-msg-edit-frm">';
1939
+	}
1940
+
1941
+	public function _add_form_element_after()
1942
+	{
1943
+		return '</form>';
1944
+	}
1945
+
1946
+
1947
+	/**
1948
+	 * This executes switching the template pack for a message template.
1949
+	 *
1950
+	 * @since 4.5.0
1951
+	 * @throws EE_Error
1952
+	 * @throws InvalidDataTypeException
1953
+	 * @throws InvalidInterfaceException
1954
+	 * @throws InvalidArgumentException
1955
+	 * @throws ReflectionException
1956
+	 */
1957
+	public function switch_template_pack()
1958
+	{
1959
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1960
+		$template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1961
+
1962
+		// verify we have needed values.
1963
+		if (empty($GRP_ID) || empty($template_pack)) {
1964
+			$this->_template_args['error'] = true;
1965
+			EE_Error::add_error(
1966
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1967
+				__FILE__,
1968
+				__FUNCTION__,
1969
+				__LINE__
1970
+			);
1971
+		} else {
1972
+			// get template, set the new template_pack and then reset to default
1973
+			/** @type EE_Message_Template_Group $message_template_group */
1974
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1975
+
1976
+			$message_template_group->set_template_pack_name($template_pack);
1977
+			$this->_req_data['msgr'] = $message_template_group->messenger();
1978
+			$this->_req_data['mt'] = $message_template_group->message_type();
1979
+
1980
+			$query_args = $this->_reset_to_default_template();
1981
+
1982
+			if (empty($query_args['id'])) {
1983
+				EE_Error::add_error(
1984
+					esc_html__(
1985
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
1986
+						'event_espresso'
1987
+					),
1988
+					__FILE__,
1989
+					__FUNCTION__,
1990
+					__LINE__
1991
+				);
1992
+				$this->_template_args['error'] = true;
1993
+			} else {
1994
+				$template_label = $message_template_group->get_template_pack()->label;
1995
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1996
+				EE_Error::add_success(
1997
+					sprintf(
1998
+						esc_html__(
1999
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2000
+							'event_espresso'
2001
+						),
2002
+						$template_label,
2003
+						$template_pack_labels->template_pack
2004
+					)
2005
+				);
2006
+				// generate the redirect url for js.
2007
+				$url = self::add_query_args_and_nonce(
2008
+					$query_args,
2009
+					$this->_admin_base_url
2010
+				);
2011
+				$this->_template_args['data']['redirect_url'] = $url;
2012
+				$this->_template_args['success'] = true;
2013
+			}
2014
+
2015
+			$this->_return_json();
2016
+		}
2017
+	}
2018
+
2019
+
2020
+	/**
2021
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2022
+	 * they want.
2023
+	 *
2024
+	 * @access protected
2025
+	 * @return array|null
2026
+	 * @throws EE_Error
2027
+	 * @throws InvalidArgumentException
2028
+	 * @throws InvalidDataTypeException
2029
+	 * @throws InvalidInterfaceException
2030
+	 */
2031
+	protected function _reset_to_default_template()
2032
+	{
2033
+
2034
+		$templates = array();
2035
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2036
+		// we need to make sure we've got the info we need.
2037
+		if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2038
+			EE_Error::add_error(
2039
+				esc_html__(
2040
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2041
+					'event_espresso'
2042
+				),
2043
+				__FILE__,
2044
+				__FUNCTION__,
2045
+				__LINE__
2046
+			);
2047
+		}
2048
+
2049
+		// all templates will be reset to whatever the defaults are
2050
+		// for the global template matching the messenger and message type.
2051
+		$success = ! empty($GRP_ID) ? true : false;
2052
+
2053
+		if ($success) {
2054
+			// let's first determine if the incoming template is a global template,
2055
+			// if it isn't then we need to get the global template matching messenger and message type.
2056
+			// $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2057
+
2058
+
2059
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2060
+			$success = $this->_delete_mtp_permanently($GRP_ID, false);
2061
+
2062
+			if ($success) {
2063
+				// if successfully deleted, lets generate the new ones.
2064
+				// Note. We set GLOBAL to true, because resets on ANY template
2065
+				// will use the related global template defaults for regeneration.
2066
+				// This means that if a custom template is reset it resets to whatever the related global template is.
2067
+				// HOWEVER, we DO keep the template pack and template variation set
2068
+				// for the current custom template when resetting.
2069
+				$templates = $this->_generate_new_templates(
2070
+					$this->_req_data['msgr'],
2071
+					$this->_req_data['mt'],
2072
+					$GRP_ID,
2073
+					true
2074
+				);
2075
+			}
2076
+		}
2077
+
2078
+		// any error messages?
2079
+		if (! $success) {
2080
+			EE_Error::add_error(
2081
+				esc_html__(
2082
+					'Something went wrong with deleting existing templates. Unable to reset to default',
2083
+					'event_espresso'
2084
+				),
2085
+				__FILE__,
2086
+				__FUNCTION__,
2087
+				__LINE__
2088
+			);
2089
+		}
2090
+
2091
+		// all good, let's add a success message!
2092
+		if ($success && ! empty($templates)) {
2093
+			// the info for the template we generated is the first element in the returned array
2094
+			// $templates = $templates[0];
2095
+			EE_Error::overwrite_success();
2096
+			EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2097
+		}
2098
+
2099
+
2100
+		$query_args = array(
2101
+			'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2102
+			'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2103
+			'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2104
+		);
2105
+
2106
+		// if called via ajax then we return query args otherwise redirect
2107
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2108
+			return $query_args;
2109
+		} else {
2110
+			$this->_redirect_after_action(false, '', '', $query_args, true);
2111
+
2112
+			return null;
2113
+		}
2114
+	}
2115
+
2116
+
2117
+	/**
2118
+	 * Retrieve and set the message preview for display.
2119
+	 *
2120
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2121
+	 * @return string
2122
+	 * @throws ReflectionException
2123
+	 * @throws EE_Error
2124
+	 * @throws InvalidArgumentException
2125
+	 * @throws InvalidDataTypeException
2126
+	 * @throws InvalidInterfaceException
2127
+	 */
2128
+	public function _preview_message($send = false)
2129
+	{
2130
+		// first make sure we've got the necessary parameters
2131
+		if (! isset(
2132
+			$this->_req_data['message_type'],
2133
+			$this->_req_data['messenger'],
2134
+			$this->_req_data['messenger'],
2135
+			$this->_req_data['GRP_ID']
2136
+		)) {
2137
+			EE_Error::add_error(
2138
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2139
+				__FILE__,
2140
+				__FUNCTION__,
2141
+				__LINE__
2142
+			);
2143
+		}
2144
+
2145
+		EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
2146 2146
         
2147
-        // if we have an evt_id set on the request, use it.
2148
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2149
-        ? absint($this->_req_data['evt_id'])
2150
-        : false;
2151
-
2152
-
2153
-        // get the preview!
2154
-        $preview = EED_Messages::preview_message(
2155
-            $this->_req_data['message_type'],
2156
-            $this->_req_data['context'],
2157
-            $this->_req_data['messenger'],
2158
-            $send
2159
-        );
2160
-
2161
-        if ($send) {
2162
-            return $preview;
2163
-        }
2164
-
2165
-        // let's add a button to go back to the edit view
2166
-        $query_args = array(
2167
-            'id'      => $this->_req_data['GRP_ID'],
2168
-            'evt_id'  => $EVT_ID,
2169
-            'context' => $this->_req_data['context'],
2170
-            'action'  => 'edit_message_template',
2171
-        );
2172
-        $go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2173
-        $preview_button = '<a href="'
2174
-                          . $go_back_url
2175
-                          . '" class="button-secondary messages-preview-go-back-button">'
2176
-                          . esc_html__('Go Back to Edit', 'event_espresso')
2177
-                          . '</a>';
2178
-        $message_types = $this->get_installed_message_types();
2179
-        $active_messenger = $this->_message_resource_manager->get_active_messenger(
2180
-            $this->_req_data['messenger']
2181
-        );
2182
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2183
-            ? ucwords($active_messenger->label['singular'])
2184
-            : esc_html__('Unknown Messenger', 'event_espresso');
2185
-        // let's provide a helpful title for context
2186
-        $preview_title = sprintf(
2187
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2188
-            $active_messenger_label,
2189
-            ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2190
-        );
2191
-        if (empty($preview)) {
2192
-            $this->noEventsErrorMessage();
2193
-        }
2194
-        // setup display of preview.
2195
-        $this->_admin_page_title = $preview_title;
2196
-        $this->_template_args['admin_page_title'] = $preview_title;
2197
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2198
-        $this->_template_args['data']['force_json'] = true;
2199
-
2200
-        return '';
2201
-    }
2202
-
2203
-
2204
-    /**
2205
-     * Used to set an error if there are no events available for generating a preview/test send.
2206
-     *
2207
-     * @param bool $test_send  Whether the error should be generated for the context of a test send.
2208
-     */
2209
-    protected function noEventsErrorMessage($test_send = false)
2210
-    {
2211
-        $events_url = parent::add_query_args_and_nonce(
2212
-            array(
2213
-                'action' => 'default',
2214
-                'page'   => 'espresso_events',
2215
-            ),
2216
-            admin_url('admin.php')
2217
-        );
2218
-        $message = $test_send
2219
-            ? __(
2220
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2221
-                'event_espresso'
2222
-            )
2223
-            : __(
2224
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2225
-                'event_espresso'
2226
-            );
2227
-
2228
-        EE_Error::add_attention(
2229
-            sprintf(
2230
-                $message,
2231
-                "<a href='{$events_url}'>",
2232
-                '</a>'
2233
-            )
2234
-        );
2235
-    }
2236
-
2237
-
2238
-    /**
2239
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2240
-     * gets called automatically.
2241
-     *
2242
-     * @since 4.5.0
2243
-     *
2244
-     * @return string
2245
-     */
2246
-    protected function _display_preview_message()
2247
-    {
2248
-        $this->display_admin_page_with_no_sidebar();
2249
-    }
2250
-
2251
-
2252
-    /**
2253
-     * registers metaboxes that should show up on the "edit_message_template" page
2254
-     *
2255
-     * @access protected
2256
-     * @return void
2257
-     */
2258
-    protected function _register_edit_meta_boxes()
2259
-    {
2260
-        add_meta_box(
2261
-            'mtp_valid_shortcodes',
2262
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2263
-            array($this, 'shortcode_meta_box'),
2264
-            $this->_current_screen->id,
2265
-            'side',
2266
-            'default'
2267
-        );
2268
-        add_meta_box(
2269
-            'mtp_extra_actions',
2270
-            esc_html__('Extra Actions', 'event_espresso'),
2271
-            array($this, 'extra_actions_meta_box'),
2272
-            $this->_current_screen->id,
2273
-            'side',
2274
-            'high'
2275
-        );
2276
-        add_meta_box(
2277
-            'mtp_templates',
2278
-            esc_html__('Template Styles', 'event_espresso'),
2279
-            array($this, 'template_pack_meta_box'),
2280
-            $this->_current_screen->id,
2281
-            'side',
2282
-            'high'
2283
-        );
2284
-    }
2285
-
2286
-
2287
-    /**
2288
-     * metabox content for all template pack and variation selection.
2289
-     *
2290
-     * @since 4.5.0
2291
-     * @return string
2292
-     * @throws DomainException
2293
-     * @throws EE_Error
2294
-     * @throws InvalidArgumentException
2295
-     * @throws ReflectionException
2296
-     * @throws InvalidDataTypeException
2297
-     * @throws InvalidInterfaceException
2298
-     */
2299
-    public function template_pack_meta_box()
2300
-    {
2301
-        $this->_set_message_template_group();
2302
-
2303
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2304
-
2305
-        $tp_select_values = array();
2306
-
2307
-        foreach ($tp_collection as $tp) {
2308
-            // only include template packs that support this messenger and message type!
2309
-            $supports = $tp->get_supports();
2310
-            if (! isset($supports[ $this->_message_template_group->messenger() ])
2311
-                || ! in_array(
2312
-                    $this->_message_template_group->message_type(),
2313
-                    $supports[ $this->_message_template_group->messenger() ],
2314
-                    true
2315
-                )
2316
-            ) {
2317
-                // not supported
2318
-                continue;
2319
-            }
2320
-
2321
-            $tp_select_values[] = array(
2322
-                'text' => $tp->label,
2323
-                'id'   => $tp->dbref,
2324
-            );
2325
-        }
2326
-
2327
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2328
-        // the default template pack.  This still allows for the odd template pack to override.
2329
-        if (empty($tp_select_values)) {
2330
-            $tp_select_values[] = array(
2331
-                'text' => esc_html__('Default', 'event_espresso'),
2332
-                'id'   => 'default',
2333
-            );
2334
-        }
2335
-
2336
-        // setup variation select values for the currently selected template.
2337
-        $variations = $this->_message_template_group->get_template_pack()->get_variations(
2338
-            $this->_message_template_group->messenger(),
2339
-            $this->_message_template_group->message_type()
2340
-        );
2341
-        $variations_select_values = array();
2342
-        foreach ($variations as $variation => $label) {
2343
-            $variations_select_values[] = array(
2344
-                'text' => $label,
2345
-                'id'   => $variation,
2346
-            );
2347
-        }
2348
-
2349
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2350
-
2351
-        $template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2352
-            'MTP_template_pack',
2353
-            $tp_select_values,
2354
-            $this->_message_template_group->get_template_pack_name()
2355
-        );
2356
-        $template_args['variations_selector'] = EEH_Form_Fields::select_input(
2357
-            'MTP_template_variation',
2358
-            $variations_select_values,
2359
-            $this->_message_template_group->get_template_pack_variation()
2360
-        );
2361
-        $template_args['template_pack_label'] = $template_pack_labels->template_pack;
2362
-        $template_args['template_variation_label'] = $template_pack_labels->template_variation;
2363
-        $template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2364
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2365
-
2366
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2367
-
2368
-        EEH_Template::display_template($template, $template_args);
2369
-    }
2370
-
2371
-
2372
-    /**
2373
-     * This meta box holds any extra actions related to Message Templates
2374
-     * For now, this includes Resetting templates to defaults and sending a test email.
2375
-     *
2376
-     * @access  public
2377
-     * @return void
2378
-     * @throws EE_Error
2379
-     */
2380
-    public function extra_actions_meta_box()
2381
-    {
2382
-        $template_form_fields = array();
2383
-
2384
-        $extra_args = array(
2385
-            'msgr'   => $this->_message_template_group->messenger(),
2386
-            'mt'     => $this->_message_template_group->message_type(),
2387
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2388
-        );
2389
-        // first we need to see if there are any fields
2390
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2391
-
2392
-        if (! empty($fields)) {
2393
-            // yup there be fields
2394
-            foreach ($fields as $field => $config) {
2395
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2396
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2397
-                $default = isset($config['default']) ? $config['default'] : '';
2398
-                $default = isset($config['value']) ? $config['value'] : $default;
2399
-
2400
-                // if type is hidden and the value is empty
2401
-                // something may have gone wrong so let's correct with the defaults
2402
-                $fix = $config['input'] === 'hidden'
2403
-                       && isset($existing[ $field ])
2404
-                       && empty($existing[ $field ])
2405
-                    ? $default
2406
-                    : '';
2407
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2408
-                    ? $existing[ $field ]
2409
-                    : $fix;
2410
-
2411
-                $template_form_fields[ $field_id ] = array(
2412
-                    'name'       => 'test_settings_fld[' . $field . ']',
2413
-                    'label'      => $config['label'],
2414
-                    'input'      => $config['input'],
2415
-                    'type'       => $config['type'],
2416
-                    'required'   => $config['required'],
2417
-                    'validation' => $config['validation'],
2418
-                    'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2419
-                    'css_class'  => $config['css_class'],
2420
-                    'options'    => isset($config['options']) ? $config['options'] : array(),
2421
-                    'default'    => $default,
2422
-                    'format'     => $config['format'],
2423
-                );
2424
-            }
2425
-        }
2426
-
2427
-        $test_settings_fields = ! empty($template_form_fields)
2428
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2429
-            : '';
2430
-
2431
-        $test_settings_html = '';
2432
-        // print out $test_settings_fields
2433
-        if (! empty($test_settings_fields)) {
2434
-            echo $test_settings_fields;
2435
-            $test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2436
-            $test_settings_html .= 'name="test_button" value="';
2437
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2438
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2439
-        }
2440
-
2441
-        // and button
2442
-        $test_settings_html .= '<p>'
2443
-                               . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2444
-                               . '</p>';
2445
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2446
-        $test_settings_html .= $this->get_action_link_or_button(
2447
-            'reset_to_default',
2448
-            'reset',
2449
-            $extra_args,
2450
-            'button-primary reset-default-button'
2451
-        );
2452
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2453
-        echo $test_settings_html;
2454
-    }
2455
-
2456
-
2457
-    /**
2458
-     * This returns the shortcode selector skeleton for a given context and field.
2459
-     *
2460
-     * @since 4.9.rc.000
2461
-     * @param string $field           The name of the field retrieving shortcodes for.
2462
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2463
-     * @return string
2464
-     * @throws DomainException
2465
-     * @throws EE_Error
2466
-     * @throws InvalidArgumentException
2467
-     * @throws ReflectionException
2468
-     * @throws InvalidDataTypeException
2469
-     * @throws InvalidInterfaceException
2470
-     */
2471
-    protected function _get_shortcode_selector($field, $linked_input_id)
2472
-    {
2473
-        $template_args = array(
2474
-            'shortcodes'      => $this->_get_shortcodes(array($field), true),
2475
-            'fieldname'       => $field,
2476
-            'linked_input_id' => $linked_input_id,
2477
-        );
2478
-
2479
-        return EEH_Template::display_template(
2480
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2481
-            $template_args,
2482
-            true
2483
-        );
2484
-    }
2485
-
2486
-
2487
-    /**
2488
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2489
-     * page)
2490
-     *
2491
-     * @access public
2492
-     * @return void
2493
-     * @throws EE_Error
2494
-     * @throws InvalidArgumentException
2495
-     * @throws ReflectionException
2496
-     * @throws InvalidDataTypeException
2497
-     * @throws InvalidInterfaceException
2498
-     */
2499
-    public function shortcode_meta_box()
2500
-    {
2501
-        $shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2502
-        // $messenger = $this->_message_template_group->messenger_obj();
2503
-        // now let's set the content depending on the status of the shortcodes array
2504
-        if (empty($shortcodes)) {
2505
-            $content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2506
-            echo $content;
2507
-        } else {
2508
-            // $alt = 0;
2509
-            ?>
2147
+		// if we have an evt_id set on the request, use it.
2148
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2149
+		? absint($this->_req_data['evt_id'])
2150
+		: false;
2151
+
2152
+
2153
+		// get the preview!
2154
+		$preview = EED_Messages::preview_message(
2155
+			$this->_req_data['message_type'],
2156
+			$this->_req_data['context'],
2157
+			$this->_req_data['messenger'],
2158
+			$send
2159
+		);
2160
+
2161
+		if ($send) {
2162
+			return $preview;
2163
+		}
2164
+
2165
+		// let's add a button to go back to the edit view
2166
+		$query_args = array(
2167
+			'id'      => $this->_req_data['GRP_ID'],
2168
+			'evt_id'  => $EVT_ID,
2169
+			'context' => $this->_req_data['context'],
2170
+			'action'  => 'edit_message_template',
2171
+		);
2172
+		$go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2173
+		$preview_button = '<a href="'
2174
+						  . $go_back_url
2175
+						  . '" class="button-secondary messages-preview-go-back-button">'
2176
+						  . esc_html__('Go Back to Edit', 'event_espresso')
2177
+						  . '</a>';
2178
+		$message_types = $this->get_installed_message_types();
2179
+		$active_messenger = $this->_message_resource_manager->get_active_messenger(
2180
+			$this->_req_data['messenger']
2181
+		);
2182
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2183
+			? ucwords($active_messenger->label['singular'])
2184
+			: esc_html__('Unknown Messenger', 'event_espresso');
2185
+		// let's provide a helpful title for context
2186
+		$preview_title = sprintf(
2187
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2188
+			$active_messenger_label,
2189
+			ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2190
+		);
2191
+		if (empty($preview)) {
2192
+			$this->noEventsErrorMessage();
2193
+		}
2194
+		// setup display of preview.
2195
+		$this->_admin_page_title = $preview_title;
2196
+		$this->_template_args['admin_page_title'] = $preview_title;
2197
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2198
+		$this->_template_args['data']['force_json'] = true;
2199
+
2200
+		return '';
2201
+	}
2202
+
2203
+
2204
+	/**
2205
+	 * Used to set an error if there are no events available for generating a preview/test send.
2206
+	 *
2207
+	 * @param bool $test_send  Whether the error should be generated for the context of a test send.
2208
+	 */
2209
+	protected function noEventsErrorMessage($test_send = false)
2210
+	{
2211
+		$events_url = parent::add_query_args_and_nonce(
2212
+			array(
2213
+				'action' => 'default',
2214
+				'page'   => 'espresso_events',
2215
+			),
2216
+			admin_url('admin.php')
2217
+		);
2218
+		$message = $test_send
2219
+			? __(
2220
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2221
+				'event_espresso'
2222
+			)
2223
+			: __(
2224
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2225
+				'event_espresso'
2226
+			);
2227
+
2228
+		EE_Error::add_attention(
2229
+			sprintf(
2230
+				$message,
2231
+				"<a href='{$events_url}'>",
2232
+				'</a>'
2233
+			)
2234
+		);
2235
+	}
2236
+
2237
+
2238
+	/**
2239
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2240
+	 * gets called automatically.
2241
+	 *
2242
+	 * @since 4.5.0
2243
+	 *
2244
+	 * @return string
2245
+	 */
2246
+	protected function _display_preview_message()
2247
+	{
2248
+		$this->display_admin_page_with_no_sidebar();
2249
+	}
2250
+
2251
+
2252
+	/**
2253
+	 * registers metaboxes that should show up on the "edit_message_template" page
2254
+	 *
2255
+	 * @access protected
2256
+	 * @return void
2257
+	 */
2258
+	protected function _register_edit_meta_boxes()
2259
+	{
2260
+		add_meta_box(
2261
+			'mtp_valid_shortcodes',
2262
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2263
+			array($this, 'shortcode_meta_box'),
2264
+			$this->_current_screen->id,
2265
+			'side',
2266
+			'default'
2267
+		);
2268
+		add_meta_box(
2269
+			'mtp_extra_actions',
2270
+			esc_html__('Extra Actions', 'event_espresso'),
2271
+			array($this, 'extra_actions_meta_box'),
2272
+			$this->_current_screen->id,
2273
+			'side',
2274
+			'high'
2275
+		);
2276
+		add_meta_box(
2277
+			'mtp_templates',
2278
+			esc_html__('Template Styles', 'event_espresso'),
2279
+			array($this, 'template_pack_meta_box'),
2280
+			$this->_current_screen->id,
2281
+			'side',
2282
+			'high'
2283
+		);
2284
+	}
2285
+
2286
+
2287
+	/**
2288
+	 * metabox content for all template pack and variation selection.
2289
+	 *
2290
+	 * @since 4.5.0
2291
+	 * @return string
2292
+	 * @throws DomainException
2293
+	 * @throws EE_Error
2294
+	 * @throws InvalidArgumentException
2295
+	 * @throws ReflectionException
2296
+	 * @throws InvalidDataTypeException
2297
+	 * @throws InvalidInterfaceException
2298
+	 */
2299
+	public function template_pack_meta_box()
2300
+	{
2301
+		$this->_set_message_template_group();
2302
+
2303
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2304
+
2305
+		$tp_select_values = array();
2306
+
2307
+		foreach ($tp_collection as $tp) {
2308
+			// only include template packs that support this messenger and message type!
2309
+			$supports = $tp->get_supports();
2310
+			if (! isset($supports[ $this->_message_template_group->messenger() ])
2311
+				|| ! in_array(
2312
+					$this->_message_template_group->message_type(),
2313
+					$supports[ $this->_message_template_group->messenger() ],
2314
+					true
2315
+				)
2316
+			) {
2317
+				// not supported
2318
+				continue;
2319
+			}
2320
+
2321
+			$tp_select_values[] = array(
2322
+				'text' => $tp->label,
2323
+				'id'   => $tp->dbref,
2324
+			);
2325
+		}
2326
+
2327
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2328
+		// the default template pack.  This still allows for the odd template pack to override.
2329
+		if (empty($tp_select_values)) {
2330
+			$tp_select_values[] = array(
2331
+				'text' => esc_html__('Default', 'event_espresso'),
2332
+				'id'   => 'default',
2333
+			);
2334
+		}
2335
+
2336
+		// setup variation select values for the currently selected template.
2337
+		$variations = $this->_message_template_group->get_template_pack()->get_variations(
2338
+			$this->_message_template_group->messenger(),
2339
+			$this->_message_template_group->message_type()
2340
+		);
2341
+		$variations_select_values = array();
2342
+		foreach ($variations as $variation => $label) {
2343
+			$variations_select_values[] = array(
2344
+				'text' => $label,
2345
+				'id'   => $variation,
2346
+			);
2347
+		}
2348
+
2349
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2350
+
2351
+		$template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2352
+			'MTP_template_pack',
2353
+			$tp_select_values,
2354
+			$this->_message_template_group->get_template_pack_name()
2355
+		);
2356
+		$template_args['variations_selector'] = EEH_Form_Fields::select_input(
2357
+			'MTP_template_variation',
2358
+			$variations_select_values,
2359
+			$this->_message_template_group->get_template_pack_variation()
2360
+		);
2361
+		$template_args['template_pack_label'] = $template_pack_labels->template_pack;
2362
+		$template_args['template_variation_label'] = $template_pack_labels->template_variation;
2363
+		$template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2364
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2365
+
2366
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2367
+
2368
+		EEH_Template::display_template($template, $template_args);
2369
+	}
2370
+
2371
+
2372
+	/**
2373
+	 * This meta box holds any extra actions related to Message Templates
2374
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2375
+	 *
2376
+	 * @access  public
2377
+	 * @return void
2378
+	 * @throws EE_Error
2379
+	 */
2380
+	public function extra_actions_meta_box()
2381
+	{
2382
+		$template_form_fields = array();
2383
+
2384
+		$extra_args = array(
2385
+			'msgr'   => $this->_message_template_group->messenger(),
2386
+			'mt'     => $this->_message_template_group->message_type(),
2387
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2388
+		);
2389
+		// first we need to see if there are any fields
2390
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2391
+
2392
+		if (! empty($fields)) {
2393
+			// yup there be fields
2394
+			foreach ($fields as $field => $config) {
2395
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2396
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2397
+				$default = isset($config['default']) ? $config['default'] : '';
2398
+				$default = isset($config['value']) ? $config['value'] : $default;
2399
+
2400
+				// if type is hidden and the value is empty
2401
+				// something may have gone wrong so let's correct with the defaults
2402
+				$fix = $config['input'] === 'hidden'
2403
+					   && isset($existing[ $field ])
2404
+					   && empty($existing[ $field ])
2405
+					? $default
2406
+					: '';
2407
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2408
+					? $existing[ $field ]
2409
+					: $fix;
2410
+
2411
+				$template_form_fields[ $field_id ] = array(
2412
+					'name'       => 'test_settings_fld[' . $field . ']',
2413
+					'label'      => $config['label'],
2414
+					'input'      => $config['input'],
2415
+					'type'       => $config['type'],
2416
+					'required'   => $config['required'],
2417
+					'validation' => $config['validation'],
2418
+					'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2419
+					'css_class'  => $config['css_class'],
2420
+					'options'    => isset($config['options']) ? $config['options'] : array(),
2421
+					'default'    => $default,
2422
+					'format'     => $config['format'],
2423
+				);
2424
+			}
2425
+		}
2426
+
2427
+		$test_settings_fields = ! empty($template_form_fields)
2428
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2429
+			: '';
2430
+
2431
+		$test_settings_html = '';
2432
+		// print out $test_settings_fields
2433
+		if (! empty($test_settings_fields)) {
2434
+			echo $test_settings_fields;
2435
+			$test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2436
+			$test_settings_html .= 'name="test_button" value="';
2437
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2438
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2439
+		}
2440
+
2441
+		// and button
2442
+		$test_settings_html .= '<p>'
2443
+							   . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2444
+							   . '</p>';
2445
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2446
+		$test_settings_html .= $this->get_action_link_or_button(
2447
+			'reset_to_default',
2448
+			'reset',
2449
+			$extra_args,
2450
+			'button-primary reset-default-button'
2451
+		);
2452
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2453
+		echo $test_settings_html;
2454
+	}
2455
+
2456
+
2457
+	/**
2458
+	 * This returns the shortcode selector skeleton for a given context and field.
2459
+	 *
2460
+	 * @since 4.9.rc.000
2461
+	 * @param string $field           The name of the field retrieving shortcodes for.
2462
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2463
+	 * @return string
2464
+	 * @throws DomainException
2465
+	 * @throws EE_Error
2466
+	 * @throws InvalidArgumentException
2467
+	 * @throws ReflectionException
2468
+	 * @throws InvalidDataTypeException
2469
+	 * @throws InvalidInterfaceException
2470
+	 */
2471
+	protected function _get_shortcode_selector($field, $linked_input_id)
2472
+	{
2473
+		$template_args = array(
2474
+			'shortcodes'      => $this->_get_shortcodes(array($field), true),
2475
+			'fieldname'       => $field,
2476
+			'linked_input_id' => $linked_input_id,
2477
+		);
2478
+
2479
+		return EEH_Template::display_template(
2480
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2481
+			$template_args,
2482
+			true
2483
+		);
2484
+	}
2485
+
2486
+
2487
+	/**
2488
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2489
+	 * page)
2490
+	 *
2491
+	 * @access public
2492
+	 * @return void
2493
+	 * @throws EE_Error
2494
+	 * @throws InvalidArgumentException
2495
+	 * @throws ReflectionException
2496
+	 * @throws InvalidDataTypeException
2497
+	 * @throws InvalidInterfaceException
2498
+	 */
2499
+	public function shortcode_meta_box()
2500
+	{
2501
+		$shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2502
+		// $messenger = $this->_message_template_group->messenger_obj();
2503
+		// now let's set the content depending on the status of the shortcodes array
2504
+		if (empty($shortcodes)) {
2505
+			$content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2506
+			echo $content;
2507
+		} else {
2508
+			// $alt = 0;
2509
+			?>
2510 2510
             <div style="float:right; margin-top:10px"><?php
2511
-                            echo $this->_get_help_tab_link('message_template_shortcodes');
2512
-                            ?></div>
2511
+							echo $this->_get_help_tab_link('message_template_shortcodes');
2512
+							?></div>
2513 2513
             <p class="small-text"><?php
2514
-                                  printf(
2515
-                                      esc_html__(
2516
-                                          'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2517
-                                          'event_espresso'
2518
-                                      ),
2519
-                                      '<span class="dashicons dashicons-menu"></span>'
2520
-                                  );
2521
-                                ?>
2514
+								  printf(
2515
+									  esc_html__(
2516
+										  'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2517
+										  'event_espresso'
2518
+									  ),
2519
+									  '<span class="dashicons dashicons-menu"></span>'
2520
+								  );
2521
+								?>
2522 2522
             </p>
2523 2523
             <?php
2524
-        }
2525
-    }
2526
-
2527
-
2528
-    /**
2529
-     * used to set the $_shortcodes property for when its needed elsewhere.
2530
-     *
2531
-     * @access protected
2532
-     * @return void
2533
-     * @throws EE_Error
2534
-     * @throws InvalidArgumentException
2535
-     * @throws ReflectionException
2536
-     * @throws InvalidDataTypeException
2537
-     * @throws InvalidInterfaceException
2538
-     */
2539
-    protected function _set_shortcodes()
2540
-    {
2541
-
2542
-        // no need to run this if the property is already set
2543
-        if (! empty($this->_shortcodes)) {
2544
-            return;
2545
-        }
2546
-
2547
-        $this->_shortcodes = $this->_get_shortcodes();
2548
-    }
2549
-
2550
-
2551
-    /**
2552
-     * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2553
-     * property)
2554
-     *
2555
-     * @access  protected
2556
-     * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2557
-     *                         for. Defaults to all (for the given context)
2558
-     * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2559
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2560
-     *                         true just an array of shortcode/label pairs.
2561
-     * @throws EE_Error
2562
-     * @throws InvalidArgumentException
2563
-     * @throws ReflectionException
2564
-     * @throws InvalidDataTypeException
2565
-     * @throws InvalidInterfaceException
2566
-     */
2567
-    protected function _get_shortcodes($fields = array(), $merged = true)
2568
-    {
2569
-        $this->_set_message_template_group();
2570
-
2571
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2572
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2573
-            ? absint($this->_req_data['id'])
2574
-            : false;
2575
-        $context = isset($this->_req_data['context'])
2576
-            ? $this->_req_data['context']
2577
-            : key($this->_message_template_group->contexts_config());
2578
-
2579
-        return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2580
-    }
2581
-
2582
-
2583
-    /**
2584
-     * This sets the _message_template property (containing the called message_template object)
2585
-     *
2586
-     * @access protected
2587
-     * @return void
2588
-     * @throws EE_Error
2589
-     * @throws InvalidArgumentException
2590
-     * @throws ReflectionException
2591
-     * @throws InvalidDataTypeException
2592
-     * @throws InvalidInterfaceException
2593
-     */
2594
-    protected function _set_message_template_group()
2595
-    {
2596
-
2597
-        if (! empty($this->_message_template_group)) {
2598
-            return;
2599
-        } //get out if this is already set.
2600
-
2601
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2602
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2603
-
2604
-        // let's get the message templates
2605
-        $MTP = EEM_Message_Template_Group::instance();
2606
-
2607
-        if (empty($GRP_ID)) {
2608
-            $this->_message_template_group = $MTP->create_default_object();
2609
-        } else {
2610
-            $this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2611
-        }
2612
-
2613
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2614
-        $this->_variation = $this->_message_template_group->get_template_pack_variation();
2615
-    }
2616
-
2617
-
2618
-    /**
2619
-     * sets up a context switcher for edit forms
2620
-     *
2621
-     * @access  protected
2622
-     * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2623
-     * @param array                      $args                  various things the context switcher needs.
2624
-     * @throws EE_Error
2625
-     */
2626
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2627
-    {
2628
-        $context_details = $template_group_object->contexts_config();
2629
-        $context_label = $template_group_object->context_label();
2630
-        ob_start();
2631
-        ?>
2524
+		}
2525
+	}
2526
+
2527
+
2528
+	/**
2529
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2530
+	 *
2531
+	 * @access protected
2532
+	 * @return void
2533
+	 * @throws EE_Error
2534
+	 * @throws InvalidArgumentException
2535
+	 * @throws ReflectionException
2536
+	 * @throws InvalidDataTypeException
2537
+	 * @throws InvalidInterfaceException
2538
+	 */
2539
+	protected function _set_shortcodes()
2540
+	{
2541
+
2542
+		// no need to run this if the property is already set
2543
+		if (! empty($this->_shortcodes)) {
2544
+			return;
2545
+		}
2546
+
2547
+		$this->_shortcodes = $this->_get_shortcodes();
2548
+	}
2549
+
2550
+
2551
+	/**
2552
+	 * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2553
+	 * property)
2554
+	 *
2555
+	 * @access  protected
2556
+	 * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2557
+	 *                         for. Defaults to all (for the given context)
2558
+	 * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2559
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2560
+	 *                         true just an array of shortcode/label pairs.
2561
+	 * @throws EE_Error
2562
+	 * @throws InvalidArgumentException
2563
+	 * @throws ReflectionException
2564
+	 * @throws InvalidDataTypeException
2565
+	 * @throws InvalidInterfaceException
2566
+	 */
2567
+	protected function _get_shortcodes($fields = array(), $merged = true)
2568
+	{
2569
+		$this->_set_message_template_group();
2570
+
2571
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2572
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2573
+			? absint($this->_req_data['id'])
2574
+			: false;
2575
+		$context = isset($this->_req_data['context'])
2576
+			? $this->_req_data['context']
2577
+			: key($this->_message_template_group->contexts_config());
2578
+
2579
+		return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2580
+	}
2581
+
2582
+
2583
+	/**
2584
+	 * This sets the _message_template property (containing the called message_template object)
2585
+	 *
2586
+	 * @access protected
2587
+	 * @return void
2588
+	 * @throws EE_Error
2589
+	 * @throws InvalidArgumentException
2590
+	 * @throws ReflectionException
2591
+	 * @throws InvalidDataTypeException
2592
+	 * @throws InvalidInterfaceException
2593
+	 */
2594
+	protected function _set_message_template_group()
2595
+	{
2596
+
2597
+		if (! empty($this->_message_template_group)) {
2598
+			return;
2599
+		} //get out if this is already set.
2600
+
2601
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2602
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2603
+
2604
+		// let's get the message templates
2605
+		$MTP = EEM_Message_Template_Group::instance();
2606
+
2607
+		if (empty($GRP_ID)) {
2608
+			$this->_message_template_group = $MTP->create_default_object();
2609
+		} else {
2610
+			$this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2611
+		}
2612
+
2613
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2614
+		$this->_variation = $this->_message_template_group->get_template_pack_variation();
2615
+	}
2616
+
2617
+
2618
+	/**
2619
+	 * sets up a context switcher for edit forms
2620
+	 *
2621
+	 * @access  protected
2622
+	 * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2623
+	 * @param array                      $args                  various things the context switcher needs.
2624
+	 * @throws EE_Error
2625
+	 */
2626
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2627
+	{
2628
+		$context_details = $template_group_object->contexts_config();
2629
+		$context_label = $template_group_object->context_label();
2630
+		ob_start();
2631
+		?>
2632 2632
         <div class="ee-msg-switcher-container">
2633 2633
             <form method="get" action="<?php echo EE_MSG_ADMIN_URL; ?>" id="ee-msg-context-switcher-frm">
2634 2634
                 <?php
2635
-                foreach ($args as $name => $value) {
2636
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2637
-                        continue;
2638
-                    }
2639
-                    ?>
2635
+				foreach ($args as $name => $value) {
2636
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2637
+						continue;
2638
+					}
2639
+					?>
2640 2640
                     <input type="hidden" name="<?php echo $name; ?>" value="<?php echo $value; ?>"/>
2641 2641
                     <?php
2642
-                }
2643
-                // setup nonce_url
2644
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2645
-                ?>
2642
+				}
2643
+				// setup nonce_url
2644
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2645
+				?>
2646 2646
                 <select name="context">
2647 2647
                     <?php
2648
-                    $context_templates = $template_group_object->context_templates();
2649
-                    if (is_array($context_templates)) :
2650
-                        foreach ($context_templates as $context => $template_fields) :
2651
-                            $checked = ($context === $args['context']) ? 'selected="selected"' : '';
2652
-                            ?>
2648
+					$context_templates = $template_group_object->context_templates();
2649
+					if (is_array($context_templates)) :
2650
+						foreach ($context_templates as $context => $template_fields) :
2651
+							$checked = ($context === $args['context']) ? 'selected="selected"' : '';
2652
+							?>
2653 2653
                             <option value="<?php echo $context; ?>" <?php echo $checked; ?>>
2654 2654
                                 <?php echo $context_details[ $context ]['label']; ?>
2655 2655
                             </option>
2656 2656
                         <?php endforeach;
2657
-                    endif; ?>
2657
+					endif; ?>
2658 2658
                 </select>
2659 2659
                 <?php $button_text = sprintf(__('Switch %s', 'event_espresso'), ucwords($context_label['label'])); ?>
2660 2660
                 <input id="submit-msg-context-switcher-sbmt" class="button-secondary" type="submit"
@@ -2663,1925 +2663,1925 @@  discard block
 block discarded – undo
2663 2663
             <?php echo $args['extra']; ?>
2664 2664
         </div> <!-- end .ee-msg-switcher-container -->
2665 2665
         <?php
2666
-        $output = ob_get_contents();
2667
-        ob_clean();
2668
-        $this->_context_switcher = $output;
2669
-    }
2670
-
2671
-
2672
-    /**
2673
-     * utility for sanitizing new values coming in.
2674
-     * Note: this is only used when updating a context.
2675
-     *
2676
-     * @access protected
2677
-     *
2678
-     * @param int $index This helps us know which template field to select from the request array.
2679
-     *
2680
-     * @return array
2681
-     */
2682
-    protected function _set_message_template_column_values($index)
2683
-    {
2684
-        if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2685
-            foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2686
-                $this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2687
-            }
2688
-        }
2689
-
2690
-
2691
-        $set_column_values = array(
2692
-            'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2693
-            'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2694
-            'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2695
-            'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2696
-            'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2697
-            'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2698
-            'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2699
-            'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2700
-            'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2701
-                ? absint($this->_req_data['MTP_is_global'])
2702
-                : 0,
2703
-            'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2704
-                ? absint($this->_req_data['MTP_is_override'])
2705
-                : 0,
2706
-            'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2707
-            'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2708
-        );
2709
-
2710
-
2711
-        return $set_column_values;
2712
-    }
2713
-
2714
-
2715
-    protected function _insert_or_update_message_template($new = false)
2716
-    {
2717
-
2718
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2719
-        $success = 0;
2720
-        $override = false;
2721
-
2722
-        // setup notices description
2723
-        $messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2724
-
2725
-        // need the message type and messenger objects to be able to use the labels for the notices
2726
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2727
-        $messenger_label = $messenger_object instanceof EE_messenger
2728
-            ? ucwords($messenger_object->label['singular'])
2729
-            : '';
2730
-
2731
-        $message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2732
-            ? $this->_req_data['MTP_message_type']
2733
-            : '';
2734
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2735
-
2736
-        $message_type_label = $message_type_object instanceof EE_message_type
2737
-            ? ucwords($message_type_object->label['singular'])
2738
-            : '';
2739
-
2740
-        $context_slug = ! empty($this->_req_data['MTP_context'])
2741
-            ? $this->_req_data['MTP_context']
2742
-            : '';
2743
-        $context = ucwords(str_replace('_', ' ', $context_slug));
2744
-
2745
-        $item_desc = $messenger_label && $message_type_label
2746
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2747
-            : '';
2748
-        $item_desc .= 'Message Template';
2749
-        $query_args = array();
2750
-        $edit_array = array();
2751
-        $action_desc = '';
2752
-
2753
-        // if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2754
-        // user to edit.
2755
-        if ($new) {
2756
-            $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2757
-            if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2758
-                if (empty($edit_array)) {
2759
-                    $success = 0;
2760
-                } else {
2761
-                    $success = 1;
2762
-                    $edit_array = $edit_array[0];
2763
-                    $query_args = array(
2764
-                        'id'      => $edit_array['GRP_ID'],
2765
-                        'context' => $edit_array['MTP_context'],
2766
-                        'action'  => 'edit_message_template',
2767
-                    );
2768
-                }
2769
-            }
2770
-            $action_desc = 'created';
2771
-        } else {
2772
-            $MTPG = EEM_Message_Template_Group::instance();
2773
-            $MTP = EEM_Message_Template::instance();
2774
-
2775
-
2776
-            // run update for each template field in displayed context
2777
-            if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2778
-                EE_Error::add_error(
2779
-                    esc_html__(
2780
-                        'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2781
-                        'event_espresso'
2782
-                    ),
2783
-                    __FILE__,
2784
-                    __FUNCTION__,
2785
-                    __LINE__
2786
-                );
2787
-                $success = 0;
2788
-            } else {
2789
-                // first validate all fields!
2790
-                // this filter allows client code to add its own validation to the template fields as well.
2791
-                // returning an empty array means everything passed validation.
2792
-                // errors in validation should be represented in an array with the following shape:
2793
-                // array(
2794
-                //   'fieldname' => array(
2795
-                //          'msg' => 'error message'
2796
-                //          'value' => 'value for field producing error'
2797
-                // )
2798
-                $custom_validation = (array) apply_filters(
2799
-                    'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2800
-                    array(),
2801
-                    $this->_req_data['MTP_template_fields'],
2802
-                    $context_slug,
2803
-                    $messenger_slug,
2804
-                    $message_type_slug
2805
-                );
2806
-
2807
-                $system_validation = $MTPG->validate(
2808
-                    $this->_req_data['MTP_template_fields'],
2809
-                    $context_slug,
2810
-                    $messenger_slug,
2811
-                    $message_type_slug
2812
-                );
2813
-
2814
-                $system_validation = ! is_array($system_validation) && $system_validation ? array()
2815
-                    : $system_validation;
2816
-                $validates = array_merge($custom_validation, $system_validation);
2817
-
2818
-                // if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2819
-                // appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2820
-                //  WE need to make sure there is no actual error messages in validates.
2821
-                if (is_array($validates) && ! empty($validates)) {
2822
-                    // add the transient so when the form loads we know which fields to highlight
2823
-                    $this->_add_transient('edit_message_template', $validates);
2824
-
2825
-                    $success = 0;
2826
-
2827
-                    // setup notices
2828
-                    foreach ($validates as $field => $error) {
2829
-                        if (isset($error['msg'])) {
2830
-                            EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2831
-                        }
2832
-                    }
2833
-                } else {
2834
-                    $set_column_values = array();
2835
-                    foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2836
-                        $set_column_values = $this->_set_message_template_column_values($template_field);
2837
-
2838
-                        $where_cols_n_values = array(
2839
-                            'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2840
-                        );
2841
-                        // if they aren't allowed to use all JS, restrict them to just posty-y tags
2842
-                        if (! current_user_can('unfiltered_html')) {
2843
-                            if (is_array($set_column_values['MTP_content'])) {
2844
-                                foreach ($set_column_values['MTP_content'] as $key => $value) {
2845
-                                    // remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2846
-                                    // only removes slashes from double-quotes, so attributes using single quotes always
2847
-                                    // appear invalid.) But currently the models expect slashed data, so after wp_kses
2848
-                                    // runs we need to re-slash the data. Sheesh. See
2849
-                                    // https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2850
-                                    $set_column_values['MTP_content'][ $key ] = addslashes(
2851
-                                        wp_kses(
2852
-                                            stripslashes($value),
2853
-                                            wp_kses_allowed_html('post')
2854
-                                        )
2855
-                                    );
2856
-                                }
2857
-                            } else {
2858
-                                $set_column_values['MTP_content'] = wp_kses(
2859
-                                    $set_column_values['MTP_content'],
2860
-                                    wp_kses_allowed_html('post')
2861
-                                );
2862
-                            }
2863
-                        }
2864
-                        $message_template_fields = array(
2865
-                            'GRP_ID'             => $set_column_values['GRP_ID'],
2866
-                            'MTP_template_field' => $set_column_values['MTP_template_field'],
2867
-                            'MTP_context'        => $set_column_values['MTP_context'],
2868
-                            'MTP_content'        => $set_column_values['MTP_content'],
2869
-                        );
2870
-                        if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2871
-                            if ($updated === false) {
2872
-                                EE_Error::add_error(
2873
-                                    sprintf(
2874
-                                        esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2875
-                                        $template_field
2876
-                                    ),
2877
-                                    __FILE__,
2878
-                                    __FUNCTION__,
2879
-                                    __LINE__
2880
-                                );
2881
-                            } else {
2882
-                                $success = 1;
2883
-                            }
2884
-                        } else {
2885
-                            // only do this logic if we don't have a MTP_ID for this field
2886
-                            if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2887
-                                // this has already been through the template field validator and sanitized, so it will be
2888
-                                // safe to insert this field.  Why insert?  This typically happens when we introduce a new
2889
-                                // message template field in a messenger/message type and existing users don't have the
2890
-                                // default setup for it.
2891
-                                // @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2892
-                                $updated = $MTP->insert($message_template_fields);
2893
-                                if (! $updated || is_wp_error($updated)) {
2894
-                                    EE_Error::add_error(
2895
-                                        sprintf(
2896
-                                            esc_html__('%s field could not be updated.', 'event_espresso'),
2897
-                                            $template_field
2898
-                                        ),
2899
-                                        __FILE__,
2900
-                                        __FUNCTION__,
2901
-                                        __LINE__
2902
-                                    );
2903
-                                    $success = 0;
2904
-                                } else {
2905
-                                    $success = 1;
2906
-                                }
2907
-                            }
2908
-                        }
2909
-                        $action_desc = 'updated';
2910
-                    }
2911
-
2912
-                    // we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2913
-                    $mtpg_fields = array(
2914
-                        'MTP_user_id'      => $set_column_values['MTP_user_id'],
2915
-                        'MTP_messenger'    => $set_column_values['MTP_messenger'],
2916
-                        'MTP_message_type' => $set_column_values['MTP_message_type'],
2917
-                        'MTP_is_global'    => $set_column_values['MTP_is_global'],
2918
-                        'MTP_is_override'  => $set_column_values['MTP_is_override'],
2919
-                        'MTP_deleted'      => $set_column_values['MTP_deleted'],
2920
-                        'MTP_is_active'    => $set_column_values['MTP_is_active'],
2921
-                        'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2922
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2923
-                            : '',
2924
-                        'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2925
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2926
-                            : '',
2927
-                    );
2928
-
2929
-                    $mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2930
-                    $updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2931
-
2932
-                    if ($updated === false) {
2933
-                        EE_Error::add_error(
2934
-                            sprintf(
2935
-                                esc_html__(
2936
-                                    'The Message Template Group (%d) was NOT updated for some reason',
2937
-                                    'event_espresso'
2938
-                                ),
2939
-                                $set_column_values['GRP_ID']
2940
-                            ),
2941
-                            __FILE__,
2942
-                            __FUNCTION__,
2943
-                            __LINE__
2944
-                        );
2945
-                    } else {
2946
-                        // k now we need to ensure the template_pack and template_variation fields are set.
2947
-                        $template_pack = ! empty($this->_req_data['MTP_template_pack'])
2948
-                            ? $this->_req_data['MTP_template_pack']
2949
-                            : 'default';
2950
-
2951
-                        $template_variation = ! empty($this->_req_data['MTP_template_variation'])
2952
-                            ? $this->_req_data['MTP_template_variation']
2953
-                            : 'default';
2954
-
2955
-                        $mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2956
-                        if ($mtpg_obj instanceof EE_Message_Template_Group) {
2957
-                            $mtpg_obj->set_template_pack_name($template_pack);
2958
-                            $mtpg_obj->set_template_pack_variation($template_variation);
2959
-                        }
2960
-                        $success = 1;
2961
-                    }
2962
-                }
2963
-            }
2964
-        }
2965
-
2966
-        // we return things differently if doing ajax
2967
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2968
-            $this->_template_args['success'] = $success;
2969
-            $this->_template_args['error'] = ! $success ? true : false;
2970
-            $this->_template_args['content'] = '';
2971
-            $this->_template_args['data'] = array(
2972
-                'grpID'        => $edit_array['GRP_ID'],
2973
-                'templateName' => $edit_array['template_name'],
2974
-            );
2975
-            if ($success) {
2976
-                EE_Error::overwrite_success();
2977
-                EE_Error::add_success(
2978
-                    esc_html__(
2979
-                        'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2980
-                        'event_espresso'
2981
-                    )
2982
-                );
2983
-            }
2984
-
2985
-            $this->_return_json();
2986
-        }
2987
-
2988
-
2989
-        // was a test send triggered?
2990
-        if (isset($this->_req_data['test_button'])) {
2991
-            EE_Error::overwrite_success();
2992
-            $this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
2993
-            $override = true;
2994
-        }
2995
-
2996
-        if (empty($query_args)) {
2997
-            $query_args = array(
2998
-                'id'      => $this->_req_data['GRP_ID'],
2999
-                'context' => $context_slug,
3000
-                'action'  => 'edit_message_template',
3001
-            );
3002
-        }
3003
-
3004
-        $this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3005
-    }
3006
-
3007
-
3008
-    /**
3009
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
3010
-     *
3011
-     * @param  string $context      what context being tested
3012
-     * @param  string $messenger    messenger being tested
3013
-     * @param  string $message_type message type being tested
3014
-     * @throws EE_Error
3015
-     * @throws InvalidArgumentException
3016
-     * @throws InvalidDataTypeException
3017
-     * @throws InvalidInterfaceException
3018
-     */
3019
-    protected function _do_test_send($context, $messenger, $message_type)
3020
-    {
3021
-        // set things up for preview
3022
-        $this->_req_data['messenger'] = $messenger;
3023
-        $this->_req_data['message_type'] = $message_type;
3024
-        $this->_req_data['context'] = $context;
3025
-        $this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3026
-        $active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3027
-
3028
-        // let's save any existing fields that might be required by the messenger
3029
-        if (isset($this->_req_data['test_settings_fld'])
3030
-            && $active_messenger instanceof EE_messenger
3031
-            && apply_filters(
3032
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3033
-                true,
3034
-                $this->_req_data['test_settings_fld'],
3035
-                $active_messenger
3036
-            )
3037
-        ) {
3038
-            $active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3039
-        }
3040
-
3041
-        /**
3042
-         * Use filter to add additional controls on whether message can send or not
3043
-         */
3044
-        if (apply_filters(
3045
-            'FHEE__Messages_Admin_Page__do_test_send__can_send',
3046
-            true,
3047
-            $context,
3048
-            $this->_req_data,
3049
-            $messenger,
3050
-            $message_type
3051
-        )) {
3052
-            if (EEM_Event::instance()->count() > 0) {
3053
-                $success = $this->_preview_message(true);
3054
-                if ($success) {
3055
-                    EE_Error::add_success(__('Test message sent', 'event_espresso'));
3056
-                } else {
3057
-                    EE_Error::add_error(
3058
-                        esc_html__('The test message was not sent', 'event_espresso'),
3059
-                        __FILE__,
3060
-                        __FUNCTION__,
3061
-                        __LINE__
3062
-                    );
3063
-                }
3064
-            } else {
3065
-                $this->noEventsErrorMessage(true);
3066
-            }
3067
-        }
3068
-    }
3069
-
3070
-
3071
-    /**
3072
-     * _generate_new_templates
3073
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3074
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3075
-     * for the event.
3076
-     *
3077
-     *
3078
-     * @param  string $messenger     the messenger we are generating templates for
3079
-     * @param array   $message_types array of message types that the templates are generated for.
3080
-     * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3081
-     *                               indicate the message_template_group being used as the base.
3082
-     *
3083
-     * @param bool    $global
3084
-     *
3085
-     * @return array|bool array of data required for the redirect to the correct edit page or bool if
3086
-     *                               encountering problems.
3087
-     * @throws EE_Error
3088
-     */
3089
-    protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3090
-    {
3091
-
3092
-        // if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3093
-        // just don't generate any templates.
3094
-        if (empty($message_types)) {
3095
-            return true;
3096
-        }
3097
-
3098
-        return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3099
-    }
3100
-
3101
-
3102
-    /**
3103
-     * [_trash_or_restore_message_template]
3104
-     *
3105
-     * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3106
-     * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3107
-     *                        an individual context (FALSE).
3108
-     * @return void
3109
-     * @throws EE_Error
3110
-     * @throws InvalidArgumentException
3111
-     * @throws InvalidDataTypeException
3112
-     * @throws InvalidInterfaceException
3113
-     */
3114
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
3115
-    {
3116
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3117
-        $MTP = EEM_Message_Template_Group::instance();
3118
-
3119
-        $success = 1;
3120
-
3121
-        // incoming GRP_IDs
3122
-        if ($all) {
3123
-            // Checkboxes
3124
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3125
-                // if array has more than one element then success message should be plural.
3126
-                // todo: what about nonce?
3127
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3128
-
3129
-                // cycle through checkboxes
3130
-                while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3131
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3132
-                    if (! $trashed_or_restored) {
3133
-                        $success = 0;
3134
-                    }
3135
-                }
3136
-            } else {
3137
-                // grab single GRP_ID and handle
3138
-                $GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3139
-                if (! empty($GRP_ID)) {
3140
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3141
-                    if (! $trashed_or_restored) {
3142
-                        $success = 0;
3143
-                    }
3144
-                } else {
3145
-                    $success = 0;
3146
-                }
3147
-            }
3148
-        }
3149
-
3150
-        $action_desc = $trash
3151
-            ? esc_html__('moved to the trash', 'event_espresso')
3152
-            : esc_html__('restored', 'event_espresso');
3153
-
3154
-        $action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3155
-
3156
-        $item_desc = $all ? _n(
3157
-            'Message Template Group',
3158
-            'Message Template Groups',
3159
-            $success,
3160
-            'event_espresso'
3161
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3162
-
3163
-        $item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3164
-            'template',
3165
-            'templates',
3166
-            $success,
3167
-            'event_espresso'
3168
-        ) : $item_desc;
3169
-
3170
-        $this->_redirect_after_action($success, $item_desc, $action_desc, array());
3171
-    }
3172
-
3173
-
3174
-    /**
3175
-     * [_delete_message_template]
3176
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3177
-     *
3178
-     * @return void
3179
-     * @throws EE_Error
3180
-     * @throws InvalidArgumentException
3181
-     * @throws InvalidDataTypeException
3182
-     * @throws InvalidInterfaceException
3183
-     */
3184
-    protected function _delete_message_template()
3185
-    {
3186
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3187
-
3188
-        // checkboxes
3189
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3190
-            // if array has more than one element then success message should be plural
3191
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3192
-
3193
-            // cycle through bulk action checkboxes
3194
-            while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3195
-                $success = $this->_delete_mtp_permanently($GRP_ID);
3196
-            }
3197
-        } else {
3198
-            // grab single grp_id and delete
3199
-            $GRP_ID = absint($this->_req_data['id']);
3200
-            $success = $this->_delete_mtp_permanently($GRP_ID);
3201
-        }
3202
-
3203
-        $this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3204
-    }
3205
-
3206
-
3207
-    /**
3208
-     * helper for permanently deleting a mtP group and all related message_templates
3209
-     *
3210
-     * @param  int  $GRP_ID        The group being deleted
3211
-     * @param  bool $include_group whether to delete the Message Template Group as well.
3212
-     * @return bool boolean to indicate the success of the deletes or not.
3213
-     * @throws EE_Error
3214
-     * @throws InvalidArgumentException
3215
-     * @throws InvalidDataTypeException
3216
-     * @throws InvalidInterfaceException
3217
-     */
3218
-    private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3219
-    {
3220
-        $success = 1;
3221
-        $MTPG = EEM_Message_Template_Group::instance();
3222
-        // first let's GET this group
3223
-        $MTG = $MTPG->get_one_by_ID($GRP_ID);
3224
-        // then delete permanently all the related Message Templates
3225
-        $deleted = $MTG->delete_related_permanently('Message_Template');
3226
-
3227
-        if ($deleted === 0) {
3228
-            $success = 0;
3229
-        }
3230
-
3231
-        // now delete permanently this particular group
3232
-
3233
-        if ($include_group && ! $MTG->delete_permanently()) {
3234
-            $success = 0;
3235
-        }
3236
-
3237
-        return $success;
3238
-    }
3239
-
3240
-
3241
-    /**
3242
-     *    _learn_more_about_message_templates_link
3243
-     *
3244
-     * @access protected
3245
-     * @return string
3246
-     */
3247
-    protected function _learn_more_about_message_templates_link()
3248
-    {
3249
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3250
-               . esc_html__('learn more about how message templates works', 'event_espresso')
3251
-               . '</a>';
3252
-    }
3253
-
3254
-
3255
-    /**
3256
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3257
-     * ajax and other routes.
3258
-     *
3259
-     * @return void
3260
-     * @throws DomainException
3261
-     */
3262
-    protected function _settings()
3263
-    {
3264
-
3265
-
3266
-        $this->_set_m_mt_settings();
3267
-
3268
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3269
-            ? $this->_req_data['selected_messenger']
3270
-            : 'email';
3271
-
3272
-        // let's setup the messenger tabs
3273
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3274
-            $this->_m_mt_settings['messenger_tabs'],
3275
-            'messenger_links',
3276
-            '|',
3277
-            $selected_messenger
3278
-        );
3279
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3280
-        $this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3281
-
3282
-        $this->display_admin_page_with_sidebar();
3283
-    }
3284
-
3285
-
3286
-    /**
3287
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3288
-     *
3289
-     * @access protected
3290
-     * @return void
3291
-     * @throws DomainException
3292
-     */
3293
-    protected function _set_m_mt_settings()
3294
-    {
3295
-        // first if this is already set then lets get out no need to regenerate data.
3296
-        if (! empty($this->_m_mt_settings)) {
3297
-            return;
3298
-        }
3299
-
3300
-        // get all installed messengers and message_types
3301
-        /** @type EE_messenger[] $messengers */
3302
-        $messengers = $this->_message_resource_manager->installed_messengers();
3303
-        /** @type EE_message_type[] $message_types */
3304
-        $message_types = $this->_message_resource_manager->installed_message_types();
3305
-
3306
-
3307
-        // assemble the array for the _tab_text_links helper
3308
-
3309
-        foreach ($messengers as $messenger) {
3310
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3311
-                'label' => ucwords($messenger->label['singular']),
3312
-                'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3313
-                    ? 'messenger-active'
3314
-                    : '',
3315
-                'href'  => $messenger->name,
3316
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3317
-                'slug'  => $messenger->name,
3318
-                'obj'   => $messenger,
3319
-            );
3320
-
3321
-
3322
-            $message_types_for_messenger = $messenger->get_valid_message_types();
3323
-
3324
-            foreach ($message_types as $message_type) {
3325
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3326
-                // it shouldn't show in either the inactive OR active metabox.
3327
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3328
-                    continue;
3329
-                }
3330
-
3331
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3332
-                    $messenger->name,
3333
-                    $message_type->name
3334
-                )
3335
-                    ? 'active'
3336
-                    : 'inactive';
3337
-
3338
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3339
-                    'label'    => ucwords($message_type->label['singular']),
3340
-                    'class'    => 'message-type-' . $a_or_i,
3341
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3342
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3343
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3344
-                    'title'    => $a_or_i === 'active'
3345
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3346
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3347
-                    'content'  => $a_or_i === 'active'
3348
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
3349
-                        : $this->_message_type_settings_content($message_type, $messenger),
3350
-                    'slug'     => $message_type->name,
3351
-                    'active'   => $a_or_i === 'active',
3352
-                    'obj'      => $message_type,
3353
-                );
3354
-            }
3355
-        }
3356
-    }
3357
-
3358
-
3359
-    /**
3360
-     * This just prepares the content for the message type settings
3361
-     *
3362
-     * @param  EE_message_type $message_type The message type object
3363
-     * @param  EE_messenger    $messenger    The messenger object
3364
-     * @param  boolean         $active       Whether the message type is active or not
3365
-     * @return string html output for the content
3366
-     * @throws DomainException
3367
-     */
3368
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
3369
-    {
3370
-        // get message type fields
3371
-        $fields = $message_type->get_admin_settings_fields();
3372
-        $settings_template_args['template_form_fields'] = '';
3373
-
3374
-        if (! empty($fields) && $active) {
3375
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3376
-            foreach ($fields as $fldname => $fldprops) {
3377
-                $field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3378
-                $template_form_field[ $field_id ] = array(
3379
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3380
-                    'label'      => $fldprops['label'],
3381
-                    'input'      => $fldprops['field_type'],
3382
-                    'type'       => $fldprops['value_type'],
3383
-                    'required'   => $fldprops['required'],
3384
-                    'validation' => $fldprops['validation'],
3385
-                    'value'      => isset($existing_settings[ $fldname ])
3386
-                        ? $existing_settings[ $fldname ]
3387
-                        : $fldprops['default'],
3388
-                    'options'    => isset($fldprops['options'])
3389
-                        ? $fldprops['options']
3390
-                        : array(),
3391
-                    'default'    => isset($existing_settings[ $fldname ])
3392
-                        ? $existing_settings[ $fldname ]
3393
-                        : $fldprops['default'],
3394
-                    'css_class'  => 'no-drag',
3395
-                    'format'     => $fldprops['format'],
3396
-                );
3397
-            }
3398
-
3399
-
3400
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3401
-                ? $this->_generate_admin_form_fields(
3402
-                    $template_form_field,
3403
-                    'string',
3404
-                    'ee_mt_activate_form'
3405
-                )
3406
-                : '';
3407
-        }
3408
-
3409
-        $settings_template_args['description'] = $message_type->description;
3410
-        // we also need some hidden fields
3411
-        $settings_template_args['hidden_fields'] = array(
3412
-            'message_type_settings[messenger]'    => array(
3413
-                'type'  => 'hidden',
3414
-                'value' => $messenger->name,
3415
-            ),
3416
-            'message_type_settings[message_type]' => array(
3417
-                'type'  => 'hidden',
3418
-                'value' => $message_type->name,
3419
-            ),
3420
-            'type'                                => array(
3421
-                'type'  => 'hidden',
3422
-                'value' => 'message_type',
3423
-            ),
3424
-        );
3425
-
3426
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3427
-            $settings_template_args['hidden_fields'],
3428
-            'array'
3429
-        );
3430
-        $settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3431
-            ? ' hidden'
3432
-            : '';
3433
-
3434
-
3435
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3436
-        $content = EEH_Template::display_template($template, $settings_template_args, true);
3437
-
3438
-        return $content;
3439
-    }
3440
-
3441
-
3442
-    /**
3443
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3444
-     *
3445
-     * @access protected
3446
-     * @return void
3447
-     * @throws DomainException
3448
-     */
3449
-    protected function _messages_settings_metaboxes()
3450
-    {
3451
-        $this->_set_m_mt_settings();
3452
-        $m_boxes = $mt_boxes = array();
3453
-        $m_template_args = $mt_template_args = array();
3454
-
3455
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3456
-            ? $this->_req_data['selected_messenger']
3457
-            : 'email';
3458
-
3459
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3460
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3461
-                $hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3462
-                $hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3463
-                // messenger meta boxes
3464
-                $active = $selected_messenger === $messenger;
3465
-                $active_mt_tabs = isset(
3466
-                    $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3467
-                )
3468
-                    ? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3469
-                    : '';
3470
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3471
-                    esc_html__('%s Settings', 'event_espresso'),
3472
-                    $tab_array['label']
3473
-                );
3474
-                $m_template_args[ $messenger . '_a_box' ] = array(
3475
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3476
-                    'inactive_message_types' => isset(
3477
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3478
-                    )
3479
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3480
-                        : '',
3481
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3482
-                    'hidden'                 => $active ? '' : ' hidden',
3483
-                    'hide_on_message'        => $hide_on_message,
3484
-                    'messenger'              => $messenger,
3485
-                    'active'                 => $active,
3486
-                );
3487
-                // message type meta boxes
3488
-                // (which is really just the inactive container for each messenger
3489
-                // showing inactive message types for that messenger)
3490
-                $mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3491
-                $mt_template_args[ $messenger . '_i_box' ] = array(
3492
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3493
-                    'inactive_message_types' => isset(
3494
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3495
-                    )
3496
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3497
-                        : '',
3498
-                    'hidden'                 => $active ? '' : ' hidden',
3499
-                    'hide_on_message'        => $hide_on_message,
3500
-                    'hide_off_message'       => $hide_off_message,
3501
-                    'messenger'              => $messenger,
3502
-                    'active'                 => $active,
3503
-                );
3504
-            }
3505
-        }
3506
-
3507
-
3508
-        // register messenger metaboxes
3509
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3510
-        foreach ($m_boxes as $box => $label) {
3511
-            $callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3512
-            $msgr = str_replace('_a_box', '', $box);
3513
-            add_meta_box(
3514
-                'espresso_' . $msgr . '_settings',
3515
-                $label,
3516
-                function ($post, $metabox) {
3517
-                    echo EEH_Template::display_template(
3518
-                        $metabox["args"]["template_path"],
3519
-                        $metabox["args"]["template_args"],
3520
-                        true
3521
-                    );
3522
-                },
3523
-                $this->_current_screen->id,
3524
-                'normal',
3525
-                'high',
3526
-                $callback_args
3527
-            );
3528
-        }
3529
-
3530
-        // register message type metaboxes
3531
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3532
-        foreach ($mt_boxes as $box => $label) {
3533
-            $callback_args = array(
3534
-                'template_path' => $mt_template_path,
3535
-                'template_args' => $mt_template_args[ $box ],
3536
-            );
3537
-            $mt = str_replace('_i_box', '', $box);
3538
-            add_meta_box(
3539
-                'espresso_' . $mt . '_inactive_mts',
3540
-                $label,
3541
-                function ($post, $metabox) {
3542
-                    echo EEH_Template::display_template(
3543
-                        $metabox["args"]["template_path"],
3544
-                        $metabox["args"]["template_args"],
3545
-                        true
3546
-                    );
3547
-                },
3548
-                $this->_current_screen->id,
3549
-                'side',
3550
-                'high',
3551
-                $callback_args
3552
-            );
3553
-        }
3554
-
3555
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3556
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3557
-        if (is_main_site()) {
3558
-            add_meta_box(
3559
-                'espresso_global_message_settings',
3560
-                esc_html__('Global Message Settings', 'event_espresso'),
3561
-                array($this, 'global_messages_settings_metabox_content'),
3562
-                $this->_current_screen->id,
3563
-                'normal',
3564
-                'low',
3565
-                array()
3566
-            );
3567
-        }
3568
-    }
3569
-
3570
-
3571
-    /**
3572
-     *  This generates the content for the global messages settings metabox.
3573
-     *
3574
-     * @return string
3575
-     * @throws EE_Error
3576
-     * @throws InvalidArgumentException
3577
-     * @throws ReflectionException
3578
-     * @throws InvalidDataTypeException
3579
-     * @throws InvalidInterfaceException
3580
-     */
3581
-    public function global_messages_settings_metabox_content()
3582
-    {
3583
-        $form = $this->_generate_global_settings_form();
3584
-        echo $form->form_open(
3585
-            $this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3586
-            'POST'
3587
-        )
3588
-             . $form->get_html()
3589
-             . $form->form_close();
3590
-    }
3591
-
3592
-
3593
-    /**
3594
-     * This generates and returns the form object for the global messages settings.
3595
-     *
3596
-     * @return EE_Form_Section_Proper
3597
-     * @throws EE_Error
3598
-     * @throws InvalidArgumentException
3599
-     * @throws ReflectionException
3600
-     * @throws InvalidDataTypeException
3601
-     * @throws InvalidInterfaceException
3602
-     */
3603
-    protected function _generate_global_settings_form()
3604
-    {
3605
-        EE_Registry::instance()->load_helper('HTML');
3606
-        /** @var EE_Network_Core_Config $network_config */
3607
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3608
-
3609
-        return new EE_Form_Section_Proper(
3610
-            array(
3611
-                'name'            => 'global_messages_settings',
3612
-                'html_id'         => 'global_messages_settings',
3613
-                'html_class'      => 'form-table',
3614
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3615
-                'subsections'     => apply_filters(
3616
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3617
-                    array(
3618
-                        'do_messages_on_same_request' => new EE_Select_Input(
3619
-                            array(
3620
-                                true  => esc_html__("On the same request", "event_espresso"),
3621
-                                false => esc_html__("On a separate request", "event_espresso"),
3622
-                            ),
3623
-                            array(
3624
-                                'default'         => $network_config->do_messages_on_same_request,
3625
-                                'html_label_text' => esc_html__(
3626
-                                    'Generate and send all messages:',
3627
-                                    'event_espresso'
3628
-                                ),
3629
-                                'html_help_text'  => esc_html__(
3630
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3631
-                                    'event_espresso'
3632
-                                ),
3633
-                            )
3634
-                        ),
3635
-                        'delete_threshold'            => new EE_Select_Input(
3636
-                            array(
3637
-                                0  => esc_html__('Forever', 'event_espresso'),
3638
-                                3  => esc_html__('3 Months', 'event_espresso'),
3639
-                                6  => esc_html__('6 Months', 'event_espresso'),
3640
-                                9  => esc_html__('9 Months', 'event_espresso'),
3641
-                                12 => esc_html__('12 Months', 'event_espresso'),
3642
-                                24 => esc_html__('24 Months', 'event_espresso'),
3643
-                                36 => esc_html__('36 Months', 'event_espresso'),
3644
-                            ),
3645
-                            array(
3646
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3647
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3648
-                                'html_help_text'  => esc_html__(
3649
-                                    'You can control how long a record of processed messages is kept via this option.',
3650
-                                    'event_espresso'
3651
-                                ),
3652
-                            )
3653
-                        ),
3654
-                        'update_settings'             => new EE_Submit_Input(
3655
-                            array(
3656
-                                'default'         => esc_html__('Update', 'event_espresso'),
3657
-                                'html_label_text' => '&nbsp',
3658
-                            )
3659
-                        ),
3660
-                    )
3661
-                ),
3662
-            )
3663
-        );
3664
-    }
3665
-
3666
-
3667
-    /**
3668
-     * This handles updating the global settings set on the admin page.
3669
-     *
3670
-     * @throws EE_Error
3671
-     * @throws InvalidDataTypeException
3672
-     * @throws InvalidInterfaceException
3673
-     * @throws InvalidArgumentException
3674
-     * @throws ReflectionException
3675
-     */
3676
-    protected function _update_global_settings()
3677
-    {
3678
-        /** @var EE_Network_Core_Config $network_config */
3679
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3680
-        $messages_config = EE_Registry::instance()->CFG->messages;
3681
-        $form = $this->_generate_global_settings_form();
3682
-        if ($form->was_submitted()) {
3683
-            $form->receive_form_submission();
3684
-            if ($form->is_valid()) {
3685
-                $valid_data = $form->valid_data();
3686
-                foreach ($valid_data as $property => $value) {
3687
-                    $setter = 'set_' . $property;
3688
-                    if (method_exists($network_config, $setter)) {
3689
-                        $network_config->{$setter}($value);
3690
-                    } elseif (property_exists($network_config, $property)
3691
-                        && $network_config->{$property} !== $value
3692
-                    ) {
3693
-                        $network_config->{$property} = $value;
3694
-                    } elseif (property_exists($messages_config, $property)
3695
-                        && $messages_config->{$property} !== $value
3696
-                    ) {
3697
-                        $messages_config->{$property} = $value;
3698
-                    }
3699
-                }
3700
-                // only update if the form submission was valid!
3701
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3702
-                EE_Registry::instance()->CFG->update_espresso_config();
3703
-                EE_Error::overwrite_success();
3704
-                EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3705
-            }
3706
-        }
3707
-        $this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3708
-    }
3709
-
3710
-
3711
-    /**
3712
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3713
-     *
3714
-     * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3715
-     * @return string html formatted tabs
3716
-     * @throws DomainException
3717
-     */
3718
-    protected function _get_mt_tabs($tab_array)
3719
-    {
3720
-        $tab_array = (array) $tab_array;
3721
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3722
-        $tabs = '';
3723
-
3724
-        foreach ($tab_array as $tab) {
3725
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3726
-        }
3727
-
3728
-        return $tabs;
3729
-    }
3730
-
3731
-
3732
-    /**
3733
-     * This prepares the content of the messenger meta box admin settings
3734
-     *
3735
-     * @param  EE_messenger $messenger The messenger we're setting up content for
3736
-     * @return string html formatted content
3737
-     * @throws DomainException
3738
-     */
3739
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3740
-    {
3741
-
3742
-        $fields = $messenger->get_admin_settings_fields();
3743
-        $settings_template_args['template_form_fields'] = '';
3744
-
3745
-        // is $messenger active?
3746
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3747
-
3748
-
3749
-        if (! empty($fields)) {
3750
-            $existing_settings = $messenger->get_existing_admin_settings();
3751
-
3752
-            foreach ($fields as $fldname => $fldprops) {
3753
-                $field_id = $messenger->name . '-' . $fldname;
3754
-                $template_form_field[ $field_id ] = array(
3755
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3756
-                    'label'      => $fldprops['label'],
3757
-                    'input'      => $fldprops['field_type'],
3758
-                    'type'       => $fldprops['value_type'],
3759
-                    'required'   => $fldprops['required'],
3760
-                    'validation' => $fldprops['validation'],
3761
-                    'value'      => isset($existing_settings[ $field_id ])
3762
-                        ? $existing_settings[ $field_id ]
3763
-                        : $fldprops['default'],
3764
-                    'css_class'  => '',
3765
-                    'format'     => $fldprops['format'],
3766
-                );
3767
-            }
3768
-
3769
-
3770
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3771
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3772
-                : '';
3773
-        }
3774
-
3775
-        // we also need some hidden fields
3776
-        $settings_template_args['hidden_fields'] = array(
3777
-            'messenger_settings[messenger]' => array(
3778
-                'type'  => 'hidden',
3779
-                'value' => $messenger->name,
3780
-            ),
3781
-            'type'                          => array(
3782
-                'type'  => 'hidden',
3783
-                'value' => 'messenger',
3784
-            ),
3785
-        );
3786
-
3787
-        // make sure any active message types that are existing are included in the hidden fields
3788
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3789
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3790
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3791
-                    'type'  => 'hidden',
3792
-                    'value' => $mt,
3793
-                );
3794
-            }
3795
-        }
3796
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3797
-            $settings_template_args['hidden_fields'],
3798
-            'array'
3799
-        );
3800
-        $active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3801
-
3802
-        $settings_template_args['messenger'] = $messenger->name;
3803
-        $settings_template_args['description'] = $messenger->description;
3804
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3805
-
3806
-
3807
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3808
-            $messenger->name
3809
-        )
3810
-            ? $settings_template_args['show_hide_edit_form']
3811
-            : ' hidden';
3812
-
3813
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3814
-            ? ' hidden'
3815
-            : $settings_template_args['show_hide_edit_form'];
3816
-
3817
-
3818
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3819
-        $settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3820
-        $settings_template_args['on_off_status'] = $active ? true : false;
3821
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3822
-        $content = EEH_Template::display_template(
3823
-            $template,
3824
-            $settings_template_args,
3825
-            true
3826
-        );
3827
-
3828
-        return $content;
3829
-    }
3830
-
3831
-
3832
-    /**
3833
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3834
-     *
3835
-     * @throws DomainException
3836
-     * @throws EE_Error
3837
-     * @throws InvalidDataTypeException
3838
-     * @throws InvalidInterfaceException
3839
-     * @throws InvalidArgumentException
3840
-     * @throws ReflectionException
3841
-     */
3842
-    public function activate_messenger_toggle()
3843
-    {
3844
-        $success = true;
3845
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3846
-        // let's check that we have required data
3847
-        if (! isset($this->_req_data['messenger'])) {
3848
-            EE_Error::add_error(
3849
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3850
-                __FILE__,
3851
-                __FUNCTION__,
3852
-                __LINE__
3853
-            );
3854
-            $success = false;
3855
-        }
3856
-
3857
-        // do a nonce check here since we're not arriving via a normal route
3858
-        $nonce = isset($this->_req_data['activate_nonce'])
3859
-            ? sanitize_text_field($this->_req_data['activate_nonce'])
3860
-            : '';
3861
-        $nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3862
-
3863
-        $this->_verify_nonce($nonce, $nonce_ref);
3864
-
3865
-
3866
-        if (! isset($this->_req_data['status'])) {
3867
-            EE_Error::add_error(
3868
-                esc_html__(
3869
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3870
-                    'event_espresso'
3871
-                ),
3872
-                __FILE__,
3873
-                __FUNCTION__,
3874
-                __LINE__
3875
-            );
3876
-            $success = false;
3877
-        }
3878
-
3879
-        // do check to verify we have a valid status.
3880
-        $status = $this->_req_data['status'];
3881
-
3882
-        if ($status !== 'off' && $status !== 'on') {
3883
-            EE_Error::add_error(
3884
-                sprintf(
3885
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3886
-                    $this->_req_data['status']
3887
-                ),
3888
-                __FILE__,
3889
-                __FUNCTION__,
3890
-                __LINE__
3891
-            );
3892
-            $success = false;
3893
-        }
3894
-
3895
-        if ($success) {
3896
-            // made it here?  Stop dawdling then!!
3897
-            $success = $status === 'off'
3898
-                ? $this->_deactivate_messenger($this->_req_data['messenger'])
3899
-                : $this->_activate_messenger($this->_req_data['messenger']);
3900
-        }
3901
-
3902
-        $this->_template_args['success'] = $success;
3903
-
3904
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
3905
-        $this->_return_json();
3906
-    }
3907
-
3908
-
3909
-    /**
3910
-     * used by ajax from the messages settings page to activate|deactivate a message type
3911
-     *
3912
-     * @throws DomainException
3913
-     * @throws EE_Error
3914
-     * @throws ReflectionException
3915
-     * @throws InvalidDataTypeException
3916
-     * @throws InvalidInterfaceException
3917
-     * @throws InvalidArgumentException
3918
-     */
3919
-    public function activate_mt_toggle()
3920
-    {
3921
-        $success = true;
3922
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3923
-
3924
-        // let's make sure we have the necessary data
3925
-        if (! isset($this->_req_data['message_type'])) {
3926
-            EE_Error::add_error(
3927
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3928
-                __FILE__,
3929
-                __FUNCTION__,
3930
-                __LINE__
3931
-            );
3932
-            $success = false;
3933
-        }
3934
-
3935
-        if (! isset($this->_req_data['messenger'])) {
3936
-            EE_Error::add_error(
3937
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3938
-                __FILE__,
3939
-                __FUNCTION__,
3940
-                __LINE__
3941
-            );
3942
-            $success = false;
3943
-        }
3944
-
3945
-        if (! isset($this->_req_data['status'])) {
3946
-            EE_Error::add_error(
3947
-                esc_html__(
3948
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3949
-                    'event_espresso'
3950
-                ),
3951
-                __FILE__,
3952
-                __FUNCTION__,
3953
-                __LINE__
3954
-            );
3955
-            $success = false;
3956
-        }
3957
-
3958
-
3959
-        // do check to verify we have a valid status.
3960
-        $status = $this->_req_data['status'];
3961
-
3962
-        if ($status !== 'activate' && $status !== 'deactivate') {
3963
-            EE_Error::add_error(
3964
-                sprintf(
3965
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3966
-                    $this->_req_data['status']
3967
-                ),
3968
-                __FILE__,
3969
-                __FUNCTION__,
3970
-                __LINE__
3971
-            );
3972
-            $success = false;
3973
-        }
3974
-
3975
-
3976
-        // do a nonce check here since we're not arriving via a normal route
3977
-        $nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3978
-        $nonce_ref = $this->_req_data['message_type'] . '_nonce';
3979
-
3980
-        $this->_verify_nonce($nonce, $nonce_ref);
3981
-
3982
-        if ($success) {
3983
-            // made it here? um, what are you waiting for then?
3984
-            $success = $status === 'deactivate'
3985
-                ? $this->_deactivate_message_type_for_messenger(
3986
-                    $this->_req_data['messenger'],
3987
-                    $this->_req_data['message_type']
3988
-                )
3989
-                : $this->_activate_message_type_for_messenger(
3990
-                    $this->_req_data['messenger'],
3991
-                    $this->_req_data['message_type']
3992
-                );
3993
-        }
3994
-
3995
-        $this->_template_args['success'] = $success;
3996
-        $this->_return_json();
3997
-    }
3998
-
3999
-
4000
-    /**
4001
-     * Takes care of processing activating a messenger and preparing the appropriate response.
4002
-     *
4003
-     * @param string $messenger_name The name of the messenger being activated
4004
-     * @return bool
4005
-     * @throws DomainException
4006
-     * @throws EE_Error
4007
-     * @throws InvalidArgumentException
4008
-     * @throws ReflectionException
4009
-     * @throws InvalidDataTypeException
4010
-     * @throws InvalidInterfaceException
4011
-     */
4012
-    protected function _activate_messenger($messenger_name)
4013
-    {
4014
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4015
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4016
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
4017
-            ? $active_messenger->get_default_message_types()
4018
-            : array();
4019
-
4020
-        // ensure is active
4021
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4022
-
4023
-        // set response_data for reload
4024
-        foreach ($message_types_to_activate as $message_type_name) {
4025
-            /** @var EE_message_type $message_type */
4026
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4027
-            if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4028
-                $messenger_name,
4029
-                $message_type_name
4030
-            )
4031
-                && $message_type instanceof EE_message_type
4032
-            ) {
4033
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
4034
-                if ($message_type->get_admin_settings_fields()) {
4035
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
4036
-                }
4037
-            }
4038
-        }
4039
-
4040
-        // add success message for activating messenger
4041
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4042
-    }
4043
-
4044
-
4045
-    /**
4046
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
4047
-     *
4048
-     * @param string $messenger_name The name of the messenger being activated
4049
-     * @return bool
4050
-     * @throws DomainException
4051
-     * @throws EE_Error
4052
-     * @throws InvalidArgumentException
4053
-     * @throws ReflectionException
4054
-     * @throws InvalidDataTypeException
4055
-     * @throws InvalidInterfaceException
4056
-     */
4057
-    protected function _deactivate_messenger($messenger_name)
4058
-    {
4059
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4060
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4061
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
4062
-
4063
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4064
-    }
4065
-
4066
-
4067
-    /**
4068
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4069
-     *
4070
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
4071
-     * @param string $message_type_name The name of the message type being activated for the messenger
4072
-     * @return bool
4073
-     * @throws DomainException
4074
-     * @throws EE_Error
4075
-     * @throws InvalidArgumentException
4076
-     * @throws ReflectionException
4077
-     * @throws InvalidDataTypeException
4078
-     * @throws InvalidInterfaceException
4079
-     */
4080
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4081
-    {
4082
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4083
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4084
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4085
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4086
-
4087
-        // ensure is active
4088
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4089
-
4090
-        // set response for load
4091
-        if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4092
-            $messenger_name,
4093
-            $message_type_name
4094
-        )
4095
-        ) {
4096
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
4097
-            if ($message_type_to_activate->get_admin_settings_fields()) {
4098
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
4099
-            }
4100
-        }
4101
-
4102
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
4103
-            $active_messenger,
4104
-            $message_type_to_activate
4105
-        );
4106
-    }
4107
-
4108
-
4109
-    /**
4110
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4111
-     *
4112
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4113
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
4114
-     * @return bool
4115
-     * @throws DomainException
4116
-     * @throws EE_Error
4117
-     * @throws InvalidArgumentException
4118
-     * @throws ReflectionException
4119
-     * @throws InvalidDataTypeException
4120
-     * @throws InvalidInterfaceException
4121
-     */
4122
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4123
-    {
4124
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4125
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4126
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4127
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4128
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4129
-
4130
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4131
-            $active_messenger,
4132
-            $message_type_to_deactivate
4133
-        );
4134
-    }
4135
-
4136
-
4137
-    /**
4138
-     * This just initializes the defaults for activating messenger and message type responses.
4139
-     */
4140
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
4141
-    {
4142
-        $this->_template_args['data']['active_mts'] = array();
4143
-        $this->_template_args['data']['mt_reload'] = array();
4144
-    }
4145
-
4146
-
4147
-    /**
4148
-     * Setup appropriate response for activating a messenger and/or message types
4149
-     *
4150
-     * @param EE_messenger         $messenger
4151
-     * @param EE_message_type|null $message_type
4152
-     * @return bool
4153
-     * @throws DomainException
4154
-     * @throws EE_Error
4155
-     * @throws InvalidArgumentException
4156
-     * @throws ReflectionException
4157
-     * @throws InvalidDataTypeException
4158
-     * @throws InvalidInterfaceException
4159
-     */
4160
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
4161
-        $messenger,
4162
-        EE_Message_Type $message_type = null
4163
-    ) {
4164
-        // if $messenger isn't a valid messenger object then get out.
4165
-        if (! $messenger instanceof EE_Messenger) {
4166
-            EE_Error::add_error(
4167
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4168
-                __FILE__,
4169
-                __FUNCTION__,
4170
-                __LINE__
4171
-            );
4172
-
4173
-            return false;
4174
-        }
4175
-        // activated
4176
-        if ($this->_template_args['data']['active_mts']) {
4177
-            EE_Error::overwrite_success();
4178
-            // activated a message type with the messenger
4179
-            if ($message_type instanceof EE_message_type) {
4180
-                EE_Error::add_success(
4181
-                    sprintf(
4182
-                        esc_html__(
4183
-                            '%s message type has been successfully activated with the %s messenger',
4184
-                            'event_espresso'
4185
-                        ),
4186
-                        ucwords($message_type->label['singular']),
4187
-                        ucwords($messenger->label['singular'])
4188
-                    )
4189
-                );
4190
-
4191
-                // if message type was invoice then let's make sure we activate the invoice payment method.
4192
-                if ($message_type->name === 'invoice') {
4193
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
4194
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4195
-                    if ($pm instanceof EE_Payment_Method) {
4196
-                        EE_Error::add_attention(
4197
-                            esc_html__(
4198
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4199
-                                'event_espresso'
4200
-                            )
4201
-                        );
4202
-                    }
4203
-                }
4204
-                // just toggles the entire messenger
4205
-            } else {
4206
-                EE_Error::add_success(
4207
-                    sprintf(
4208
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4209
-                        ucwords($messenger->label['singular'])
4210
-                    )
4211
-                );
4212
-            }
4213
-
4214
-            return true;
4215
-
4216
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4217
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4218
-            // in which case we just give a success message for the messenger being successfully activated.
4219
-        } else {
4220
-            if (! $messenger->get_default_message_types()) {
4221
-                // messenger doesn't have any default message types so still a success.
4222
-                EE_Error::add_success(
4223
-                    sprintf(
4224
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4225
-                        ucwords($messenger->label['singular'])
4226
-                    )
4227
-                );
4228
-
4229
-                return true;
4230
-            } else {
4231
-                EE_Error::add_error(
4232
-                    $message_type instanceof EE_message_type
4233
-                        ? sprintf(
4234
-                            esc_html__(
4235
-                                '%s message type was not successfully activated with the %s messenger',
4236
-                                'event_espresso'
4237
-                            ),
4238
-                            ucwords($message_type->label['singular']),
4239
-                            ucwords($messenger->label['singular'])
4240
-                        )
4241
-                        : sprintf(
4242
-                            esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4243
-                            ucwords($messenger->label['singular'])
4244
-                        ),
4245
-                    __FILE__,
4246
-                    __FUNCTION__,
4247
-                    __LINE__
4248
-                );
4249
-
4250
-                return false;
4251
-            }
4252
-        }
4253
-    }
4254
-
4255
-
4256
-    /**
4257
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
4258
-     *
4259
-     * @param EE_messenger         $messenger
4260
-     * @param EE_message_type|null $message_type
4261
-     * @return bool
4262
-     * @throws DomainException
4263
-     * @throws EE_Error
4264
-     * @throws InvalidArgumentException
4265
-     * @throws ReflectionException
4266
-     * @throws InvalidDataTypeException
4267
-     * @throws InvalidInterfaceException
4268
-     */
4269
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4270
-        $messenger,
4271
-        EE_message_type $message_type = null
4272
-    ) {
4273
-        EE_Error::overwrite_success();
4274
-
4275
-        // if $messenger isn't a valid messenger object then get out.
4276
-        if (! $messenger instanceof EE_Messenger) {
4277
-            EE_Error::add_error(
4278
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4279
-                __FILE__,
4280
-                __FUNCTION__,
4281
-                __LINE__
4282
-            );
4283
-
4284
-            return false;
4285
-        }
4286
-
4287
-        if ($message_type instanceof EE_message_type) {
4288
-            $message_type_name = $message_type->name;
4289
-            EE_Error::add_success(
4290
-                sprintf(
4291
-                    esc_html__(
4292
-                        '%s message type has been successfully deactivated for the %s messenger.',
4293
-                        'event_espresso'
4294
-                    ),
4295
-                    ucwords($message_type->label['singular']),
4296
-                    ucwords($messenger->label['singular'])
4297
-                )
4298
-            );
4299
-        } else {
4300
-            $message_type_name = '';
4301
-            EE_Error::add_success(
4302
-                sprintf(
4303
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4304
-                    ucwords($messenger->label['singular'])
4305
-                )
4306
-            );
4307
-        }
4308
-
4309
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4310
-        if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4311
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
4312
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4313
-            if ($count_updated > 0) {
4314
-                $msg = $message_type_name === 'invoice'
4315
-                    ? esc_html__(
4316
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4317
-                        'event_espresso'
4318
-                    )
4319
-                    : esc_html__(
4320
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4321
-                        'event_espresso'
4322
-                    );
4323
-                EE_Error::add_attention($msg);
4324
-            }
4325
-        }
4326
-
4327
-        return true;
4328
-    }
4329
-
4330
-
4331
-    /**
4332
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4333
-     *
4334
-     * @throws DomainException
4335
-     */
4336
-    public function update_mt_form()
4337
-    {
4338
-        if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4339
-            EE_Error::add_error(
4340
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4341
-                __FILE__,
4342
-                __FUNCTION__,
4343
-                __LINE__
4344
-            );
4345
-            $this->_return_json();
4346
-        }
4347
-
4348
-        $message_types = $this->get_installed_message_types();
4349
-
4350
-        $message_type = $message_types[ $this->_req_data['message_type'] ];
4351
-        $messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4352
-
4353
-        $content = $this->_message_type_settings_content(
4354
-            $message_type,
4355
-            $messenger,
4356
-            true
4357
-        );
4358
-        $this->_template_args['success'] = true;
4359
-        $this->_template_args['content'] = $content;
4360
-        $this->_return_json();
4361
-    }
4362
-
4363
-
4364
-    /**
4365
-     * this handles saving the settings for a messenger or message type
4366
-     *
4367
-     */
4368
-    public function save_settings()
4369
-    {
4370
-        if (! isset($this->_req_data['type'])) {
4371
-            EE_Error::add_error(
4372
-                esc_html__(
4373
-                    'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4374
-                    'event_espresso'
4375
-                ),
4376
-                __FILE__,
4377
-                __FUNCTION__,
4378
-                __LINE__
4379
-            );
4380
-            $this->_template_args['error'] = true;
4381
-            $this->_return_json();
4382
-        }
4383
-
4384
-
4385
-        if ($this->_req_data['type'] === 'messenger') {
4386
-            // this should be an array.
4387
-            $settings = $this->_req_data['messenger_settings'];
4388
-            $messenger = $settings['messenger'];
4389
-            // let's setup the settings data
4390
-            foreach ($settings as $key => $value) {
4391
-                switch ($key) {
4392
-                    case 'messenger':
4393
-                        unset($settings['messenger']);
4394
-                        break;
4395
-                    case 'message_types':
4396
-                        unset($settings['message_types']);
4397
-                        break;
4398
-                    default:
4399
-                        $settings[ $key ] = $value;
4400
-                        break;
4401
-                }
4402
-            }
4403
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4404
-        } elseif ($this->_req_data['type'] === 'message_type') {
4405
-            $settings = $this->_req_data['message_type_settings'];
4406
-            $messenger = $settings['messenger'];
4407
-            $message_type = $settings['message_type'];
4408
-
4409
-            foreach ($settings as $key => $value) {
4410
-                switch ($key) {
4411
-                    case 'messenger':
4412
-                        unset($settings['messenger']);
4413
-                        break;
4414
-                    case 'message_type':
4415
-                        unset($settings['message_type']);
4416
-                        break;
4417
-                    default:
4418
-                        $settings[ $key ] = $value;
4419
-                        break;
4420
-                }
4421
-            }
4422
-
4423
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4424
-        }
4425
-
4426
-        // okay we should have the data all setup.  Now we just update!
4427
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4428
-
4429
-        if ($success) {
4430
-            EE_Error::add_success(__('Settings updated', 'event_espresso'));
4431
-        } else {
4432
-            EE_Error::add_error(
4433
-                esc_html__(
4434
-                    'Settings did not get updated',
4435
-                    'event_espresso'
4436
-                ),
4437
-                __FILE__,
4438
-                __FUNCTION__,
4439
-                __LINE__
4440
-            );
4441
-        }
4442
-
4443
-        $this->_template_args['success'] = $success;
4444
-        $this->_return_json();
4445
-    }
4446
-
4447
-
4448
-
4449
-
4450
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4451
-
4452
-
4453
-    /**
4454
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4455
-     * However, this does not send immediately, it just queues for sending.
4456
-     *
4457
-     * @since 4.9.0
4458
-     * @throws EE_Error
4459
-     * @throws InvalidDataTypeException
4460
-     * @throws InvalidInterfaceException
4461
-     * @throws InvalidArgumentException
4462
-     * @throws ReflectionException
4463
-     */
4464
-    protected function _generate_now()
4465
-    {
4466
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4467
-        $this->_redirect_after_action(false, '', '', array(), true);
4468
-    }
4469
-
4470
-
4471
-    /**
4472
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4473
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4474
-     *
4475
-     * @since 4.9.0
4476
-     * @throws EE_Error
4477
-     * @throws InvalidDataTypeException
4478
-     * @throws InvalidInterfaceException
4479
-     * @throws InvalidArgumentException
4480
-     * @throws ReflectionException
4481
-     */
4482
-    protected function _generate_and_send_now()
4483
-    {
4484
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4485
-        $this->_redirect_after_action(false, '', '', array(), true);
4486
-    }
4487
-
4488
-
4489
-    /**
4490
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4491
-     *
4492
-     * @since 4.9.0
4493
-     * @throws EE_Error
4494
-     * @throws InvalidDataTypeException
4495
-     * @throws InvalidInterfaceException
4496
-     * @throws InvalidArgumentException
4497
-     * @throws ReflectionException
4498
-     */
4499
-    protected function _queue_for_resending()
4500
-    {
4501
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4502
-        $this->_redirect_after_action(false, '', '', array(), true);
4503
-    }
4504
-
4505
-
4506
-    /**
4507
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4508
-     *
4509
-     * @since 4.9.0
4510
-     * @throws EE_Error
4511
-     * @throws InvalidDataTypeException
4512
-     * @throws InvalidInterfaceException
4513
-     * @throws InvalidArgumentException
4514
-     * @throws ReflectionException
4515
-     */
4516
-    protected function _send_now()
4517
-    {
4518
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4519
-        $this->_redirect_after_action(false, '', '', array(), true);
4520
-    }
4521
-
4522
-
4523
-    /**
4524
-     * Deletes EE_messages for IDs in the request.
4525
-     *
4526
-     * @since 4.9.0
4527
-     * @throws EE_Error
4528
-     * @throws InvalidDataTypeException
4529
-     * @throws InvalidInterfaceException
4530
-     * @throws InvalidArgumentException
4531
-     */
4532
-    protected function _delete_ee_messages()
4533
-    {
4534
-        $msg_ids = $this->_get_msg_ids_from_request();
4535
-        $deleted_count = 0;
4536
-        foreach ($msg_ids as $msg_id) {
4537
-            if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4538
-                $deleted_count++;
4539
-            }
4540
-        }
4541
-        if ($deleted_count) {
4542
-            EE_Error::add_success(
4543
-                esc_html(
4544
-                    _n(
4545
-                        'Message successfully deleted',
4546
-                        'Messages successfully deleted',
4547
-                        $deleted_count,
4548
-                        'event_espresso'
4549
-                    )
4550
-                )
4551
-            );
4552
-            $this->_redirect_after_action(
4553
-                false,
4554
-                '',
4555
-                '',
4556
-                array(),
4557
-                true
4558
-            );
4559
-        } else {
4560
-            EE_Error::add_error(
4561
-                _n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4562
-                __FILE__,
4563
-                __FUNCTION__,
4564
-                __LINE__
4565
-            );
4566
-            $this->_redirect_after_action(false, '', '', array(), true);
4567
-        }
4568
-    }
4569
-
4570
-
4571
-    /**
4572
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4573
-     *
4574
-     * @since 4.9.0
4575
-     * @return array
4576
-     */
4577
-    protected function _get_msg_ids_from_request()
4578
-    {
4579
-        if (! isset($this->_req_data['MSG_ID'])) {
4580
-            return array();
4581
-        }
4582
-
4583
-        return is_array($this->_req_data['MSG_ID'])
4584
-            ? array_keys($this->_req_data['MSG_ID'])
4585
-            : array($this->_req_data['MSG_ID']);
4586
-    }
2666
+		$output = ob_get_contents();
2667
+		ob_clean();
2668
+		$this->_context_switcher = $output;
2669
+	}
2670
+
2671
+
2672
+	/**
2673
+	 * utility for sanitizing new values coming in.
2674
+	 * Note: this is only used when updating a context.
2675
+	 *
2676
+	 * @access protected
2677
+	 *
2678
+	 * @param int $index This helps us know which template field to select from the request array.
2679
+	 *
2680
+	 * @return array
2681
+	 */
2682
+	protected function _set_message_template_column_values($index)
2683
+	{
2684
+		if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2685
+			foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2686
+				$this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2687
+			}
2688
+		}
2689
+
2690
+
2691
+		$set_column_values = array(
2692
+			'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2693
+			'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2694
+			'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2695
+			'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2696
+			'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2697
+			'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2698
+			'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2699
+			'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2700
+			'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2701
+				? absint($this->_req_data['MTP_is_global'])
2702
+				: 0,
2703
+			'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2704
+				? absint($this->_req_data['MTP_is_override'])
2705
+				: 0,
2706
+			'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2707
+			'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2708
+		);
2709
+
2710
+
2711
+		return $set_column_values;
2712
+	}
2713
+
2714
+
2715
+	protected function _insert_or_update_message_template($new = false)
2716
+	{
2717
+
2718
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2719
+		$success = 0;
2720
+		$override = false;
2721
+
2722
+		// setup notices description
2723
+		$messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2724
+
2725
+		// need the message type and messenger objects to be able to use the labels for the notices
2726
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2727
+		$messenger_label = $messenger_object instanceof EE_messenger
2728
+			? ucwords($messenger_object->label['singular'])
2729
+			: '';
2730
+
2731
+		$message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2732
+			? $this->_req_data['MTP_message_type']
2733
+			: '';
2734
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2735
+
2736
+		$message_type_label = $message_type_object instanceof EE_message_type
2737
+			? ucwords($message_type_object->label['singular'])
2738
+			: '';
2739
+
2740
+		$context_slug = ! empty($this->_req_data['MTP_context'])
2741
+			? $this->_req_data['MTP_context']
2742
+			: '';
2743
+		$context = ucwords(str_replace('_', ' ', $context_slug));
2744
+
2745
+		$item_desc = $messenger_label && $message_type_label
2746
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2747
+			: '';
2748
+		$item_desc .= 'Message Template';
2749
+		$query_args = array();
2750
+		$edit_array = array();
2751
+		$action_desc = '';
2752
+
2753
+		// if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2754
+		// user to edit.
2755
+		if ($new) {
2756
+			$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2757
+			if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2758
+				if (empty($edit_array)) {
2759
+					$success = 0;
2760
+				} else {
2761
+					$success = 1;
2762
+					$edit_array = $edit_array[0];
2763
+					$query_args = array(
2764
+						'id'      => $edit_array['GRP_ID'],
2765
+						'context' => $edit_array['MTP_context'],
2766
+						'action'  => 'edit_message_template',
2767
+					);
2768
+				}
2769
+			}
2770
+			$action_desc = 'created';
2771
+		} else {
2772
+			$MTPG = EEM_Message_Template_Group::instance();
2773
+			$MTP = EEM_Message_Template::instance();
2774
+
2775
+
2776
+			// run update for each template field in displayed context
2777
+			if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2778
+				EE_Error::add_error(
2779
+					esc_html__(
2780
+						'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2781
+						'event_espresso'
2782
+					),
2783
+					__FILE__,
2784
+					__FUNCTION__,
2785
+					__LINE__
2786
+				);
2787
+				$success = 0;
2788
+			} else {
2789
+				// first validate all fields!
2790
+				// this filter allows client code to add its own validation to the template fields as well.
2791
+				// returning an empty array means everything passed validation.
2792
+				// errors in validation should be represented in an array with the following shape:
2793
+				// array(
2794
+				//   'fieldname' => array(
2795
+				//          'msg' => 'error message'
2796
+				//          'value' => 'value for field producing error'
2797
+				// )
2798
+				$custom_validation = (array) apply_filters(
2799
+					'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2800
+					array(),
2801
+					$this->_req_data['MTP_template_fields'],
2802
+					$context_slug,
2803
+					$messenger_slug,
2804
+					$message_type_slug
2805
+				);
2806
+
2807
+				$system_validation = $MTPG->validate(
2808
+					$this->_req_data['MTP_template_fields'],
2809
+					$context_slug,
2810
+					$messenger_slug,
2811
+					$message_type_slug
2812
+				);
2813
+
2814
+				$system_validation = ! is_array($system_validation) && $system_validation ? array()
2815
+					: $system_validation;
2816
+				$validates = array_merge($custom_validation, $system_validation);
2817
+
2818
+				// if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2819
+				// appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2820
+				//  WE need to make sure there is no actual error messages in validates.
2821
+				if (is_array($validates) && ! empty($validates)) {
2822
+					// add the transient so when the form loads we know which fields to highlight
2823
+					$this->_add_transient('edit_message_template', $validates);
2824
+
2825
+					$success = 0;
2826
+
2827
+					// setup notices
2828
+					foreach ($validates as $field => $error) {
2829
+						if (isset($error['msg'])) {
2830
+							EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2831
+						}
2832
+					}
2833
+				} else {
2834
+					$set_column_values = array();
2835
+					foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2836
+						$set_column_values = $this->_set_message_template_column_values($template_field);
2837
+
2838
+						$where_cols_n_values = array(
2839
+							'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2840
+						);
2841
+						// if they aren't allowed to use all JS, restrict them to just posty-y tags
2842
+						if (! current_user_can('unfiltered_html')) {
2843
+							if (is_array($set_column_values['MTP_content'])) {
2844
+								foreach ($set_column_values['MTP_content'] as $key => $value) {
2845
+									// remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2846
+									// only removes slashes from double-quotes, so attributes using single quotes always
2847
+									// appear invalid.) But currently the models expect slashed data, so after wp_kses
2848
+									// runs we need to re-slash the data. Sheesh. See
2849
+									// https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2850
+									$set_column_values['MTP_content'][ $key ] = addslashes(
2851
+										wp_kses(
2852
+											stripslashes($value),
2853
+											wp_kses_allowed_html('post')
2854
+										)
2855
+									);
2856
+								}
2857
+							} else {
2858
+								$set_column_values['MTP_content'] = wp_kses(
2859
+									$set_column_values['MTP_content'],
2860
+									wp_kses_allowed_html('post')
2861
+								);
2862
+							}
2863
+						}
2864
+						$message_template_fields = array(
2865
+							'GRP_ID'             => $set_column_values['GRP_ID'],
2866
+							'MTP_template_field' => $set_column_values['MTP_template_field'],
2867
+							'MTP_context'        => $set_column_values['MTP_context'],
2868
+							'MTP_content'        => $set_column_values['MTP_content'],
2869
+						);
2870
+						if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2871
+							if ($updated === false) {
2872
+								EE_Error::add_error(
2873
+									sprintf(
2874
+										esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2875
+										$template_field
2876
+									),
2877
+									__FILE__,
2878
+									__FUNCTION__,
2879
+									__LINE__
2880
+								);
2881
+							} else {
2882
+								$success = 1;
2883
+							}
2884
+						} else {
2885
+							// only do this logic if we don't have a MTP_ID for this field
2886
+							if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2887
+								// this has already been through the template field validator and sanitized, so it will be
2888
+								// safe to insert this field.  Why insert?  This typically happens when we introduce a new
2889
+								// message template field in a messenger/message type and existing users don't have the
2890
+								// default setup for it.
2891
+								// @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2892
+								$updated = $MTP->insert($message_template_fields);
2893
+								if (! $updated || is_wp_error($updated)) {
2894
+									EE_Error::add_error(
2895
+										sprintf(
2896
+											esc_html__('%s field could not be updated.', 'event_espresso'),
2897
+											$template_field
2898
+										),
2899
+										__FILE__,
2900
+										__FUNCTION__,
2901
+										__LINE__
2902
+									);
2903
+									$success = 0;
2904
+								} else {
2905
+									$success = 1;
2906
+								}
2907
+							}
2908
+						}
2909
+						$action_desc = 'updated';
2910
+					}
2911
+
2912
+					// we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2913
+					$mtpg_fields = array(
2914
+						'MTP_user_id'      => $set_column_values['MTP_user_id'],
2915
+						'MTP_messenger'    => $set_column_values['MTP_messenger'],
2916
+						'MTP_message_type' => $set_column_values['MTP_message_type'],
2917
+						'MTP_is_global'    => $set_column_values['MTP_is_global'],
2918
+						'MTP_is_override'  => $set_column_values['MTP_is_override'],
2919
+						'MTP_deleted'      => $set_column_values['MTP_deleted'],
2920
+						'MTP_is_active'    => $set_column_values['MTP_is_active'],
2921
+						'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2922
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2923
+							: '',
2924
+						'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2925
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2926
+							: '',
2927
+					);
2928
+
2929
+					$mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2930
+					$updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2931
+
2932
+					if ($updated === false) {
2933
+						EE_Error::add_error(
2934
+							sprintf(
2935
+								esc_html__(
2936
+									'The Message Template Group (%d) was NOT updated for some reason',
2937
+									'event_espresso'
2938
+								),
2939
+								$set_column_values['GRP_ID']
2940
+							),
2941
+							__FILE__,
2942
+							__FUNCTION__,
2943
+							__LINE__
2944
+						);
2945
+					} else {
2946
+						// k now we need to ensure the template_pack and template_variation fields are set.
2947
+						$template_pack = ! empty($this->_req_data['MTP_template_pack'])
2948
+							? $this->_req_data['MTP_template_pack']
2949
+							: 'default';
2950
+
2951
+						$template_variation = ! empty($this->_req_data['MTP_template_variation'])
2952
+							? $this->_req_data['MTP_template_variation']
2953
+							: 'default';
2954
+
2955
+						$mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2956
+						if ($mtpg_obj instanceof EE_Message_Template_Group) {
2957
+							$mtpg_obj->set_template_pack_name($template_pack);
2958
+							$mtpg_obj->set_template_pack_variation($template_variation);
2959
+						}
2960
+						$success = 1;
2961
+					}
2962
+				}
2963
+			}
2964
+		}
2965
+
2966
+		// we return things differently if doing ajax
2967
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2968
+			$this->_template_args['success'] = $success;
2969
+			$this->_template_args['error'] = ! $success ? true : false;
2970
+			$this->_template_args['content'] = '';
2971
+			$this->_template_args['data'] = array(
2972
+				'grpID'        => $edit_array['GRP_ID'],
2973
+				'templateName' => $edit_array['template_name'],
2974
+			);
2975
+			if ($success) {
2976
+				EE_Error::overwrite_success();
2977
+				EE_Error::add_success(
2978
+					esc_html__(
2979
+						'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2980
+						'event_espresso'
2981
+					)
2982
+				);
2983
+			}
2984
+
2985
+			$this->_return_json();
2986
+		}
2987
+
2988
+
2989
+		// was a test send triggered?
2990
+		if (isset($this->_req_data['test_button'])) {
2991
+			EE_Error::overwrite_success();
2992
+			$this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
2993
+			$override = true;
2994
+		}
2995
+
2996
+		if (empty($query_args)) {
2997
+			$query_args = array(
2998
+				'id'      => $this->_req_data['GRP_ID'],
2999
+				'context' => $context_slug,
3000
+				'action'  => 'edit_message_template',
3001
+			);
3002
+		}
3003
+
3004
+		$this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3005
+	}
3006
+
3007
+
3008
+	/**
3009
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
3010
+	 *
3011
+	 * @param  string $context      what context being tested
3012
+	 * @param  string $messenger    messenger being tested
3013
+	 * @param  string $message_type message type being tested
3014
+	 * @throws EE_Error
3015
+	 * @throws InvalidArgumentException
3016
+	 * @throws InvalidDataTypeException
3017
+	 * @throws InvalidInterfaceException
3018
+	 */
3019
+	protected function _do_test_send($context, $messenger, $message_type)
3020
+	{
3021
+		// set things up for preview
3022
+		$this->_req_data['messenger'] = $messenger;
3023
+		$this->_req_data['message_type'] = $message_type;
3024
+		$this->_req_data['context'] = $context;
3025
+		$this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3026
+		$active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3027
+
3028
+		// let's save any existing fields that might be required by the messenger
3029
+		if (isset($this->_req_data['test_settings_fld'])
3030
+			&& $active_messenger instanceof EE_messenger
3031
+			&& apply_filters(
3032
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3033
+				true,
3034
+				$this->_req_data['test_settings_fld'],
3035
+				$active_messenger
3036
+			)
3037
+		) {
3038
+			$active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3039
+		}
3040
+
3041
+		/**
3042
+		 * Use filter to add additional controls on whether message can send or not
3043
+		 */
3044
+		if (apply_filters(
3045
+			'FHEE__Messages_Admin_Page__do_test_send__can_send',
3046
+			true,
3047
+			$context,
3048
+			$this->_req_data,
3049
+			$messenger,
3050
+			$message_type
3051
+		)) {
3052
+			if (EEM_Event::instance()->count() > 0) {
3053
+				$success = $this->_preview_message(true);
3054
+				if ($success) {
3055
+					EE_Error::add_success(__('Test message sent', 'event_espresso'));
3056
+				} else {
3057
+					EE_Error::add_error(
3058
+						esc_html__('The test message was not sent', 'event_espresso'),
3059
+						__FILE__,
3060
+						__FUNCTION__,
3061
+						__LINE__
3062
+					);
3063
+				}
3064
+			} else {
3065
+				$this->noEventsErrorMessage(true);
3066
+			}
3067
+		}
3068
+	}
3069
+
3070
+
3071
+	/**
3072
+	 * _generate_new_templates
3073
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3074
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3075
+	 * for the event.
3076
+	 *
3077
+	 *
3078
+	 * @param  string $messenger     the messenger we are generating templates for
3079
+	 * @param array   $message_types array of message types that the templates are generated for.
3080
+	 * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3081
+	 *                               indicate the message_template_group being used as the base.
3082
+	 *
3083
+	 * @param bool    $global
3084
+	 *
3085
+	 * @return array|bool array of data required for the redirect to the correct edit page or bool if
3086
+	 *                               encountering problems.
3087
+	 * @throws EE_Error
3088
+	 */
3089
+	protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3090
+	{
3091
+
3092
+		// if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3093
+		// just don't generate any templates.
3094
+		if (empty($message_types)) {
3095
+			return true;
3096
+		}
3097
+
3098
+		return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3099
+	}
3100
+
3101
+
3102
+	/**
3103
+	 * [_trash_or_restore_message_template]
3104
+	 *
3105
+	 * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3106
+	 * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3107
+	 *                        an individual context (FALSE).
3108
+	 * @return void
3109
+	 * @throws EE_Error
3110
+	 * @throws InvalidArgumentException
3111
+	 * @throws InvalidDataTypeException
3112
+	 * @throws InvalidInterfaceException
3113
+	 */
3114
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
3115
+	{
3116
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3117
+		$MTP = EEM_Message_Template_Group::instance();
3118
+
3119
+		$success = 1;
3120
+
3121
+		// incoming GRP_IDs
3122
+		if ($all) {
3123
+			// Checkboxes
3124
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3125
+				// if array has more than one element then success message should be plural.
3126
+				// todo: what about nonce?
3127
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3128
+
3129
+				// cycle through checkboxes
3130
+				while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3131
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3132
+					if (! $trashed_or_restored) {
3133
+						$success = 0;
3134
+					}
3135
+				}
3136
+			} else {
3137
+				// grab single GRP_ID and handle
3138
+				$GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3139
+				if (! empty($GRP_ID)) {
3140
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3141
+					if (! $trashed_or_restored) {
3142
+						$success = 0;
3143
+					}
3144
+				} else {
3145
+					$success = 0;
3146
+				}
3147
+			}
3148
+		}
3149
+
3150
+		$action_desc = $trash
3151
+			? esc_html__('moved to the trash', 'event_espresso')
3152
+			: esc_html__('restored', 'event_espresso');
3153
+
3154
+		$action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3155
+
3156
+		$item_desc = $all ? _n(
3157
+			'Message Template Group',
3158
+			'Message Template Groups',
3159
+			$success,
3160
+			'event_espresso'
3161
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3162
+
3163
+		$item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3164
+			'template',
3165
+			'templates',
3166
+			$success,
3167
+			'event_espresso'
3168
+		) : $item_desc;
3169
+
3170
+		$this->_redirect_after_action($success, $item_desc, $action_desc, array());
3171
+	}
3172
+
3173
+
3174
+	/**
3175
+	 * [_delete_message_template]
3176
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3177
+	 *
3178
+	 * @return void
3179
+	 * @throws EE_Error
3180
+	 * @throws InvalidArgumentException
3181
+	 * @throws InvalidDataTypeException
3182
+	 * @throws InvalidInterfaceException
3183
+	 */
3184
+	protected function _delete_message_template()
3185
+	{
3186
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3187
+
3188
+		// checkboxes
3189
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3190
+			// if array has more than one element then success message should be plural
3191
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3192
+
3193
+			// cycle through bulk action checkboxes
3194
+			while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3195
+				$success = $this->_delete_mtp_permanently($GRP_ID);
3196
+			}
3197
+		} else {
3198
+			// grab single grp_id and delete
3199
+			$GRP_ID = absint($this->_req_data['id']);
3200
+			$success = $this->_delete_mtp_permanently($GRP_ID);
3201
+		}
3202
+
3203
+		$this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3204
+	}
3205
+
3206
+
3207
+	/**
3208
+	 * helper for permanently deleting a mtP group and all related message_templates
3209
+	 *
3210
+	 * @param  int  $GRP_ID        The group being deleted
3211
+	 * @param  bool $include_group whether to delete the Message Template Group as well.
3212
+	 * @return bool boolean to indicate the success of the deletes or not.
3213
+	 * @throws EE_Error
3214
+	 * @throws InvalidArgumentException
3215
+	 * @throws InvalidDataTypeException
3216
+	 * @throws InvalidInterfaceException
3217
+	 */
3218
+	private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3219
+	{
3220
+		$success = 1;
3221
+		$MTPG = EEM_Message_Template_Group::instance();
3222
+		// first let's GET this group
3223
+		$MTG = $MTPG->get_one_by_ID($GRP_ID);
3224
+		// then delete permanently all the related Message Templates
3225
+		$deleted = $MTG->delete_related_permanently('Message_Template');
3226
+
3227
+		if ($deleted === 0) {
3228
+			$success = 0;
3229
+		}
3230
+
3231
+		// now delete permanently this particular group
3232
+
3233
+		if ($include_group && ! $MTG->delete_permanently()) {
3234
+			$success = 0;
3235
+		}
3236
+
3237
+		return $success;
3238
+	}
3239
+
3240
+
3241
+	/**
3242
+	 *    _learn_more_about_message_templates_link
3243
+	 *
3244
+	 * @access protected
3245
+	 * @return string
3246
+	 */
3247
+	protected function _learn_more_about_message_templates_link()
3248
+	{
3249
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3250
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
3251
+			   . '</a>';
3252
+	}
3253
+
3254
+
3255
+	/**
3256
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3257
+	 * ajax and other routes.
3258
+	 *
3259
+	 * @return void
3260
+	 * @throws DomainException
3261
+	 */
3262
+	protected function _settings()
3263
+	{
3264
+
3265
+
3266
+		$this->_set_m_mt_settings();
3267
+
3268
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3269
+			? $this->_req_data['selected_messenger']
3270
+			: 'email';
3271
+
3272
+		// let's setup the messenger tabs
3273
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3274
+			$this->_m_mt_settings['messenger_tabs'],
3275
+			'messenger_links',
3276
+			'|',
3277
+			$selected_messenger
3278
+		);
3279
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3280
+		$this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3281
+
3282
+		$this->display_admin_page_with_sidebar();
3283
+	}
3284
+
3285
+
3286
+	/**
3287
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3288
+	 *
3289
+	 * @access protected
3290
+	 * @return void
3291
+	 * @throws DomainException
3292
+	 */
3293
+	protected function _set_m_mt_settings()
3294
+	{
3295
+		// first if this is already set then lets get out no need to regenerate data.
3296
+		if (! empty($this->_m_mt_settings)) {
3297
+			return;
3298
+		}
3299
+
3300
+		// get all installed messengers and message_types
3301
+		/** @type EE_messenger[] $messengers */
3302
+		$messengers = $this->_message_resource_manager->installed_messengers();
3303
+		/** @type EE_message_type[] $message_types */
3304
+		$message_types = $this->_message_resource_manager->installed_message_types();
3305
+
3306
+
3307
+		// assemble the array for the _tab_text_links helper
3308
+
3309
+		foreach ($messengers as $messenger) {
3310
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3311
+				'label' => ucwords($messenger->label['singular']),
3312
+				'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3313
+					? 'messenger-active'
3314
+					: '',
3315
+				'href'  => $messenger->name,
3316
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3317
+				'slug'  => $messenger->name,
3318
+				'obj'   => $messenger,
3319
+			);
3320
+
3321
+
3322
+			$message_types_for_messenger = $messenger->get_valid_message_types();
3323
+
3324
+			foreach ($message_types as $message_type) {
3325
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3326
+				// it shouldn't show in either the inactive OR active metabox.
3327
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3328
+					continue;
3329
+				}
3330
+
3331
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3332
+					$messenger->name,
3333
+					$message_type->name
3334
+				)
3335
+					? 'active'
3336
+					: 'inactive';
3337
+
3338
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3339
+					'label'    => ucwords($message_type->label['singular']),
3340
+					'class'    => 'message-type-' . $a_or_i,
3341
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3342
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3343
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3344
+					'title'    => $a_or_i === 'active'
3345
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3346
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3347
+					'content'  => $a_or_i === 'active'
3348
+						? $this->_message_type_settings_content($message_type, $messenger, true)
3349
+						: $this->_message_type_settings_content($message_type, $messenger),
3350
+					'slug'     => $message_type->name,
3351
+					'active'   => $a_or_i === 'active',
3352
+					'obj'      => $message_type,
3353
+				);
3354
+			}
3355
+		}
3356
+	}
3357
+
3358
+
3359
+	/**
3360
+	 * This just prepares the content for the message type settings
3361
+	 *
3362
+	 * @param  EE_message_type $message_type The message type object
3363
+	 * @param  EE_messenger    $messenger    The messenger object
3364
+	 * @param  boolean         $active       Whether the message type is active or not
3365
+	 * @return string html output for the content
3366
+	 * @throws DomainException
3367
+	 */
3368
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
3369
+	{
3370
+		// get message type fields
3371
+		$fields = $message_type->get_admin_settings_fields();
3372
+		$settings_template_args['template_form_fields'] = '';
3373
+
3374
+		if (! empty($fields) && $active) {
3375
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3376
+			foreach ($fields as $fldname => $fldprops) {
3377
+				$field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3378
+				$template_form_field[ $field_id ] = array(
3379
+					'name'       => 'message_type_settings[' . $fldname . ']',
3380
+					'label'      => $fldprops['label'],
3381
+					'input'      => $fldprops['field_type'],
3382
+					'type'       => $fldprops['value_type'],
3383
+					'required'   => $fldprops['required'],
3384
+					'validation' => $fldprops['validation'],
3385
+					'value'      => isset($existing_settings[ $fldname ])
3386
+						? $existing_settings[ $fldname ]
3387
+						: $fldprops['default'],
3388
+					'options'    => isset($fldprops['options'])
3389
+						? $fldprops['options']
3390
+						: array(),
3391
+					'default'    => isset($existing_settings[ $fldname ])
3392
+						? $existing_settings[ $fldname ]
3393
+						: $fldprops['default'],
3394
+					'css_class'  => 'no-drag',
3395
+					'format'     => $fldprops['format'],
3396
+				);
3397
+			}
3398
+
3399
+
3400
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3401
+				? $this->_generate_admin_form_fields(
3402
+					$template_form_field,
3403
+					'string',
3404
+					'ee_mt_activate_form'
3405
+				)
3406
+				: '';
3407
+		}
3408
+
3409
+		$settings_template_args['description'] = $message_type->description;
3410
+		// we also need some hidden fields
3411
+		$settings_template_args['hidden_fields'] = array(
3412
+			'message_type_settings[messenger]'    => array(
3413
+				'type'  => 'hidden',
3414
+				'value' => $messenger->name,
3415
+			),
3416
+			'message_type_settings[message_type]' => array(
3417
+				'type'  => 'hidden',
3418
+				'value' => $message_type->name,
3419
+			),
3420
+			'type'                                => array(
3421
+				'type'  => 'hidden',
3422
+				'value' => 'message_type',
3423
+			),
3424
+		);
3425
+
3426
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3427
+			$settings_template_args['hidden_fields'],
3428
+			'array'
3429
+		);
3430
+		$settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3431
+			? ' hidden'
3432
+			: '';
3433
+
3434
+
3435
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3436
+		$content = EEH_Template::display_template($template, $settings_template_args, true);
3437
+
3438
+		return $content;
3439
+	}
3440
+
3441
+
3442
+	/**
3443
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3444
+	 *
3445
+	 * @access protected
3446
+	 * @return void
3447
+	 * @throws DomainException
3448
+	 */
3449
+	protected function _messages_settings_metaboxes()
3450
+	{
3451
+		$this->_set_m_mt_settings();
3452
+		$m_boxes = $mt_boxes = array();
3453
+		$m_template_args = $mt_template_args = array();
3454
+
3455
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3456
+			? $this->_req_data['selected_messenger']
3457
+			: 'email';
3458
+
3459
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3460
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3461
+				$hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3462
+				$hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3463
+				// messenger meta boxes
3464
+				$active = $selected_messenger === $messenger;
3465
+				$active_mt_tabs = isset(
3466
+					$this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3467
+				)
3468
+					? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3469
+					: '';
3470
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3471
+					esc_html__('%s Settings', 'event_espresso'),
3472
+					$tab_array['label']
3473
+				);
3474
+				$m_template_args[ $messenger . '_a_box' ] = array(
3475
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3476
+					'inactive_message_types' => isset(
3477
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3478
+					)
3479
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3480
+						: '',
3481
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3482
+					'hidden'                 => $active ? '' : ' hidden',
3483
+					'hide_on_message'        => $hide_on_message,
3484
+					'messenger'              => $messenger,
3485
+					'active'                 => $active,
3486
+				);
3487
+				// message type meta boxes
3488
+				// (which is really just the inactive container for each messenger
3489
+				// showing inactive message types for that messenger)
3490
+				$mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3491
+				$mt_template_args[ $messenger . '_i_box' ] = array(
3492
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3493
+					'inactive_message_types' => isset(
3494
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3495
+					)
3496
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3497
+						: '',
3498
+					'hidden'                 => $active ? '' : ' hidden',
3499
+					'hide_on_message'        => $hide_on_message,
3500
+					'hide_off_message'       => $hide_off_message,
3501
+					'messenger'              => $messenger,
3502
+					'active'                 => $active,
3503
+				);
3504
+			}
3505
+		}
3506
+
3507
+
3508
+		// register messenger metaboxes
3509
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3510
+		foreach ($m_boxes as $box => $label) {
3511
+			$callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3512
+			$msgr = str_replace('_a_box', '', $box);
3513
+			add_meta_box(
3514
+				'espresso_' . $msgr . '_settings',
3515
+				$label,
3516
+				function ($post, $metabox) {
3517
+					echo EEH_Template::display_template(
3518
+						$metabox["args"]["template_path"],
3519
+						$metabox["args"]["template_args"],
3520
+						true
3521
+					);
3522
+				},
3523
+				$this->_current_screen->id,
3524
+				'normal',
3525
+				'high',
3526
+				$callback_args
3527
+			);
3528
+		}
3529
+
3530
+		// register message type metaboxes
3531
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3532
+		foreach ($mt_boxes as $box => $label) {
3533
+			$callback_args = array(
3534
+				'template_path' => $mt_template_path,
3535
+				'template_args' => $mt_template_args[ $box ],
3536
+			);
3537
+			$mt = str_replace('_i_box', '', $box);
3538
+			add_meta_box(
3539
+				'espresso_' . $mt . '_inactive_mts',
3540
+				$label,
3541
+				function ($post, $metabox) {
3542
+					echo EEH_Template::display_template(
3543
+						$metabox["args"]["template_path"],
3544
+						$metabox["args"]["template_args"],
3545
+						true
3546
+					);
3547
+				},
3548
+				$this->_current_screen->id,
3549
+				'side',
3550
+				'high',
3551
+				$callback_args
3552
+			);
3553
+		}
3554
+
3555
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3556
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3557
+		if (is_main_site()) {
3558
+			add_meta_box(
3559
+				'espresso_global_message_settings',
3560
+				esc_html__('Global Message Settings', 'event_espresso'),
3561
+				array($this, 'global_messages_settings_metabox_content'),
3562
+				$this->_current_screen->id,
3563
+				'normal',
3564
+				'low',
3565
+				array()
3566
+			);
3567
+		}
3568
+	}
3569
+
3570
+
3571
+	/**
3572
+	 *  This generates the content for the global messages settings metabox.
3573
+	 *
3574
+	 * @return string
3575
+	 * @throws EE_Error
3576
+	 * @throws InvalidArgumentException
3577
+	 * @throws ReflectionException
3578
+	 * @throws InvalidDataTypeException
3579
+	 * @throws InvalidInterfaceException
3580
+	 */
3581
+	public function global_messages_settings_metabox_content()
3582
+	{
3583
+		$form = $this->_generate_global_settings_form();
3584
+		echo $form->form_open(
3585
+			$this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3586
+			'POST'
3587
+		)
3588
+			 . $form->get_html()
3589
+			 . $form->form_close();
3590
+	}
3591
+
3592
+
3593
+	/**
3594
+	 * This generates and returns the form object for the global messages settings.
3595
+	 *
3596
+	 * @return EE_Form_Section_Proper
3597
+	 * @throws EE_Error
3598
+	 * @throws InvalidArgumentException
3599
+	 * @throws ReflectionException
3600
+	 * @throws InvalidDataTypeException
3601
+	 * @throws InvalidInterfaceException
3602
+	 */
3603
+	protected function _generate_global_settings_form()
3604
+	{
3605
+		EE_Registry::instance()->load_helper('HTML');
3606
+		/** @var EE_Network_Core_Config $network_config */
3607
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3608
+
3609
+		return new EE_Form_Section_Proper(
3610
+			array(
3611
+				'name'            => 'global_messages_settings',
3612
+				'html_id'         => 'global_messages_settings',
3613
+				'html_class'      => 'form-table',
3614
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3615
+				'subsections'     => apply_filters(
3616
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3617
+					array(
3618
+						'do_messages_on_same_request' => new EE_Select_Input(
3619
+							array(
3620
+								true  => esc_html__("On the same request", "event_espresso"),
3621
+								false => esc_html__("On a separate request", "event_espresso"),
3622
+							),
3623
+							array(
3624
+								'default'         => $network_config->do_messages_on_same_request,
3625
+								'html_label_text' => esc_html__(
3626
+									'Generate and send all messages:',
3627
+									'event_espresso'
3628
+								),
3629
+								'html_help_text'  => esc_html__(
3630
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3631
+									'event_espresso'
3632
+								),
3633
+							)
3634
+						),
3635
+						'delete_threshold'            => new EE_Select_Input(
3636
+							array(
3637
+								0  => esc_html__('Forever', 'event_espresso'),
3638
+								3  => esc_html__('3 Months', 'event_espresso'),
3639
+								6  => esc_html__('6 Months', 'event_espresso'),
3640
+								9  => esc_html__('9 Months', 'event_espresso'),
3641
+								12 => esc_html__('12 Months', 'event_espresso'),
3642
+								24 => esc_html__('24 Months', 'event_espresso'),
3643
+								36 => esc_html__('36 Months', 'event_espresso'),
3644
+							),
3645
+							array(
3646
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3647
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3648
+								'html_help_text'  => esc_html__(
3649
+									'You can control how long a record of processed messages is kept via this option.',
3650
+									'event_espresso'
3651
+								),
3652
+							)
3653
+						),
3654
+						'update_settings'             => new EE_Submit_Input(
3655
+							array(
3656
+								'default'         => esc_html__('Update', 'event_espresso'),
3657
+								'html_label_text' => '&nbsp',
3658
+							)
3659
+						),
3660
+					)
3661
+				),
3662
+			)
3663
+		);
3664
+	}
3665
+
3666
+
3667
+	/**
3668
+	 * This handles updating the global settings set on the admin page.
3669
+	 *
3670
+	 * @throws EE_Error
3671
+	 * @throws InvalidDataTypeException
3672
+	 * @throws InvalidInterfaceException
3673
+	 * @throws InvalidArgumentException
3674
+	 * @throws ReflectionException
3675
+	 */
3676
+	protected function _update_global_settings()
3677
+	{
3678
+		/** @var EE_Network_Core_Config $network_config */
3679
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3680
+		$messages_config = EE_Registry::instance()->CFG->messages;
3681
+		$form = $this->_generate_global_settings_form();
3682
+		if ($form->was_submitted()) {
3683
+			$form->receive_form_submission();
3684
+			if ($form->is_valid()) {
3685
+				$valid_data = $form->valid_data();
3686
+				foreach ($valid_data as $property => $value) {
3687
+					$setter = 'set_' . $property;
3688
+					if (method_exists($network_config, $setter)) {
3689
+						$network_config->{$setter}($value);
3690
+					} elseif (property_exists($network_config, $property)
3691
+						&& $network_config->{$property} !== $value
3692
+					) {
3693
+						$network_config->{$property} = $value;
3694
+					} elseif (property_exists($messages_config, $property)
3695
+						&& $messages_config->{$property} !== $value
3696
+					) {
3697
+						$messages_config->{$property} = $value;
3698
+					}
3699
+				}
3700
+				// only update if the form submission was valid!
3701
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3702
+				EE_Registry::instance()->CFG->update_espresso_config();
3703
+				EE_Error::overwrite_success();
3704
+				EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3705
+			}
3706
+		}
3707
+		$this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3708
+	}
3709
+
3710
+
3711
+	/**
3712
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3713
+	 *
3714
+	 * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3715
+	 * @return string html formatted tabs
3716
+	 * @throws DomainException
3717
+	 */
3718
+	protected function _get_mt_tabs($tab_array)
3719
+	{
3720
+		$tab_array = (array) $tab_array;
3721
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3722
+		$tabs = '';
3723
+
3724
+		foreach ($tab_array as $tab) {
3725
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3726
+		}
3727
+
3728
+		return $tabs;
3729
+	}
3730
+
3731
+
3732
+	/**
3733
+	 * This prepares the content of the messenger meta box admin settings
3734
+	 *
3735
+	 * @param  EE_messenger $messenger The messenger we're setting up content for
3736
+	 * @return string html formatted content
3737
+	 * @throws DomainException
3738
+	 */
3739
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3740
+	{
3741
+
3742
+		$fields = $messenger->get_admin_settings_fields();
3743
+		$settings_template_args['template_form_fields'] = '';
3744
+
3745
+		// is $messenger active?
3746
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3747
+
3748
+
3749
+		if (! empty($fields)) {
3750
+			$existing_settings = $messenger->get_existing_admin_settings();
3751
+
3752
+			foreach ($fields as $fldname => $fldprops) {
3753
+				$field_id = $messenger->name . '-' . $fldname;
3754
+				$template_form_field[ $field_id ] = array(
3755
+					'name'       => 'messenger_settings[' . $field_id . ']',
3756
+					'label'      => $fldprops['label'],
3757
+					'input'      => $fldprops['field_type'],
3758
+					'type'       => $fldprops['value_type'],
3759
+					'required'   => $fldprops['required'],
3760
+					'validation' => $fldprops['validation'],
3761
+					'value'      => isset($existing_settings[ $field_id ])
3762
+						? $existing_settings[ $field_id ]
3763
+						: $fldprops['default'],
3764
+					'css_class'  => '',
3765
+					'format'     => $fldprops['format'],
3766
+				);
3767
+			}
3768
+
3769
+
3770
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3771
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3772
+				: '';
3773
+		}
3774
+
3775
+		// we also need some hidden fields
3776
+		$settings_template_args['hidden_fields'] = array(
3777
+			'messenger_settings[messenger]' => array(
3778
+				'type'  => 'hidden',
3779
+				'value' => $messenger->name,
3780
+			),
3781
+			'type'                          => array(
3782
+				'type'  => 'hidden',
3783
+				'value' => 'messenger',
3784
+			),
3785
+		);
3786
+
3787
+		// make sure any active message types that are existing are included in the hidden fields
3788
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3789
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3790
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3791
+					'type'  => 'hidden',
3792
+					'value' => $mt,
3793
+				);
3794
+			}
3795
+		}
3796
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3797
+			$settings_template_args['hidden_fields'],
3798
+			'array'
3799
+		);
3800
+		$active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3801
+
3802
+		$settings_template_args['messenger'] = $messenger->name;
3803
+		$settings_template_args['description'] = $messenger->description;
3804
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3805
+
3806
+
3807
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3808
+			$messenger->name
3809
+		)
3810
+			? $settings_template_args['show_hide_edit_form']
3811
+			: ' hidden';
3812
+
3813
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3814
+			? ' hidden'
3815
+			: $settings_template_args['show_hide_edit_form'];
3816
+
3817
+
3818
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3819
+		$settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3820
+		$settings_template_args['on_off_status'] = $active ? true : false;
3821
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3822
+		$content = EEH_Template::display_template(
3823
+			$template,
3824
+			$settings_template_args,
3825
+			true
3826
+		);
3827
+
3828
+		return $content;
3829
+	}
3830
+
3831
+
3832
+	/**
3833
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3834
+	 *
3835
+	 * @throws DomainException
3836
+	 * @throws EE_Error
3837
+	 * @throws InvalidDataTypeException
3838
+	 * @throws InvalidInterfaceException
3839
+	 * @throws InvalidArgumentException
3840
+	 * @throws ReflectionException
3841
+	 */
3842
+	public function activate_messenger_toggle()
3843
+	{
3844
+		$success = true;
3845
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3846
+		// let's check that we have required data
3847
+		if (! isset($this->_req_data['messenger'])) {
3848
+			EE_Error::add_error(
3849
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3850
+				__FILE__,
3851
+				__FUNCTION__,
3852
+				__LINE__
3853
+			);
3854
+			$success = false;
3855
+		}
3856
+
3857
+		// do a nonce check here since we're not arriving via a normal route
3858
+		$nonce = isset($this->_req_data['activate_nonce'])
3859
+			? sanitize_text_field($this->_req_data['activate_nonce'])
3860
+			: '';
3861
+		$nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3862
+
3863
+		$this->_verify_nonce($nonce, $nonce_ref);
3864
+
3865
+
3866
+		if (! isset($this->_req_data['status'])) {
3867
+			EE_Error::add_error(
3868
+				esc_html__(
3869
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3870
+					'event_espresso'
3871
+				),
3872
+				__FILE__,
3873
+				__FUNCTION__,
3874
+				__LINE__
3875
+			);
3876
+			$success = false;
3877
+		}
3878
+
3879
+		// do check to verify we have a valid status.
3880
+		$status = $this->_req_data['status'];
3881
+
3882
+		if ($status !== 'off' && $status !== 'on') {
3883
+			EE_Error::add_error(
3884
+				sprintf(
3885
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3886
+					$this->_req_data['status']
3887
+				),
3888
+				__FILE__,
3889
+				__FUNCTION__,
3890
+				__LINE__
3891
+			);
3892
+			$success = false;
3893
+		}
3894
+
3895
+		if ($success) {
3896
+			// made it here?  Stop dawdling then!!
3897
+			$success = $status === 'off'
3898
+				? $this->_deactivate_messenger($this->_req_data['messenger'])
3899
+				: $this->_activate_messenger($this->_req_data['messenger']);
3900
+		}
3901
+
3902
+		$this->_template_args['success'] = $success;
3903
+
3904
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
3905
+		$this->_return_json();
3906
+	}
3907
+
3908
+
3909
+	/**
3910
+	 * used by ajax from the messages settings page to activate|deactivate a message type
3911
+	 *
3912
+	 * @throws DomainException
3913
+	 * @throws EE_Error
3914
+	 * @throws ReflectionException
3915
+	 * @throws InvalidDataTypeException
3916
+	 * @throws InvalidInterfaceException
3917
+	 * @throws InvalidArgumentException
3918
+	 */
3919
+	public function activate_mt_toggle()
3920
+	{
3921
+		$success = true;
3922
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3923
+
3924
+		// let's make sure we have the necessary data
3925
+		if (! isset($this->_req_data['message_type'])) {
3926
+			EE_Error::add_error(
3927
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3928
+				__FILE__,
3929
+				__FUNCTION__,
3930
+				__LINE__
3931
+			);
3932
+			$success = false;
3933
+		}
3934
+
3935
+		if (! isset($this->_req_data['messenger'])) {
3936
+			EE_Error::add_error(
3937
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3938
+				__FILE__,
3939
+				__FUNCTION__,
3940
+				__LINE__
3941
+			);
3942
+			$success = false;
3943
+		}
3944
+
3945
+		if (! isset($this->_req_data['status'])) {
3946
+			EE_Error::add_error(
3947
+				esc_html__(
3948
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3949
+					'event_espresso'
3950
+				),
3951
+				__FILE__,
3952
+				__FUNCTION__,
3953
+				__LINE__
3954
+			);
3955
+			$success = false;
3956
+		}
3957
+
3958
+
3959
+		// do check to verify we have a valid status.
3960
+		$status = $this->_req_data['status'];
3961
+
3962
+		if ($status !== 'activate' && $status !== 'deactivate') {
3963
+			EE_Error::add_error(
3964
+				sprintf(
3965
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3966
+					$this->_req_data['status']
3967
+				),
3968
+				__FILE__,
3969
+				__FUNCTION__,
3970
+				__LINE__
3971
+			);
3972
+			$success = false;
3973
+		}
3974
+
3975
+
3976
+		// do a nonce check here since we're not arriving via a normal route
3977
+		$nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3978
+		$nonce_ref = $this->_req_data['message_type'] . '_nonce';
3979
+
3980
+		$this->_verify_nonce($nonce, $nonce_ref);
3981
+
3982
+		if ($success) {
3983
+			// made it here? um, what are you waiting for then?
3984
+			$success = $status === 'deactivate'
3985
+				? $this->_deactivate_message_type_for_messenger(
3986
+					$this->_req_data['messenger'],
3987
+					$this->_req_data['message_type']
3988
+				)
3989
+				: $this->_activate_message_type_for_messenger(
3990
+					$this->_req_data['messenger'],
3991
+					$this->_req_data['message_type']
3992
+				);
3993
+		}
3994
+
3995
+		$this->_template_args['success'] = $success;
3996
+		$this->_return_json();
3997
+	}
3998
+
3999
+
4000
+	/**
4001
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
4002
+	 *
4003
+	 * @param string $messenger_name The name of the messenger being activated
4004
+	 * @return bool
4005
+	 * @throws DomainException
4006
+	 * @throws EE_Error
4007
+	 * @throws InvalidArgumentException
4008
+	 * @throws ReflectionException
4009
+	 * @throws InvalidDataTypeException
4010
+	 * @throws InvalidInterfaceException
4011
+	 */
4012
+	protected function _activate_messenger($messenger_name)
4013
+	{
4014
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4015
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4016
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
4017
+			? $active_messenger->get_default_message_types()
4018
+			: array();
4019
+
4020
+		// ensure is active
4021
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4022
+
4023
+		// set response_data for reload
4024
+		foreach ($message_types_to_activate as $message_type_name) {
4025
+			/** @var EE_message_type $message_type */
4026
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4027
+			if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4028
+				$messenger_name,
4029
+				$message_type_name
4030
+			)
4031
+				&& $message_type instanceof EE_message_type
4032
+			) {
4033
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
4034
+				if ($message_type->get_admin_settings_fields()) {
4035
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
4036
+				}
4037
+			}
4038
+		}
4039
+
4040
+		// add success message for activating messenger
4041
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4042
+	}
4043
+
4044
+
4045
+	/**
4046
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
4047
+	 *
4048
+	 * @param string $messenger_name The name of the messenger being activated
4049
+	 * @return bool
4050
+	 * @throws DomainException
4051
+	 * @throws EE_Error
4052
+	 * @throws InvalidArgumentException
4053
+	 * @throws ReflectionException
4054
+	 * @throws InvalidDataTypeException
4055
+	 * @throws InvalidInterfaceException
4056
+	 */
4057
+	protected function _deactivate_messenger($messenger_name)
4058
+	{
4059
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4060
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4061
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
4062
+
4063
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4064
+	}
4065
+
4066
+
4067
+	/**
4068
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4069
+	 *
4070
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
4071
+	 * @param string $message_type_name The name of the message type being activated for the messenger
4072
+	 * @return bool
4073
+	 * @throws DomainException
4074
+	 * @throws EE_Error
4075
+	 * @throws InvalidArgumentException
4076
+	 * @throws ReflectionException
4077
+	 * @throws InvalidDataTypeException
4078
+	 * @throws InvalidInterfaceException
4079
+	 */
4080
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4081
+	{
4082
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4083
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4084
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4085
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4086
+
4087
+		// ensure is active
4088
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4089
+
4090
+		// set response for load
4091
+		if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4092
+			$messenger_name,
4093
+			$message_type_name
4094
+		)
4095
+		) {
4096
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
4097
+			if ($message_type_to_activate->get_admin_settings_fields()) {
4098
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
4099
+			}
4100
+		}
4101
+
4102
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
4103
+			$active_messenger,
4104
+			$message_type_to_activate
4105
+		);
4106
+	}
4107
+
4108
+
4109
+	/**
4110
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4111
+	 *
4112
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4113
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
4114
+	 * @return bool
4115
+	 * @throws DomainException
4116
+	 * @throws EE_Error
4117
+	 * @throws InvalidArgumentException
4118
+	 * @throws ReflectionException
4119
+	 * @throws InvalidDataTypeException
4120
+	 * @throws InvalidInterfaceException
4121
+	 */
4122
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4123
+	{
4124
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4125
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4126
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4127
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4128
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4129
+
4130
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4131
+			$active_messenger,
4132
+			$message_type_to_deactivate
4133
+		);
4134
+	}
4135
+
4136
+
4137
+	/**
4138
+	 * This just initializes the defaults for activating messenger and message type responses.
4139
+	 */
4140
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
4141
+	{
4142
+		$this->_template_args['data']['active_mts'] = array();
4143
+		$this->_template_args['data']['mt_reload'] = array();
4144
+	}
4145
+
4146
+
4147
+	/**
4148
+	 * Setup appropriate response for activating a messenger and/or message types
4149
+	 *
4150
+	 * @param EE_messenger         $messenger
4151
+	 * @param EE_message_type|null $message_type
4152
+	 * @return bool
4153
+	 * @throws DomainException
4154
+	 * @throws EE_Error
4155
+	 * @throws InvalidArgumentException
4156
+	 * @throws ReflectionException
4157
+	 * @throws InvalidDataTypeException
4158
+	 * @throws InvalidInterfaceException
4159
+	 */
4160
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
4161
+		$messenger,
4162
+		EE_Message_Type $message_type = null
4163
+	) {
4164
+		// if $messenger isn't a valid messenger object then get out.
4165
+		if (! $messenger instanceof EE_Messenger) {
4166
+			EE_Error::add_error(
4167
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4168
+				__FILE__,
4169
+				__FUNCTION__,
4170
+				__LINE__
4171
+			);
4172
+
4173
+			return false;
4174
+		}
4175
+		// activated
4176
+		if ($this->_template_args['data']['active_mts']) {
4177
+			EE_Error::overwrite_success();
4178
+			// activated a message type with the messenger
4179
+			if ($message_type instanceof EE_message_type) {
4180
+				EE_Error::add_success(
4181
+					sprintf(
4182
+						esc_html__(
4183
+							'%s message type has been successfully activated with the %s messenger',
4184
+							'event_espresso'
4185
+						),
4186
+						ucwords($message_type->label['singular']),
4187
+						ucwords($messenger->label['singular'])
4188
+					)
4189
+				);
4190
+
4191
+				// if message type was invoice then let's make sure we activate the invoice payment method.
4192
+				if ($message_type->name === 'invoice') {
4193
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
4194
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4195
+					if ($pm instanceof EE_Payment_Method) {
4196
+						EE_Error::add_attention(
4197
+							esc_html__(
4198
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4199
+								'event_espresso'
4200
+							)
4201
+						);
4202
+					}
4203
+				}
4204
+				// just toggles the entire messenger
4205
+			} else {
4206
+				EE_Error::add_success(
4207
+					sprintf(
4208
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4209
+						ucwords($messenger->label['singular'])
4210
+					)
4211
+				);
4212
+			}
4213
+
4214
+			return true;
4215
+
4216
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4217
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4218
+			// in which case we just give a success message for the messenger being successfully activated.
4219
+		} else {
4220
+			if (! $messenger->get_default_message_types()) {
4221
+				// messenger doesn't have any default message types so still a success.
4222
+				EE_Error::add_success(
4223
+					sprintf(
4224
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4225
+						ucwords($messenger->label['singular'])
4226
+					)
4227
+				);
4228
+
4229
+				return true;
4230
+			} else {
4231
+				EE_Error::add_error(
4232
+					$message_type instanceof EE_message_type
4233
+						? sprintf(
4234
+							esc_html__(
4235
+								'%s message type was not successfully activated with the %s messenger',
4236
+								'event_espresso'
4237
+							),
4238
+							ucwords($message_type->label['singular']),
4239
+							ucwords($messenger->label['singular'])
4240
+						)
4241
+						: sprintf(
4242
+							esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4243
+							ucwords($messenger->label['singular'])
4244
+						),
4245
+					__FILE__,
4246
+					__FUNCTION__,
4247
+					__LINE__
4248
+				);
4249
+
4250
+				return false;
4251
+			}
4252
+		}
4253
+	}
4254
+
4255
+
4256
+	/**
4257
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
4258
+	 *
4259
+	 * @param EE_messenger         $messenger
4260
+	 * @param EE_message_type|null $message_type
4261
+	 * @return bool
4262
+	 * @throws DomainException
4263
+	 * @throws EE_Error
4264
+	 * @throws InvalidArgumentException
4265
+	 * @throws ReflectionException
4266
+	 * @throws InvalidDataTypeException
4267
+	 * @throws InvalidInterfaceException
4268
+	 */
4269
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4270
+		$messenger,
4271
+		EE_message_type $message_type = null
4272
+	) {
4273
+		EE_Error::overwrite_success();
4274
+
4275
+		// if $messenger isn't a valid messenger object then get out.
4276
+		if (! $messenger instanceof EE_Messenger) {
4277
+			EE_Error::add_error(
4278
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4279
+				__FILE__,
4280
+				__FUNCTION__,
4281
+				__LINE__
4282
+			);
4283
+
4284
+			return false;
4285
+		}
4286
+
4287
+		if ($message_type instanceof EE_message_type) {
4288
+			$message_type_name = $message_type->name;
4289
+			EE_Error::add_success(
4290
+				sprintf(
4291
+					esc_html__(
4292
+						'%s message type has been successfully deactivated for the %s messenger.',
4293
+						'event_espresso'
4294
+					),
4295
+					ucwords($message_type->label['singular']),
4296
+					ucwords($messenger->label['singular'])
4297
+				)
4298
+			);
4299
+		} else {
4300
+			$message_type_name = '';
4301
+			EE_Error::add_success(
4302
+				sprintf(
4303
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4304
+					ucwords($messenger->label['singular'])
4305
+				)
4306
+			);
4307
+		}
4308
+
4309
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4310
+		if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4311
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
4312
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4313
+			if ($count_updated > 0) {
4314
+				$msg = $message_type_name === 'invoice'
4315
+					? esc_html__(
4316
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4317
+						'event_espresso'
4318
+					)
4319
+					: esc_html__(
4320
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4321
+						'event_espresso'
4322
+					);
4323
+				EE_Error::add_attention($msg);
4324
+			}
4325
+		}
4326
+
4327
+		return true;
4328
+	}
4329
+
4330
+
4331
+	/**
4332
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4333
+	 *
4334
+	 * @throws DomainException
4335
+	 */
4336
+	public function update_mt_form()
4337
+	{
4338
+		if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4339
+			EE_Error::add_error(
4340
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4341
+				__FILE__,
4342
+				__FUNCTION__,
4343
+				__LINE__
4344
+			);
4345
+			$this->_return_json();
4346
+		}
4347
+
4348
+		$message_types = $this->get_installed_message_types();
4349
+
4350
+		$message_type = $message_types[ $this->_req_data['message_type'] ];
4351
+		$messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4352
+
4353
+		$content = $this->_message_type_settings_content(
4354
+			$message_type,
4355
+			$messenger,
4356
+			true
4357
+		);
4358
+		$this->_template_args['success'] = true;
4359
+		$this->_template_args['content'] = $content;
4360
+		$this->_return_json();
4361
+	}
4362
+
4363
+
4364
+	/**
4365
+	 * this handles saving the settings for a messenger or message type
4366
+	 *
4367
+	 */
4368
+	public function save_settings()
4369
+	{
4370
+		if (! isset($this->_req_data['type'])) {
4371
+			EE_Error::add_error(
4372
+				esc_html__(
4373
+					'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4374
+					'event_espresso'
4375
+				),
4376
+				__FILE__,
4377
+				__FUNCTION__,
4378
+				__LINE__
4379
+			);
4380
+			$this->_template_args['error'] = true;
4381
+			$this->_return_json();
4382
+		}
4383
+
4384
+
4385
+		if ($this->_req_data['type'] === 'messenger') {
4386
+			// this should be an array.
4387
+			$settings = $this->_req_data['messenger_settings'];
4388
+			$messenger = $settings['messenger'];
4389
+			// let's setup the settings data
4390
+			foreach ($settings as $key => $value) {
4391
+				switch ($key) {
4392
+					case 'messenger':
4393
+						unset($settings['messenger']);
4394
+						break;
4395
+					case 'message_types':
4396
+						unset($settings['message_types']);
4397
+						break;
4398
+					default:
4399
+						$settings[ $key ] = $value;
4400
+						break;
4401
+				}
4402
+			}
4403
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4404
+		} elseif ($this->_req_data['type'] === 'message_type') {
4405
+			$settings = $this->_req_data['message_type_settings'];
4406
+			$messenger = $settings['messenger'];
4407
+			$message_type = $settings['message_type'];
4408
+
4409
+			foreach ($settings as $key => $value) {
4410
+				switch ($key) {
4411
+					case 'messenger':
4412
+						unset($settings['messenger']);
4413
+						break;
4414
+					case 'message_type':
4415
+						unset($settings['message_type']);
4416
+						break;
4417
+					default:
4418
+						$settings[ $key ] = $value;
4419
+						break;
4420
+				}
4421
+			}
4422
+
4423
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4424
+		}
4425
+
4426
+		// okay we should have the data all setup.  Now we just update!
4427
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4428
+
4429
+		if ($success) {
4430
+			EE_Error::add_success(__('Settings updated', 'event_espresso'));
4431
+		} else {
4432
+			EE_Error::add_error(
4433
+				esc_html__(
4434
+					'Settings did not get updated',
4435
+					'event_espresso'
4436
+				),
4437
+				__FILE__,
4438
+				__FUNCTION__,
4439
+				__LINE__
4440
+			);
4441
+		}
4442
+
4443
+		$this->_template_args['success'] = $success;
4444
+		$this->_return_json();
4445
+	}
4446
+
4447
+
4448
+
4449
+
4450
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4451
+
4452
+
4453
+	/**
4454
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4455
+	 * However, this does not send immediately, it just queues for sending.
4456
+	 *
4457
+	 * @since 4.9.0
4458
+	 * @throws EE_Error
4459
+	 * @throws InvalidDataTypeException
4460
+	 * @throws InvalidInterfaceException
4461
+	 * @throws InvalidArgumentException
4462
+	 * @throws ReflectionException
4463
+	 */
4464
+	protected function _generate_now()
4465
+	{
4466
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4467
+		$this->_redirect_after_action(false, '', '', array(), true);
4468
+	}
4469
+
4470
+
4471
+	/**
4472
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4473
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4474
+	 *
4475
+	 * @since 4.9.0
4476
+	 * @throws EE_Error
4477
+	 * @throws InvalidDataTypeException
4478
+	 * @throws InvalidInterfaceException
4479
+	 * @throws InvalidArgumentException
4480
+	 * @throws ReflectionException
4481
+	 */
4482
+	protected function _generate_and_send_now()
4483
+	{
4484
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4485
+		$this->_redirect_after_action(false, '', '', array(), true);
4486
+	}
4487
+
4488
+
4489
+	/**
4490
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4491
+	 *
4492
+	 * @since 4.9.0
4493
+	 * @throws EE_Error
4494
+	 * @throws InvalidDataTypeException
4495
+	 * @throws InvalidInterfaceException
4496
+	 * @throws InvalidArgumentException
4497
+	 * @throws ReflectionException
4498
+	 */
4499
+	protected function _queue_for_resending()
4500
+	{
4501
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4502
+		$this->_redirect_after_action(false, '', '', array(), true);
4503
+	}
4504
+
4505
+
4506
+	/**
4507
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4508
+	 *
4509
+	 * @since 4.9.0
4510
+	 * @throws EE_Error
4511
+	 * @throws InvalidDataTypeException
4512
+	 * @throws InvalidInterfaceException
4513
+	 * @throws InvalidArgumentException
4514
+	 * @throws ReflectionException
4515
+	 */
4516
+	protected function _send_now()
4517
+	{
4518
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4519
+		$this->_redirect_after_action(false, '', '', array(), true);
4520
+	}
4521
+
4522
+
4523
+	/**
4524
+	 * Deletes EE_messages for IDs in the request.
4525
+	 *
4526
+	 * @since 4.9.0
4527
+	 * @throws EE_Error
4528
+	 * @throws InvalidDataTypeException
4529
+	 * @throws InvalidInterfaceException
4530
+	 * @throws InvalidArgumentException
4531
+	 */
4532
+	protected function _delete_ee_messages()
4533
+	{
4534
+		$msg_ids = $this->_get_msg_ids_from_request();
4535
+		$deleted_count = 0;
4536
+		foreach ($msg_ids as $msg_id) {
4537
+			if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4538
+				$deleted_count++;
4539
+			}
4540
+		}
4541
+		if ($deleted_count) {
4542
+			EE_Error::add_success(
4543
+				esc_html(
4544
+					_n(
4545
+						'Message successfully deleted',
4546
+						'Messages successfully deleted',
4547
+						$deleted_count,
4548
+						'event_espresso'
4549
+					)
4550
+				)
4551
+			);
4552
+			$this->_redirect_after_action(
4553
+				false,
4554
+				'',
4555
+				'',
4556
+				array(),
4557
+				true
4558
+			);
4559
+		} else {
4560
+			EE_Error::add_error(
4561
+				_n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4562
+				__FILE__,
4563
+				__FUNCTION__,
4564
+				__LINE__
4565
+			);
4566
+			$this->_redirect_after_action(false, '', '', array(), true);
4567
+		}
4568
+	}
4569
+
4570
+
4571
+	/**
4572
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4573
+	 *
4574
+	 * @since 4.9.0
4575
+	 * @return array
4576
+	 */
4577
+	protected function _get_msg_ids_from_request()
4578
+	{
4579
+		if (! isset($this->_req_data['MSG_ID'])) {
4580
+			return array();
4581
+		}
4582
+
4583
+		return is_array($this->_req_data['MSG_ID'])
4584
+			? array_keys($this->_req_data['MSG_ID'])
4585
+			: array($this->_req_data['MSG_ID']);
4586
+	}
4587 4587
 }
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2556 added lines, -2556 removed lines patch added patch discarded remove patch
@@ -13,2560 +13,2560 @@
 block discarded – undo
13 13
 class Transactions_Admin_Page extends EE_Admin_Page
14 14
 {
15 15
 
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug = TXN_PG_SLUG;
50
-        $this->page_label = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels = array(
78
-            'buttons' => array(
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ),
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     */
97
-    public function _set_page_routes()
98
-    {
99
-
100
-        $this->_set_transaction_status_array();
101
-
102
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
103
-                  && ! is_array($this->_req_data['TXN_ID'])
104
-            ? $this->_req_data['TXN_ID']
105
-            : 0;
106
-
107
-        $this->_page_routes = array(
108
-
109
-            'default' => array(
110
-                'func'       => '_transactions_overview_list_table',
111
-                'capability' => 'ee_read_transactions',
112
-            ),
113
-
114
-            'view_transaction' => array(
115
-                'func'       => '_transaction_details',
116
-                'capability' => 'ee_read_transaction',
117
-                'obj_id'     => $txn_id,
118
-            ),
119
-
120
-            'send_payment_reminder' => array(
121
-                'func'       => '_send_payment_reminder',
122
-                'noheader'   => true,
123
-                'capability' => 'ee_send_message',
124
-            ),
125
-
126
-            'espresso_apply_payment' => array(
127
-                'func'       => 'apply_payments_or_refunds',
128
-                'noheader'   => true,
129
-                'capability' => 'ee_edit_payments',
130
-            ),
131
-
132
-            'espresso_apply_refund' => array(
133
-                'func'       => 'apply_payments_or_refunds',
134
-                'noheader'   => true,
135
-                'capability' => 'ee_edit_payments',
136
-            ),
137
-
138
-            'espresso_delete_payment' => array(
139
-                'func'       => 'delete_payment',
140
-                'noheader'   => true,
141
-                'capability' => 'ee_delete_payments',
142
-            ),
143
-
144
-            'espresso_recalculate_line_items' => array(
145
-                'func'       => 'recalculateLineItems',
146
-                'noheader'   => true,
147
-                'capability' => 'ee_edit_payments',
148
-            ),
149
-
150
-        );
151
-    }
152
-
153
-
154
-    protected function _set_page_config()
155
-    {
156
-        $this->_page_config = array(
157
-            'default'          => array(
158
-                'nav'           => array(
159
-                    'label' => esc_html__('Overview', 'event_espresso'),
160
-                    'order' => 10,
161
-                ),
162
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
163
-                'help_tabs'     => array(
164
-                    'transactions_overview_help_tab'                       => array(
165
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
-                        'filename' => 'transactions_overview',
167
-                    ),
168
-                    'transactions_overview_table_column_headings_help_tab' => array(
169
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
-                        'filename' => 'transactions_overview_table_column_headings',
171
-                    ),
172
-                    'transactions_overview_views_filters_help_tab'         => array(
173
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
-                        'filename' => 'transactions_overview_views_filters_search',
175
-                    ),
176
-                ),
177
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
-                // 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
-                /**
180
-                 * commented out because currently we are not displaying tips for transaction list table status but this
181
-                 * may change in a later iteration so want to keep the code for then.
182
-                 */
183
-                // 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
-                'require_nonce' => false,
185
-            ),
186
-            'view_transaction' => array(
187
-                'nav'       => array(
188
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
189
-                    'order'      => 5,
190
-                    'url'        => isset($this->_req_data['TXN_ID'])
191
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
-                        : $this->_admin_base_url,
193
-                    'persistent' => false,
194
-                ),
195
-                'help_tabs' => array(
196
-                    'transactions_view_transaction_help_tab'                                              => array(
197
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction',
199
-                    ),
200
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
203
-                    ),
204
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
-                        'filename' => 'transactions_view_transaction_attendees_registered',
207
-                    ),
208
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
-                    ),
212
-                ),
213
-                'qtips'     => array('Transaction_Details_Tips'),
214
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
-                // 'help_tour' => array('Transaction_Details_Help_Tour'),
216
-                'metaboxes' => array('_transaction_details_metaboxes'),
217
-
218
-                'require_nonce' => false,
219
-            ),
220
-        );
221
-    }
222
-
223
-
224
-    /**
225
-     * The below methods aren't used by this class currently
226
-     */
227
-    protected function _add_screen_options()
228
-    {
229
-        // noop
230
-    }
231
-
232
-
233
-    protected function _add_feature_pointers()
234
-    {
235
-        // noop
236
-    }
237
-
238
-
239
-    public function admin_init()
240
-    {
241
-        // IF a registration was JUST added via the admin...
242
-        if (isset(
243
-            $this->_req_data['redirect_from'],
244
-            $this->_req_data['EVT_ID'],
245
-            $this->_req_data['event_name']
246
-        )) {
247
-            // then set a cookie so that we can block any attempts to use
248
-            // the back button as a way to enter another registration.
249
-            setcookie(
250
-                'ee_registration_added',
251
-                $this->_req_data['EVT_ID'],
252
-                time() + WEEK_IN_SECONDS,
253
-                '/'
254
-            );
255
-            // and update the global
256
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
257
-        }
258
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
259
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
260
-            'event_espresso'
261
-        );
262
-        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
263
-            'An error occurred! Please refresh the page and try again.',
264
-            'event_espresso'
265
-        );
266
-        EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
267
-        EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
268
-        EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
269
-        EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
270
-            'This transaction has been overpaid ! Payments Total',
271
-            'event_espresso'
272
-        );
273
-    }
274
-
275
-
276
-    public function admin_notices()
277
-    {
278
-        // noop
279
-    }
280
-
281
-
282
-    public function admin_footer_scripts()
283
-    {
284
-        // noop
285
-    }
286
-
287
-
288
-    /**
289
-     * _set_transaction_status_array
290
-     * sets list of transaction statuses
291
-     *
292
-     * @access private
293
-     * @return void
294
-     * @throws EE_Error
295
-     * @throws InvalidArgumentException
296
-     * @throws InvalidDataTypeException
297
-     * @throws InvalidInterfaceException
298
-     */
299
-    private function _set_transaction_status_array()
300
-    {
301
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
302
-    }
303
-
304
-
305
-    /**
306
-     * get_transaction_status_array
307
-     * return the transaction status array for wp_list_table
308
-     *
309
-     * @access public
310
-     * @return array
311
-     */
312
-    public function get_transaction_status_array()
313
-    {
314
-        return self::$_txn_status;
315
-    }
316
-
317
-
318
-    /**
319
-     *    get list of payment statuses
320
-     *
321
-     * @access private
322
-     * @return void
323
-     * @throws EE_Error
324
-     * @throws InvalidArgumentException
325
-     * @throws InvalidDataTypeException
326
-     * @throws InvalidInterfaceException
327
-     */
328
-    private function _get_payment_status_array()
329
-    {
330
-        self::$_pay_status = EEM_Payment::instance()->status_array(true);
331
-        $this->_template_args['payment_status'] = self::$_pay_status;
332
-    }
333
-
334
-
335
-    /**
336
-     *    _add_screen_options_default
337
-     *
338
-     * @access protected
339
-     * @return void
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     */
344
-    protected function _add_screen_options_default()
345
-    {
346
-        $this->_per_page_screen_option();
347
-    }
348
-
349
-
350
-    /**
351
-     * load_scripts_styles
352
-     *
353
-     * @access public
354
-     * @return void
355
-     */
356
-    public function load_scripts_styles()
357
-    {
358
-        // enqueue style
359
-        wp_register_style(
360
-            'espresso_txn',
361
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
362
-            array(),
363
-            EVENT_ESPRESSO_VERSION
364
-        );
365
-        wp_enqueue_style('espresso_txn');
366
-        // scripts
367
-        wp_register_script(
368
-            'espresso_txn',
369
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
370
-            array(
371
-                'ee_admin_js',
372
-                'ee-datepicker',
373
-                'jquery-ui-datepicker',
374
-                'jquery-ui-draggable',
375
-                'ee-dialog',
376
-                'ee-accounting',
377
-                'ee-serialize-full-array',
378
-            ),
379
-            EVENT_ESPRESSO_VERSION,
380
-            true
381
-        );
382
-        wp_enqueue_script('espresso_txn');
383
-    }
384
-
385
-
386
-    /**
387
-     *    load_scripts_styles_view_transaction
388
-     *
389
-     * @access public
390
-     * @return void
391
-     */
392
-    public function load_scripts_styles_view_transaction()
393
-    {
394
-        // styles
395
-        wp_enqueue_style('espresso-ui-theme');
396
-    }
397
-
398
-
399
-    /**
400
-     *    load_scripts_styles_default
401
-     *
402
-     * @access public
403
-     * @return void
404
-     */
405
-    public function load_scripts_styles_default()
406
-    {
407
-        // styles
408
-        wp_enqueue_style('espresso-ui-theme');
409
-    }
410
-
411
-
412
-    /**
413
-     *    _set_list_table_views_default
414
-     *
415
-     * @access protected
416
-     * @return void
417
-     */
418
-    protected function _set_list_table_views_default()
419
-    {
420
-        $this->_views = array(
421
-            'all'        => array(
422
-                'slug'  => 'all',
423
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
424
-                'count' => 0,
425
-            ),
426
-            'abandoned'  => array(
427
-                'slug'  => 'abandoned',
428
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
-                'count' => 0,
430
-            ),
431
-            'incomplete' => array(
432
-                'slug'  => 'incomplete',
433
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
434
-                'count' => 0,
435
-            ),
436
-        );
437
-        if (/**
438
-         * Filters whether a link to the "Failed Transactions" list table
439
-         * appears on the Transactions Admin Page list table.
440
-         * List display can be turned back on via the following:
441
-         * add_filter(
442
-         *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
443
-         *     '__return_true'
444
-         * );
445
-         *
446
-         * @since 4.9.70.p
447
-         * @param boolean                 $display_failed_txns_list
448
-         * @param Transactions_Admin_Page $this
449
-         */
450
-        apply_filters(
451
-            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
452
-            false,
453
-            $this
454
-        )
455
-        ) {
456
-            $this->_views['failed'] = array(
457
-                'slug'  => 'failed',
458
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
459
-                'count' => 0,
460
-            );
461
-        }
462
-    }
463
-
464
-
465
-    /**
466
-     * _set_transaction_object
467
-     * This sets the _transaction property for the transaction details screen
468
-     *
469
-     * @access private
470
-     * @return void
471
-     * @throws EE_Error
472
-     * @throws InvalidArgumentException
473
-     * @throws RuntimeException
474
-     * @throws InvalidDataTypeException
475
-     * @throws InvalidInterfaceException
476
-     * @throws ReflectionException
477
-     */
478
-    private function _set_transaction_object()
479
-    {
480
-        if ($this->_transaction instanceof EE_Transaction) {
481
-            return;
482
-        } //get out we've already set the object
483
-
484
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
485
-            ? absint($this->_req_data['TXN_ID'])
486
-            : false;
487
-
488
-        // get transaction object
489
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
490
-        $this->_session = $this->_transaction instanceof EE_Transaction
491
-            ? $this->_transaction->session_data()
492
-            : null;
493
-        if ($this->_transaction instanceof EE_Transaction) {
494
-            $this->_transaction->verify_abandoned_transaction_status();
495
-        }
496
-
497
-        if (! $this->_transaction instanceof EE_Transaction) {
498
-            $error_msg = sprintf(
499
-                esc_html__(
500
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
501
-                    'event_espresso'
502
-                ),
503
-                $TXN_ID
504
-            );
505
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
506
-        }
507
-    }
508
-
509
-
510
-    /**
511
-     *    _transaction_legend_items
512
-     *
513
-     * @access protected
514
-     * @return array
515
-     * @throws EE_Error
516
-     * @throws InvalidArgumentException
517
-     * @throws ReflectionException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     */
521
-    protected function _transaction_legend_items()
522
-    {
523
-        EE_Registry::instance()->load_helper('MSG_Template');
524
-        $items = array();
525
-
526
-        if (EE_Registry::instance()->CAP->current_user_can(
527
-            'ee_read_global_messages',
528
-            'view_filtered_messages'
529
-        )) {
530
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
531
-            if (is_array($related_for_icon)
532
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
533
-            ) {
534
-                $items['view_related_messages'] = array(
535
-                    'class' => $related_for_icon['css_class'],
536
-                    'desc'  => $related_for_icon['label'],
537
-                );
538
-            }
539
-        }
540
-
541
-        $items = apply_filters(
542
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
543
-            array_merge(
544
-                $items,
545
-                array(
546
-                    'view_details'          => array(
547
-                        'class' => 'dashicons dashicons-cart',
548
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
549
-                    ),
550
-                    'view_invoice'          => array(
551
-                        'class' => 'dashicons dashicons-media-spreadsheet',
552
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
553
-                    ),
554
-                    'view_receipt'          => array(
555
-                        'class' => 'dashicons dashicons-media-default',
556
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
557
-                    ),
558
-                    'view_registration'     => array(
559
-                        'class' => 'dashicons dashicons-clipboard',
560
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
561
-                    ),
562
-                    'payment_overview_link' => array(
563
-                        'class' => 'dashicons dashicons-money',
564
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
565
-                    ),
566
-                )
567
-            )
568
-        );
569
-
570
-        if (EEH_MSG_Template::is_mt_active('payment_reminder')
571
-            && EE_Registry::instance()->CAP->current_user_can(
572
-                'ee_send_message',
573
-                'espresso_transactions_send_payment_reminder'
574
-            )
575
-        ) {
576
-            $items['send_payment_reminder'] = array(
577
-                'class' => 'dashicons dashicons-email-alt',
578
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
579
-            );
580
-        } else {
581
-            $items['blank*'] = array(
582
-                'class' => '',
583
-                'desc'  => '',
584
-            );
585
-        }
586
-        $more_items = apply_filters(
587
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
588
-            array(
589
-                'overpaid'   => array(
590
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
591
-                    'desc'  => EEH_Template::pretty_status(
592
-                        EEM_Transaction::overpaid_status_code,
593
-                        false,
594
-                        'sentence'
595
-                    ),
596
-                ),
597
-                'complete'   => array(
598
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
599
-                    'desc'  => EEH_Template::pretty_status(
600
-                        EEM_Transaction::complete_status_code,
601
-                        false,
602
-                        'sentence'
603
-                    ),
604
-                ),
605
-                'incomplete' => array(
606
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
607
-                    'desc'  => EEH_Template::pretty_status(
608
-                        EEM_Transaction::incomplete_status_code,
609
-                        false,
610
-                        'sentence'
611
-                    ),
612
-                ),
613
-                'abandoned'  => array(
614
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
615
-                    'desc'  => EEH_Template::pretty_status(
616
-                        EEM_Transaction::abandoned_status_code,
617
-                        false,
618
-                        'sentence'
619
-                    ),
620
-                ),
621
-                'failed'     => array(
622
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
623
-                    'desc'  => EEH_Template::pretty_status(
624
-                        EEM_Transaction::failed_status_code,
625
-                        false,
626
-                        'sentence'
627
-                    ),
628
-                ),
629
-            )
630
-        );
631
-
632
-        return array_merge($items, $more_items);
633
-    }
634
-
635
-
636
-    /**
637
-     *    _transactions_overview_list_table
638
-     *
639
-     * @access protected
640
-     * @return void
641
-     * @throws DomainException
642
-     * @throws EE_Error
643
-     * @throws InvalidArgumentException
644
-     * @throws InvalidDataTypeException
645
-     * @throws InvalidInterfaceException
646
-     * @throws ReflectionException
647
-     */
648
-    protected function _transactions_overview_list_table()
649
-    {
650
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
651
-        $event = isset($this->_req_data['EVT_ID'])
652
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
653
-            : null;
654
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
655
-            ? sprintf(
656
-                esc_html__(
657
-                    '%sViewing Transactions for the Event: %s%s',
658
-                    'event_espresso'
659
-                ),
660
-                '<h3>',
661
-                '<a href="'
662
-                . EE_Admin_Page::add_query_args_and_nonce(
663
-                    array('action' => 'edit', 'post' => $event->ID()),
664
-                    EVENTS_ADMIN_URL
665
-                )
666
-                . '" title="'
667
-                . esc_attr__(
668
-                    'Click to Edit event',
669
-                    'event_espresso'
670
-                )
671
-                . '">' . $event->name() . '</a>',
672
-                '</h3>'
673
-            )
674
-            : '';
675
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
676
-        $this->display_admin_list_table_page_with_no_sidebar();
677
-    }
678
-
679
-
680
-    /**
681
-     *    _transaction_details
682
-     * generates HTML for the View Transaction Details Admin page
683
-     *
684
-     * @access protected
685
-     * @return void
686
-     * @throws DomainException
687
-     * @throws EE_Error
688
-     * @throws InvalidArgumentException
689
-     * @throws InvalidDataTypeException
690
-     * @throws InvalidInterfaceException
691
-     * @throws RuntimeException
692
-     * @throws ReflectionException
693
-     */
694
-    protected function _transaction_details()
695
-    {
696
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
697
-
698
-        $this->_set_transaction_status_array();
699
-
700
-        $this->_template_args = array();
701
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
702
-
703
-        $this->_set_transaction_object();
704
-
705
-        if (! $this->_transaction instanceof EE_Transaction) {
706
-            return;
707
-        }
708
-        $primary_registration = $this->_transaction->primary_registration();
709
-        $attendee = $primary_registration instanceof EE_Registration
710
-            ? $primary_registration->attendee()
711
-            : null;
712
-
713
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
714
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
715
-
716
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
717
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
718
-
719
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
720
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
721
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
722
-
723
-        $this->_template_args['grand_total'] = $this->_transaction->total();
724
-        $this->_template_args['total_paid'] = $this->_transaction->paid();
725
-
726
-        $amount_due = $this->_transaction->total() - $this->_transaction->paid();
727
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
728
-            $amount_due,
729
-            true
730
-        );
731
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
732
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
733
-                                                  . $this->_template_args['amount_due'];
734
-        } else {
735
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
736
-        }
737
-        $this->_template_args['amount_due_class'] = '';
738
-
739
-        if ($this->_transaction->paid() === $this->_transaction->total()) {
740
-            // paid in full
741
-            $this->_template_args['amount_due'] = false;
742
-        } elseif ($this->_transaction->paid() > $this->_transaction->total()) {
743
-            // overpaid
744
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
745
-        } elseif ($this->_transaction->total() > (float) 0) {
746
-            if ($this->_transaction->paid() > (float) 0) {
747
-                // monies owing
748
-                $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
749
-            } elseif ($this->_transaction->paid() === (float) 0) {
750
-                // no payments made yet
751
-                $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
752
-            }
753
-        } elseif ($this->_transaction->total() === (float) 0) {
754
-            // free event
755
-            $this->_template_args['amount_due'] = false;
756
-        }
757
-
758
-        $payment_method = $this->_transaction->payment_method();
759
-
760
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
761
-            ? $payment_method->admin_name()
762
-            : esc_html__('Unknown', 'event_espresso');
763
-
764
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
765
-        // link back to overview
766
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
767
-            ? $_SERVER['HTTP_REFERER']
768
-            : TXN_ADMIN_URL;
769
-
770
-
771
-        // next link
772
-        $next_txn = $this->_transaction->next(
773
-            null,
774
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
775
-            'TXN_ID'
776
-        );
777
-        $this->_template_args['next_transaction'] = $next_txn
778
-            ? $this->_next_link(
779
-                EE_Admin_Page::add_query_args_and_nonce(
780
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
781
-                    TXN_ADMIN_URL
782
-                ),
783
-                'dashicons dashicons-arrow-right ee-icon-size-22'
784
-            )
785
-            : '';
786
-        // previous link
787
-        $previous_txn = $this->_transaction->previous(
788
-            null,
789
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
790
-            'TXN_ID'
791
-        );
792
-        $this->_template_args['previous_transaction'] = $previous_txn
793
-            ? $this->_previous_link(
794
-                EE_Admin_Page::add_query_args_and_nonce(
795
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
796
-                    TXN_ADMIN_URL
797
-                ),
798
-                'dashicons dashicons-arrow-left ee-icon-size-22'
799
-            )
800
-            : '';
801
-
802
-        // were we just redirected here after adding a new registration ???
803
-        if (isset(
804
-            $this->_req_data['redirect_from'],
805
-            $this->_req_data['EVT_ID'],
806
-            $this->_req_data['event_name']
807
-        )) {
808
-            if (EE_Registry::instance()->CAP->current_user_can(
809
-                'ee_edit_registrations',
810
-                'espresso_registrations_new_registration',
811
-                $this->_req_data['EVT_ID']
812
-            )) {
813
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
814
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
815
-                    array(
816
-                        'page'     => 'espresso_registrations',
817
-                        'action'   => 'new_registration',
818
-                        'return'   => 'default',
819
-                        'TXN_ID'   => $this->_transaction->ID(),
820
-                        'event_id' => $this->_req_data['EVT_ID'],
821
-                    ),
822
-                    REG_ADMIN_URL
823
-                );
824
-                $this->_admin_page_title .= '">';
825
-
826
-                $this->_admin_page_title .= sprintf(
827
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
828
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
829
-                );
830
-                $this->_admin_page_title .= '</a>';
831
-            }
832
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
833
-        }
834
-        // grab messages at the last second
835
-        $this->_template_args['notices'] = EE_Error::get_notices();
836
-        // path to template
837
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
838
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
839
-            $template_path,
840
-            $this->_template_args,
841
-            true
842
-        );
843
-
844
-        // the details template wrapper
845
-        $this->display_admin_page_with_sidebar();
846
-    }
847
-
848
-
849
-    /**
850
-     *        _transaction_details_metaboxes
851
-     *
852
-     * @access protected
853
-     * @return void
854
-     * @throws EE_Error
855
-     * @throws InvalidArgumentException
856
-     * @throws InvalidDataTypeException
857
-     * @throws InvalidInterfaceException
858
-     * @throws RuntimeException
859
-     * @throws ReflectionException
860
-     */
861
-    protected function _transaction_details_metaboxes()
862
-    {
863
-
864
-        $this->_set_transaction_object();
865
-
866
-        if (! $this->_transaction instanceof EE_Transaction) {
867
-            return;
868
-        }
869
-        add_meta_box(
870
-            'edit-txn-details-mbox',
871
-            esc_html__('Transaction Details', 'event_espresso'),
872
-            array($this, 'txn_details_meta_box'),
873
-            $this->_wp_page_slug,
874
-            'normal',
875
-            'high'
876
-        );
877
-        add_meta_box(
878
-            'edit-txn-attendees-mbox',
879
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
-            array($this, 'txn_attendees_meta_box'),
881
-            $this->_wp_page_slug,
882
-            'normal',
883
-            'high',
884
-            array('TXN_ID' => $this->_transaction->ID())
885
-        );
886
-        add_meta_box(
887
-            'edit-txn-registrant-mbox',
888
-            esc_html__('Primary Contact', 'event_espresso'),
889
-            array($this, 'txn_registrant_side_meta_box'),
890
-            $this->_wp_page_slug,
891
-            'side',
892
-            'high'
893
-        );
894
-        add_meta_box(
895
-            'edit-txn-billing-info-mbox',
896
-            esc_html__('Billing Information', 'event_espresso'),
897
-            array($this, 'txn_billing_info_side_meta_box'),
898
-            $this->_wp_page_slug,
899
-            'side',
900
-            'high'
901
-        );
902
-    }
903
-
904
-
905
-    /**
906
-     * Callback for transaction actions metabox.
907
-     *
908
-     * @param EE_Transaction|null $transaction
909
-     * @return string
910
-     * @throws DomainException
911
-     * @throws EE_Error
912
-     * @throws InvalidArgumentException
913
-     * @throws InvalidDataTypeException
914
-     * @throws InvalidInterfaceException
915
-     * @throws ReflectionException
916
-     * @throws RuntimeException
917
-     */
918
-    public function getActionButtons(EE_Transaction $transaction = null)
919
-    {
920
-        $content = '';
921
-        $actions = array();
922
-        if (! $transaction instanceof EE_Transaction) {
923
-            return $content;
924
-        }
925
-        /** @var EE_Registration $primary_registration */
926
-        $primary_registration = $transaction->primary_registration();
927
-        $attendee = $primary_registration instanceof EE_Registration
928
-            ? $primary_registration->attendee()
929
-            : null;
930
-
931
-        if ($attendee instanceof EE_Attendee
932
-            && EE_Registry::instance()->CAP->current_user_can(
933
-                'ee_send_message',
934
-                'espresso_transactions_send_payment_reminder'
935
-            )
936
-        ) {
937
-            $actions['payment_reminder'] =
938
-                EEH_MSG_Template::is_mt_active('payment_reminder')
939
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
940
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
941
-                    ? EEH_Template::get_button_or_link(
942
-                        EE_Admin_Page::add_query_args_and_nonce(
943
-                            array(
944
-                                'action'      => 'send_payment_reminder',
945
-                                'TXN_ID'      => $this->_transaction->ID(),
946
-                                'redirect_to' => 'view_transaction',
947
-                            ),
948
-                            TXN_ADMIN_URL
949
-                        ),
950
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
951
-                        'button secondary-button',
952
-                        'dashicons dashicons-email-alt'
953
-                    )
954
-                    : '';
955
-        }
956
-
957
-        if (EE_Registry::instance()->CAP->current_user_can(
958
-            'ee_edit_payments',
959
-            'espresso_transactions_recalculate_line_items'
960
-        )
961
-        ) {
962
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
963
-                EE_Admin_Page::add_query_args_and_nonce(
964
-                    array(
965
-                        'action'      => 'espresso_recalculate_line_items',
966
-                        'TXN_ID'      => $this->_transaction->ID(),
967
-                        'redirect_to' => 'view_transaction',
968
-                    ),
969
-                    TXN_ADMIN_URL
970
-                ),
971
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
972
-                'button secondary-button',
973
-                'dashicons dashicons-update'
974
-            );
975
-        }
976
-
977
-        if ($primary_registration instanceof EE_Registration
978
-            && EEH_MSG_Template::is_mt_active('receipt')
979
-        ) {
980
-            $actions['receipt'] = EEH_Template::get_button_or_link(
981
-                $primary_registration->receipt_url(),
982
-                esc_html__('View Receipt', 'event_espresso'),
983
-                'button secondary-button',
984
-                'dashicons dashicons-media-default'
985
-            );
986
-        }
987
-
988
-        if ($primary_registration instanceof EE_Registration
989
-            && EEH_MSG_Template::is_mt_active('invoice')
990
-        ) {
991
-            $actions['invoice'] = EEH_Template::get_button_or_link(
992
-                $primary_registration->invoice_url(),
993
-                esc_html__('View Invoice', 'event_espresso'),
994
-                'button secondary-button',
995
-                'dashicons dashicons-media-spreadsheet'
996
-            );
997
-        }
998
-        $actions = array_filter(
999
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1000
-        );
1001
-        if ($actions) {
1002
-            $content = '<ul>';
1003
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1004
-            $content .= '</uL>';
1005
-        }
1006
-        return $content;
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * txn_details_meta_box
1012
-     * generates HTML for the Transaction main meta box
1013
-     *
1014
-     * @return void
1015
-     * @throws DomainException
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     * @throws RuntimeException
1021
-     * @throws ReflectionException
1022
-     */
1023
-    public function txn_details_meta_box()
1024
-    {
1025
-        $this->_set_transaction_object();
1026
-        $this->_template_args['TXN_ID'] = $this->_transaction->ID();
1027
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1028
-            ? $this->_transaction->primary_registration()->attendee()
1029
-            : null;
1030
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1031
-            'ee_edit_payments',
1032
-            'apply_payment_or_refund_from_registration_details'
1033
-        );
1034
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1035
-            'ee_delete_payments',
1036
-            'delete_payment_from_registration_details'
1037
-        );
1038
-
1039
-        // get line table
1040
-        EEH_Autoloader::register_line_item_display_autoloaders();
1041
-        $Line_Item_Display = new EE_Line_Item_Display(
1042
-            'admin_table',
1043
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1044
-        );
1045
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1046
-            $this->_transaction->total_line_item()
1047
-        );
1048
-        $this->_template_args['REG_code'] = $this->_transaction->primary_registration()->reg_code();
1049
-
1050
-        // process taxes
1051
-        $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1052
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1053
-
1054
-        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1055
-            $this->_transaction->total(),
1056
-            false,
1057
-            false
1058
-        );
1059
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1060
-        $this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1061
-
1062
-        // process payment details
1063
-        $payments = $this->_transaction->payments();
1064
-        if (! empty($payments)) {
1065
-            $this->_template_args['payments'] = $payments;
1066
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1067
-        } else {
1068
-            $this->_template_args['payments'] = false;
1069
-            $this->_template_args['existing_reg_payments'] = array();
1070
-        }
1071
-
1072
-        $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1073
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1074
-            array('action' => 'espresso_delete_payment'),
1075
-            TXN_ADMIN_URL
1076
-        );
1077
-
1078
-        if (isset($txn_details['invoice_number'])) {
1079
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1080
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1081
-                'Invoice Number',
1082
-                'event_espresso'
1083
-            );
1084
-        }
1085
-
1086
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1087
-            ->primary_registration()
1088
-            ->session_ID();
1089
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1090
-            'Registration Session',
1091
-            'event_espresso'
1092
-        );
1093
-
1094
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1095
-            ? $this->_session['ip_address']
1096
-            : '';
1097
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1098
-            'Transaction placed from IP',
1099
-            'event_espresso'
1100
-        );
1101
-
1102
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1103
-            ? $this->_session['user_agent']
1104
-            : '';
1105
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1106
-            'Registrant User Agent',
1107
-            'event_espresso'
1108
-        );
1109
-
1110
-        $reg_steps = '<ul>';
1111
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1112
-            if ($reg_step_status === true) {
1113
-                $reg_steps .= '<li style="color:#70cc50">'
1114
-                              . sprintf(
1115
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1116
-                                  ucwords(str_replace('_', ' ', $reg_step))
1117
-                              )
1118
-                              . '</li>';
1119
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1120
-                $reg_steps .= '<li style="color:#2EA2CC">'
1121
-                              . sprintf(
1122
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1123
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1124
-                                  date(
1125
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1126
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1127
-                                  )
1128
-                              )
1129
-                              . '</li>';
1130
-            } else {
1131
-                $reg_steps .= '<li style="color:#E76700">'
1132
-                              . sprintf(
1133
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1134
-                                  ucwords(str_replace('_', ' ', $reg_step))
1135
-                              )
1136
-                              . '</li>';
1137
-            }
1138
-        }
1139
-        $reg_steps .= '</ul>';
1140
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1141
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1142
-            'Registration Step Progress',
1143
-            'event_espresso'
1144
-        );
1145
-
1146
-
1147
-        $this->_get_registrations_to_apply_payment_to();
1148
-        $this->_get_payment_methods($payments);
1149
-        $this->_get_payment_status_array();
1150
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1151
-
1152
-        $this->_template_args['transaction_form_url'] = add_query_arg(
1153
-            array(
1154
-                'action'  => 'edit_transaction',
1155
-                'process' => 'transaction',
1156
-            ),
1157
-            TXN_ADMIN_URL
1158
-        );
1159
-        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1160
-            array(
1161
-                'page'   => 'espresso_transactions',
1162
-                'action' => 'espresso_apply_payment',
1163
-            ),
1164
-            WP_AJAX_URL
1165
-        );
1166
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1167
-            array(
1168
-                'page'   => 'espresso_transactions',
1169
-                'action' => 'espresso_delete_payment',
1170
-            ),
1171
-            WP_AJAX_URL
1172
-        );
1173
-
1174
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1175
-
1176
-        // 'espresso_delete_payment_nonce'
1177
-
1178
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1179
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1180
-    }
1181
-
1182
-
1183
-    /**
1184
-     * _get_registration_payment_IDs
1185
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1186
-     *
1187
-     * @access protected
1188
-     * @param EE_Payment[] $payments
1189
-     * @return array
1190
-     * @throws EE_Error
1191
-     * @throws InvalidArgumentException
1192
-     * @throws InvalidDataTypeException
1193
-     * @throws InvalidInterfaceException
1194
-     * @throws ReflectionException
1195
-     */
1196
-    protected function _get_registration_payment_IDs($payments = array())
1197
-    {
1198
-        $existing_reg_payments = array();
1199
-        // get all reg payments for these payments
1200
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1201
-            array(
1202
-                array(
1203
-                    'PAY_ID' => array(
1204
-                        'IN',
1205
-                        array_keys($payments),
1206
-                    ),
1207
-                ),
1208
-            )
1209
-        );
1210
-        if (! empty($reg_payments)) {
1211
-            foreach ($payments as $payment) {
1212
-                if (! $payment instanceof EE_Payment) {
1213
-                    continue;
1214
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1215
-                    $existing_reg_payments[ $payment->ID() ] = array();
1216
-                }
1217
-                foreach ($reg_payments as $reg_payment) {
1218
-                    if ($reg_payment instanceof EE_Registration_Payment
1219
-                        && $reg_payment->payment_ID() === $payment->ID()
1220
-                    ) {
1221
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1222
-                    }
1223
-                }
1224
-            }
1225
-        }
1226
-
1227
-        return $existing_reg_payments;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * _get_registrations_to_apply_payment_to
1233
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1234
-     * which allows the admin to only apply the payment to the specific registrations
1235
-     *
1236
-     * @access protected
1237
-     * @return void
1238
-     * @throws EE_Error
1239
-     * @throws InvalidArgumentException
1240
-     * @throws InvalidDataTypeException
1241
-     * @throws InvalidInterfaceException
1242
-     * @throws ReflectionException
1243
-     */
1244
-    protected function _get_registrations_to_apply_payment_to()
1245
-    {
1246
-        // we want any registration with an active status (ie: not deleted or cancelled)
1247
-        $query_params = array(
1248
-            array(
1249
-                'STS_ID' => array(
1250
-                    'IN',
1251
-                    array(
1252
-                        EEM_Registration::status_id_approved,
1253
-                        EEM_Registration::status_id_pending_payment,
1254
-                        EEM_Registration::status_id_not_approved,
1255
-                    ),
1256
-                ),
1257
-            ),
1258
-        );
1259
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1260
-            '',
1261
-            'txn-admin-apply-payment-to-registrations-dv',
1262
-            '',
1263
-            'clear: both; margin: 1.5em 0 0; display: none;'
1264
-        );
1265
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1266
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1267
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1268
-            EEH_HTML::tr(
1269
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1270
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1271
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1272
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1273
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1274
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1275
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1276
-            )
1277
-        );
1278
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1279
-        // get registrations for TXN
1280
-        $registrations = $this->_transaction->registrations($query_params);
1281
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1282
-        foreach ($registrations as $registration) {
1283
-            if ($registration instanceof EE_Registration) {
1284
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
1285
-                    ? $registration->attendee()->full_name()
1286
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1287
-                $owing = $registration->final_price() - $registration->paid();
1288
-                $taxable = $registration->ticket()->taxable()
1289
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1290
-                    : '';
1291
-                $checked = empty($existing_reg_payments)
1292
-                           || in_array($registration->ID(), $existing_reg_payments, true)
1293
-                    ? ' checked="checked"'
1294
-                    : '';
1295
-                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1296
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1297
-                    EEH_HTML::td($registration->ID()) .
1298
-                    EEH_HTML::td($attendee_name) .
1299
-                    EEH_HTML::td(
1300
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1301
-                    ) .
1302
-                    EEH_HTML::td($registration->event_name()) .
1303
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1304
-                    EEH_HTML::td(
1305
-                        EEH_Template::format_currency($owing),
1306
-                        '',
1307
-                        'txn-admin-payment-owing-td jst-cntr'
1308
-                    ) .
1309
-                    EEH_HTML::td(
1310
-                        '<input type="checkbox" value="' . $registration->ID()
1311
-                        . '" name="txn_admin_payment[registrations]"'
1312
-                        . $checked . $disabled . '>',
1313
-                        '',
1314
-                        'jst-cntr'
1315
-                    ),
1316
-                    'apply-payment-registration-row-' . $registration->ID()
1317
-                );
1318
-            }
1319
-        }
1320
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1321
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1322
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1323
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1324
-            esc_html__(
1325
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1326
-                'event_espresso'
1327
-            ),
1328
-            '',
1329
-            'clear description'
1330
-        );
1331
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1332
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1333
-    }
1334
-
1335
-
1336
-    /**
1337
-     * _get_reg_status_selection
1338
-     *
1339
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1340
-     *         instead of events.
1341
-     * @access protected
1342
-     * @return void
1343
-     * @throws EE_Error
1344
-     */
1345
-    protected function _get_reg_status_selection()
1346
-    {
1347
-        // first get all possible statuses
1348
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1349
-        // let's add a "don't change" option.
1350
-        $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1351
-        $status_array = array_merge($status_array, $statuses);
1352
-        $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1353
-            'txn_reg_status_change[reg_status]',
1354
-            $status_array,
1355
-            'NAN',
1356
-            'id="txn-admin-payment-reg-status-inp"',
1357
-            'txn-reg-status-change-reg-status'
1358
-        );
1359
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1360
-            'delete_txn_reg_status_change[reg_status]',
1361
-            $status_array,
1362
-            'NAN',
1363
-            'delete-txn-admin-payment-reg-status-inp',
1364
-            'delete-txn-reg-status-change-reg-status'
1365
-        );
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     *    _get_payment_methods
1371
-     * Gets all the payment methods available generally, or the ones that are already
1372
-     * selected on these payments (in case their payment methods are no longer active).
1373
-     * Has the side-effect of updating the template args' payment_methods item
1374
-     *
1375
-     * @access private
1376
-     * @param EE_Payment[] to show on this page
1377
-     * @return void
1378
-     * @throws EE_Error
1379
-     * @throws InvalidArgumentException
1380
-     * @throws InvalidDataTypeException
1381
-     * @throws InvalidInterfaceException
1382
-     * @throws ReflectionException
1383
-     */
1384
-    private function _get_payment_methods($payments = array())
1385
-    {
1386
-        $payment_methods_of_payments = array();
1387
-        foreach ($payments as $payment) {
1388
-            if ($payment instanceof EE_Payment) {
1389
-                $payment_methods_of_payments[] = $payment->ID();
1390
-            }
1391
-        }
1392
-        if ($payment_methods_of_payments) {
1393
-            $query_args = array(
1394
-                array(
1395
-                    'OR*payment_method_for_payment' => array(
1396
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1397
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1398
-                    ),
1399
-                ),
1400
-            );
1401
-        } else {
1402
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1403
-        }
1404
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1405
-    }
1406
-
1407
-
1408
-    /**
1409
-     * txn_attendees_meta_box
1410
-     *    generates HTML for the Attendees Transaction main meta box
1411
-     *
1412
-     * @access public
1413
-     * @param WP_Post $post
1414
-     * @param array   $metabox
1415
-     * @return void
1416
-     * @throws DomainException
1417
-     * @throws EE_Error
1418
-     * @throws InvalidArgumentException
1419
-     * @throws InvalidDataTypeException
1420
-     * @throws InvalidInterfaceException
1421
-     * @throws ReflectionException
1422
-     */
1423
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1424
-    {
1425
-
1426
-        /** @noinspection NonSecureExtractUsageInspection */
1427
-        extract($metabox['args']);
1428
-        $this->_template_args['post'] = $post;
1429
-        $this->_template_args['event_attendees'] = array();
1430
-        // process items in cart
1431
-        $line_items = $this->_transaction->get_many_related(
1432
-            'Line_Item',
1433
-            array(array('LIN_type' => 'line-item'))
1434
-        );
1435
-        if (! empty($line_items)) {
1436
-            foreach ($line_items as $item) {
1437
-                if ($item instanceof EE_Line_Item) {
1438
-                    switch ($item->OBJ_type()) {
1439
-                        case 'Event':
1440
-                            break;
1441
-                        case 'Ticket':
1442
-                            $ticket = $item->ticket();
1443
-                            // right now we're only handling tickets here.
1444
-                            // Cause its expected that only tickets will have attendees right?
1445
-                            if (! $ticket instanceof EE_Ticket) {
1446
-                                break;
1447
-                            }
1448
-                            try {
1449
-                                $event_name = $ticket->get_event_name();
1450
-                            } catch (Exception $e) {
1451
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1452
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1453
-                            }
1454
-                            $event_name .= ' - ' . $item->name();
1455
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1456
-                            // now get all of the registrations for this transaction that use this ticket
1457
-                            $registrations = $ticket->registrations(
1458
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1459
-                            );
1460
-                            foreach ($registrations as $registration) {
1461
-                                if (! $registration instanceof EE_Registration) {
1462
-                                    break;
1463
-                                }
1464
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1465
-                                    = $registration->status_ID();
1466
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1467
-                                    = $registration->count();
1468
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1469
-                                    = $event_name;
1470
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1471
-                                    = $ticket_price;
1472
-                                // attendee info
1473
-                                $attendee = $registration->get_first_related('Attendee');
1474
-                                if ($attendee instanceof EE_Attendee) {
1475
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1476
-                                        = $attendee->ID();
1477
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1478
-                                        = $attendee->full_name();
1479
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1480
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1481
-                                          . esc_html__(
1482
-                                              ' Event',
1483
-                                              'event_espresso'
1484
-                                          )
1485
-                                          . '">' . $attendee->email() . '</a>';
1486
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1487
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1488
-                                } else {
1489
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1490
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1491
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1492
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1493
-                                }
1494
-                            }
1495
-                            break;
1496
-                    }
1497
-                }
1498
-            }
1499
-
1500
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1501
-                array(
1502
-                    'action'  => 'edit_transaction',
1503
-                    'process' => 'attendees',
1504
-                ),
1505
-                TXN_ADMIN_URL
1506
-            );
1507
-            echo EEH_Template::display_template(
1508
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1509
-                $this->_template_args,
1510
-                true
1511
-            );
1512
-        } else {
1513
-            echo sprintf(
1514
-                esc_html__(
1515
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1516
-                    'event_espresso'
1517
-                ),
1518
-                '<p class="important-notice">',
1519
-                '</p>'
1520
-            );
1521
-        }
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * txn_registrant_side_meta_box
1527
-     * generates HTML for the Edit Transaction side meta box
1528
-     *
1529
-     * @access public
1530
-     * @return void
1531
-     * @throws DomainException
1532
-     * @throws EE_Error
1533
-     * @throws InvalidArgumentException
1534
-     * @throws InvalidDataTypeException
1535
-     * @throws InvalidInterfaceException
1536
-     * @throws ReflectionException
1537
-     */
1538
-    public function txn_registrant_side_meta_box()
1539
-    {
1540
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1541
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1542
-            : null;
1543
-        if (! $primary_att instanceof EE_Attendee) {
1544
-            $this->_template_args['no_attendee_message'] = esc_html__(
1545
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1546
-                'event_espresso'
1547
-            );
1548
-            $primary_att = EEM_Attendee::instance()->create_default_object();
1549
-        }
1550
-        $this->_template_args['ATT_ID'] = $primary_att->ID();
1551
-        $this->_template_args['prime_reg_fname'] = $primary_att->fname();
1552
-        $this->_template_args['prime_reg_lname'] = $primary_att->lname();
1553
-        $this->_template_args['prime_reg_email'] = $primary_att->email();
1554
-        $this->_template_args['prime_reg_phone'] = $primary_att->phone();
1555
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1556
-            array(
1557
-                'action' => 'edit_attendee',
1558
-                'post'   => $primary_att->ID(),
1559
-            ),
1560
-            REG_ADMIN_URL
1561
-        );
1562
-        // get formatted address for registrant
1563
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1564
-        echo EEH_Template::display_template(
1565
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1566
-            $this->_template_args,
1567
-            true
1568
-        );
1569
-    }
1570
-
1571
-
1572
-    /**
1573
-     * txn_billing_info_side_meta_box
1574
-     *    generates HTML for the Edit Transaction side meta box
1575
-     *
1576
-     * @access public
1577
-     * @return void
1578
-     * @throws DomainException
1579
-     * @throws EE_Error
1580
-     */
1581
-    public function txn_billing_info_side_meta_box()
1582
-    {
1583
-
1584
-        $this->_template_args['billing_form'] = $this->_transaction->billing_info();
1585
-        $this->_template_args['billing_form_url'] = add_query_arg(
1586
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1587
-            TXN_ADMIN_URL
1588
-        );
1589
-
1590
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1591
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1592
-    }
1593
-
1594
-
1595
-    /**
1596
-     * apply_payments_or_refunds
1597
-     *    registers a payment or refund made towards a transaction
1598
-     *
1599
-     * @access public
1600
-     * @return void
1601
-     * @throws EE_Error
1602
-     * @throws InvalidArgumentException
1603
-     * @throws ReflectionException
1604
-     * @throws RuntimeException
1605
-     * @throws InvalidDataTypeException
1606
-     * @throws InvalidInterfaceException
1607
-     */
1608
-    public function apply_payments_or_refunds()
1609
-    {
1610
-        $json_response_data = array('return_data' => false);
1611
-        $valid_data = $this->_validate_payment_request_data();
1612
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1613
-            'ee_edit_payments',
1614
-            'apply_payment_or_refund_from_registration_details'
1615
-        );
1616
-        if (! empty($valid_data) && $has_access) {
1617
-            $PAY_ID = $valid_data['PAY_ID'];
1618
-            // save  the new payment
1619
-            $payment = $this->_create_payment_from_request_data($valid_data);
1620
-            // get the TXN for this payment
1621
-            $transaction = $payment->transaction();
1622
-            // verify transaction
1623
-            if ($transaction instanceof EE_Transaction) {
1624
-                // calculate_total_payments_and_update_status
1625
-                $this->_process_transaction_payments($transaction);
1626
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1627
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1628
-                // apply payment to registrations (if applicable)
1629
-                if (! empty($REG_IDs)) {
1630
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1631
-                    $this->_maybe_send_notifications();
1632
-                    // now process status changes for the same registrations
1633
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1634
-                }
1635
-                $this->_maybe_send_notifications($payment);
1636
-                // prepare to render page
1637
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1638
-                do_action(
1639
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1640
-                    $transaction,
1641
-                    $payment
1642
-                );
1643
-            } else {
1644
-                EE_Error::add_error(
1645
-                    esc_html__(
1646
-                        'A valid Transaction for this payment could not be retrieved.',
1647
-                        'event_espresso'
1648
-                    ),
1649
-                    __FILE__,
1650
-                    __FUNCTION__,
1651
-                    __LINE__
1652
-                );
1653
-            }
1654
-        } elseif ($has_access) {
1655
-            EE_Error::add_error(
1656
-                esc_html__(
1657
-                    'The payment form data could not be processed. Please try again.',
1658
-                    'event_espresso'
1659
-                ),
1660
-                __FILE__,
1661
-                __FUNCTION__,
1662
-                __LINE__
1663
-            );
1664
-        } else {
1665
-            EE_Error::add_error(
1666
-                esc_html__(
1667
-                    'You do not have access to apply payments or refunds to a registration.',
1668
-                    'event_espresso'
1669
-                ),
1670
-                __FILE__,
1671
-                __FUNCTION__,
1672
-                __LINE__
1673
-            );
1674
-        }
1675
-        $notices = EE_Error::get_notices(
1676
-            false,
1677
-            false,
1678
-            false
1679
-        );
1680
-        $this->_template_args = array(
1681
-            'data'    => $json_response_data,
1682
-            'error'   => $notices['errors'],
1683
-            'success' => $notices['success'],
1684
-        );
1685
-        $this->_return_json();
1686
-    }
1687
-
1688
-
1689
-    /**
1690
-     * _validate_payment_request_data
1691
-     *
1692
-     * @return array
1693
-     * @throws EE_Error
1694
-     * @throws InvalidArgumentException
1695
-     * @throws InvalidDataTypeException
1696
-     * @throws InvalidInterfaceException
1697
-     */
1698
-    protected function _validate_payment_request_data()
1699
-    {
1700
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1701
-            return array();
1702
-        }
1703
-        $payment_form = $this->_generate_payment_form_section();
1704
-        try {
1705
-            if ($payment_form->was_submitted()) {
1706
-                $payment_form->receive_form_submission();
1707
-                if (! $payment_form->is_valid()) {
1708
-                    $submission_error_messages = array();
1709
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1710
-                        if ($validation_error instanceof EE_Validation_Error) {
1711
-                            $submission_error_messages[] = sprintf(
1712
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1713
-                                $validation_error->get_form_section()->html_label_text(),
1714
-                                $validation_error->getMessage()
1715
-                            );
1716
-                        }
1717
-                    }
1718
-                    EE_Error::add_error(
1719
-                        implode('<br />', $submission_error_messages),
1720
-                        __FILE__,
1721
-                        __FUNCTION__,
1722
-                        __LINE__
1723
-                    );
1724
-                    return array();
1725
-                }
1726
-            }
1727
-        } catch (EE_Error $e) {
1728
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1729
-            return array();
1730
-        }
1731
-
1732
-        return $payment_form->valid_data();
1733
-    }
1734
-
1735
-
1736
-    /**
1737
-     * _generate_payment_form_section
1738
-     *
1739
-     * @return EE_Form_Section_Proper
1740
-     * @throws EE_Error
1741
-     */
1742
-    protected function _generate_payment_form_section()
1743
-    {
1744
-        return new EE_Form_Section_Proper(
1745
-            array(
1746
-                'name'        => 'txn_admin_payment',
1747
-                'subsections' => array(
1748
-                    'PAY_ID'          => new EE_Text_Input(
1749
-                        array(
1750
-                            'default'               => 0,
1751
-                            'required'              => false,
1752
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1753
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1754
-                        )
1755
-                    ),
1756
-                    'TXN_ID'          => new EE_Text_Input(
1757
-                        array(
1758
-                            'default'               => 0,
1759
-                            'required'              => true,
1760
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1761
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1762
-                        )
1763
-                    ),
1764
-                    'type'            => new EE_Text_Input(
1765
-                        array(
1766
-                            'default'               => 1,
1767
-                            'required'              => true,
1768
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1769
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1770
-                        )
1771
-                    ),
1772
-                    'amount'          => new EE_Text_Input(
1773
-                        array(
1774
-                            'default'               => 0,
1775
-                            'required'              => true,
1776
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1777
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1778
-                        )
1779
-                    ),
1780
-                    'status'          => new EE_Text_Input(
1781
-                        array(
1782
-                            'default'         => EEM_Payment::status_id_approved,
1783
-                            'required'        => true,
1784
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1785
-                        )
1786
-                    ),
1787
-                    'PMD_ID'          => new EE_Text_Input(
1788
-                        array(
1789
-                            'default'               => 2,
1790
-                            'required'              => true,
1791
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1792
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1793
-                        )
1794
-                    ),
1795
-                    'date'            => new EE_Text_Input(
1796
-                        array(
1797
-                            'default'         => time(),
1798
-                            'required'        => true,
1799
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1800
-                        )
1801
-                    ),
1802
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1803
-                        array(
1804
-                            'default'               => '',
1805
-                            'required'              => false,
1806
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1807
-                            'validation_strategies' => array(
1808
-                                new EE_Max_Length_Validation_Strategy(
1809
-                                    esc_html__('Input too long', 'event_espresso'),
1810
-                                    100
1811
-                                ),
1812
-                            ),
1813
-                        )
1814
-                    ),
1815
-                    'po_number'       => new EE_Text_Input(
1816
-                        array(
1817
-                            'default'               => '',
1818
-                            'required'              => false,
1819
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1820
-                            'validation_strategies' => array(
1821
-                                new EE_Max_Length_Validation_Strategy(
1822
-                                    esc_html__('Input too long', 'event_espresso'),
1823
-                                    100
1824
-                                ),
1825
-                            ),
1826
-                        )
1827
-                    ),
1828
-                    'accounting'      => new EE_Text_Input(
1829
-                        array(
1830
-                            'default'               => '',
1831
-                            'required'              => false,
1832
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1833
-                            'validation_strategies' => array(
1834
-                                new EE_Max_Length_Validation_Strategy(
1835
-                                    esc_html__('Input too long', 'event_espresso'),
1836
-                                    100
1837
-                                ),
1838
-                            ),
1839
-                        )
1840
-                    ),
1841
-                ),
1842
-            )
1843
-        );
1844
-    }
1845
-
1846
-
1847
-    /**
1848
-     * _create_payment_from_request_data
1849
-     *
1850
-     * @param array $valid_data
1851
-     * @return EE_Payment
1852
-     * @throws EE_Error
1853
-     * @throws InvalidArgumentException
1854
-     * @throws InvalidDataTypeException
1855
-     * @throws InvalidInterfaceException
1856
-     * @throws ReflectionException
1857
-     */
1858
-    protected function _create_payment_from_request_data($valid_data)
1859
-    {
1860
-        $PAY_ID = $valid_data['PAY_ID'];
1861
-        // get payment amount
1862
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1863
-        // payments have a type value of 1 and refunds have a type value of -1
1864
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1865
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1866
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1867
-        $date = $valid_data['date']
1868
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1869
-            : date('Y-m-d g:i a', current_time('timestamp'));
1870
-        $payment = EE_Payment::new_instance(
1871
-            array(
1872
-                'TXN_ID'              => $valid_data['TXN_ID'],
1873
-                'STS_ID'              => $valid_data['status'],
1874
-                'PAY_timestamp'       => $date,
1875
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1876
-                'PMD_ID'              => $valid_data['PMD_ID'],
1877
-                'PAY_amount'          => $amount,
1878
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1879
-                'PAY_po_number'       => $valid_data['po_number'],
1880
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1881
-                'PAY_details'         => $valid_data,
1882
-                'PAY_ID'              => $PAY_ID,
1883
-            ),
1884
-            '',
1885
-            array('Y-m-d', 'g:i a')
1886
-        );
1887
-
1888
-        if (! $payment->save()) {
1889
-            EE_Error::add_error(
1890
-                sprintf(
1891
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1892
-                    $payment->ID()
1893
-                ),
1894
-                __FILE__,
1895
-                __FUNCTION__,
1896
-                __LINE__
1897
-            );
1898
-        }
1899
-
1900
-        return $payment;
1901
-    }
1902
-
1903
-
1904
-    /**
1905
-     * _process_transaction_payments
1906
-     *
1907
-     * @param \EE_Transaction $transaction
1908
-     * @return void
1909
-     * @throws EE_Error
1910
-     * @throws InvalidArgumentException
1911
-     * @throws ReflectionException
1912
-     * @throws InvalidDataTypeException
1913
-     * @throws InvalidInterfaceException
1914
-     */
1915
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1916
-    {
1917
-        /** @type EE_Transaction_Payments $transaction_payments */
1918
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1919
-        // update the transaction with this payment
1920
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1921
-            EE_Error::add_success(
1922
-                esc_html__(
1923
-                    'The payment has been processed successfully.',
1924
-                    'event_espresso'
1925
-                ),
1926
-                __FILE__,
1927
-                __FUNCTION__,
1928
-                __LINE__
1929
-            );
1930
-        } else {
1931
-            EE_Error::add_error(
1932
-                esc_html__(
1933
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1934
-                    'event_espresso'
1935
-                ),
1936
-                __FILE__,
1937
-                __FUNCTION__,
1938
-                __LINE__
1939
-            );
1940
-        }
1941
-    }
1942
-
1943
-
1944
-    /**
1945
-     * _get_REG_IDs_to_apply_payment_to
1946
-     * returns a list of registration IDs that the payment will apply to
1947
-     *
1948
-     * @param \EE_Payment $payment
1949
-     * @return array
1950
-     * @throws EE_Error
1951
-     * @throws InvalidArgumentException
1952
-     * @throws InvalidDataTypeException
1953
-     * @throws InvalidInterfaceException
1954
-     * @throws ReflectionException
1955
-     */
1956
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1957
-    {
1958
-        $REG_IDs = array();
1959
-        // grab array of IDs for specific registrations to apply changes to
1960
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1961
-            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1962
-        }
1963
-        // nothing specified ? then get all reg IDs
1964
-        if (empty($REG_IDs)) {
1965
-            $registrations = $payment->transaction()->registrations();
1966
-            $REG_IDs = ! empty($registrations)
1967
-                ? array_keys($registrations)
1968
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1969
-        }
1970
-
1971
-        // ensure that REG_IDs are integers and NOT strings
1972
-        return array_map('intval', $REG_IDs);
1973
-    }
1974
-
1975
-
1976
-    /**
1977
-     * @return array
1978
-     */
1979
-    public function existing_reg_payment_REG_IDs()
1980
-    {
1981
-        return $this->_existing_reg_payment_REG_IDs;
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * @param array $existing_reg_payment_REG_IDs
1987
-     */
1988
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1989
-    {
1990
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1991
-    }
1992
-
1993
-
1994
-    /**
1995
-     * _get_existing_reg_payment_REG_IDs
1996
-     * returns a list of registration IDs that the payment is currently related to
1997
-     * as recorded in the database
1998
-     *
1999
-     * @param \EE_Payment $payment
2000
-     * @return array
2001
-     * @throws EE_Error
2002
-     * @throws InvalidArgumentException
2003
-     * @throws InvalidDataTypeException
2004
-     * @throws InvalidInterfaceException
2005
-     * @throws ReflectionException
2006
-     */
2007
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2008
-    {
2009
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2010
-            // let's get any existing reg payment records for this payment
2011
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2012
-            // but we only want the REG IDs, so grab the array keys
2013
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2014
-                ? array_keys($existing_reg_payment_REG_IDs)
2015
-                : array();
2016
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2017
-        }
2018
-
2019
-        return $this->existing_reg_payment_REG_IDs();
2020
-    }
2021
-
2022
-
2023
-    /**
2024
-     * _remove_existing_registration_payments
2025
-     * this calculates the difference between existing relations
2026
-     * to the supplied payment and the new list registration IDs,
2027
-     * removes any related registrations that no longer apply,
2028
-     * and then updates the registration paid fields
2029
-     *
2030
-     * @param \EE_Payment $payment
2031
-     * @param int         $PAY_ID
2032
-     * @return bool;
2033
-     * @throws EE_Error
2034
-     * @throws InvalidArgumentException
2035
-     * @throws ReflectionException
2036
-     * @throws InvalidDataTypeException
2037
-     * @throws InvalidInterfaceException
2038
-     */
2039
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2040
-    {
2041
-        // newly created payments will have nothing recorded for $PAY_ID
2042
-        if (absint($PAY_ID) === 0) {
2043
-            return false;
2044
-        }
2045
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2046
-        if (empty($existing_reg_payment_REG_IDs)) {
2047
-            return false;
2048
-        }
2049
-        /** @type EE_Transaction_Payments $transaction_payments */
2050
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2051
-
2052
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2053
-            $payment,
2054
-            array(
2055
-                array(
2056
-                    'PAY_ID' => $payment->ID(),
2057
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2058
-                ),
2059
-            )
2060
-        );
2061
-    }
2062
-
2063
-
2064
-    /**
2065
-     * _update_registration_payments
2066
-     * this applies the payments to the selected registrations
2067
-     * but only if they have not already been paid for
2068
-     *
2069
-     * @param  EE_Transaction $transaction
2070
-     * @param \EE_Payment     $payment
2071
-     * @param array           $REG_IDs
2072
-     * @return void
2073
-     * @throws EE_Error
2074
-     * @throws InvalidArgumentException
2075
-     * @throws ReflectionException
2076
-     * @throws RuntimeException
2077
-     * @throws InvalidDataTypeException
2078
-     * @throws InvalidInterfaceException
2079
-     */
2080
-    protected function _update_registration_payments(
2081
-        EE_Transaction $transaction,
2082
-        EE_Payment $payment,
2083
-        $REG_IDs = array()
2084
-    ) {
2085
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2086
-        // so let's do that using our set of REG_IDs from the form
2087
-        $registration_query_where_params = array(
2088
-            'REG_ID' => array('IN', $REG_IDs),
2089
-        );
2090
-        // but add in some conditions regarding payment,
2091
-        // so that we don't apply payments to registrations that are free or have already been paid for
2092
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2093
-        if (! $payment->is_a_refund()) {
2094
-            $registration_query_where_params['REG_final_price'] = array('!=', 0);
2095
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2096
-        }
2097
-        $registrations = $transaction->registrations(array($registration_query_where_params));
2098
-        if (! empty($registrations)) {
2099
-            /** @type EE_Payment_Processor $payment_processor */
2100
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2101
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2102
-        }
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * _process_registration_status_change
2108
-     * This processes requested registration status changes for all the registrations
2109
-     * on a given transaction and (optionally) sends out notifications for the changes.
2110
-     *
2111
-     * @param  EE_Transaction $transaction
2112
-     * @param array           $REG_IDs
2113
-     * @return bool
2114
-     * @throws EE_Error
2115
-     * @throws InvalidArgumentException
2116
-     * @throws ReflectionException
2117
-     * @throws InvalidDataTypeException
2118
-     * @throws InvalidInterfaceException
2119
-     */
2120
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2121
-    {
2122
-        // first if there is no change in status then we get out.
2123
-        if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2124
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2125
-        ) {
2126
-            // no error message, no change requested, just nothing to do man.
2127
-            return false;
2128
-        }
2129
-        /** @type EE_Transaction_Processor $transaction_processor */
2130
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2131
-
2132
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2133
-        return $transaction_processor->manually_update_registration_statuses(
2134
-            $transaction,
2135
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2136
-            array(array('REG_ID' => array('IN', $REG_IDs)))
2137
-        );
2138
-    }
2139
-
2140
-
2141
-    /**
2142
-     * _build_payment_json_response
2143
-     *
2144
-     * @access public
2145
-     * @param \EE_Payment $payment
2146
-     * @param array       $REG_IDs
2147
-     * @param bool | null $delete_txn_reg_status_change
2148
-     * @return array
2149
-     * @throws EE_Error
2150
-     * @throws InvalidArgumentException
2151
-     * @throws InvalidDataTypeException
2152
-     * @throws InvalidInterfaceException
2153
-     * @throws ReflectionException
2154
-     */
2155
-    protected function _build_payment_json_response(
2156
-        EE_Payment $payment,
2157
-        $REG_IDs = array(),
2158
-        $delete_txn_reg_status_change = null
2159
-    ) {
2160
-        // was the payment deleted ?
2161
-        if (is_bool($delete_txn_reg_status_change)) {
2162
-            return array(
2163
-                'PAY_ID'                       => $payment->ID(),
2164
-                'amount'                       => $payment->amount(),
2165
-                'total_paid'                   => $payment->transaction()->paid(),
2166
-                'txn_status'                   => $payment->transaction()->status_ID(),
2167
-                'pay_status'                   => $payment->STS_ID(),
2168
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2169
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2170
-            );
2171
-        } else {
2172
-            $this->_get_payment_status_array();
2173
-
2174
-            return array(
2175
-                'amount'           => $payment->amount(),
2176
-                'total_paid'       => $payment->transaction()->paid(),
2177
-                'txn_status'       => $payment->transaction()->status_ID(),
2178
-                'pay_status'       => $payment->STS_ID(),
2179
-                'PAY_ID'           => $payment->ID(),
2180
-                'STS_ID'           => $payment->STS_ID(),
2181
-                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2182
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2183
-                'method'           => strtoupper($payment->source()),
2184
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2185
-                'gateway'          => $payment->payment_method()
2186
-                    ? $payment->payment_method()->admin_name()
2187
-                    : esc_html__('Unknown', 'event_espresso'),
2188
-                'gateway_response' => $payment->gateway_response(),
2189
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2190
-                'po_number'        => $payment->po_number(),
2191
-                'extra_accntng'    => $payment->extra_accntng(),
2192
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2193
-            );
2194
-        }
2195
-    }
2196
-
2197
-
2198
-    /**
2199
-     * delete_payment
2200
-     *    delete a payment or refund made towards a transaction
2201
-     *
2202
-     * @access public
2203
-     * @return void
2204
-     * @throws EE_Error
2205
-     * @throws InvalidArgumentException
2206
-     * @throws ReflectionException
2207
-     * @throws InvalidDataTypeException
2208
-     * @throws InvalidInterfaceException
2209
-     */
2210
-    public function delete_payment()
2211
-    {
2212
-        $json_response_data = array('return_data' => false);
2213
-        $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2214
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2215
-            : 0;
2216
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2217
-            'ee_delete_payments',
2218
-            'delete_payment_from_registration_details'
2219
-        );
2220
-        if ($PAY_ID && $can_delete) {
2221
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2222
-                ? $this->_req_data['delete_txn_reg_status_change']
2223
-                : false;
2224
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2225
-            if ($payment instanceof EE_Payment) {
2226
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2227
-                /** @type EE_Transaction_Payments $transaction_payments */
2228
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2229
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2230
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2231
-                        $payment,
2232
-                        $REG_IDs,
2233
-                        $delete_txn_reg_status_change
2234
-                    );
2235
-                    if ($delete_txn_reg_status_change) {
2236
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2237
-                        // MAKE sure we also add the delete_txn_req_status_change to the
2238
-                        // $_REQUEST global because that's how messages will be looking for it.
2239
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2240
-                        $this->_maybe_send_notifications();
2241
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2242
-                    }
2243
-                }
2244
-            } else {
2245
-                EE_Error::add_error(
2246
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2247
-                    __FILE__,
2248
-                    __FUNCTION__,
2249
-                    __LINE__
2250
-                );
2251
-            }
2252
-        } elseif ($can_delete) {
2253
-            EE_Error::add_error(
2254
-                esc_html__(
2255
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2256
-                    'event_espresso'
2257
-                ),
2258
-                __FILE__,
2259
-                __FUNCTION__,
2260
-                __LINE__
2261
-            );
2262
-        } else {
2263
-            EE_Error::add_error(
2264
-                esc_html__(
2265
-                    'You do not have access to delete a payment.',
2266
-                    'event_espresso'
2267
-                ),
2268
-                __FILE__,
2269
-                __FUNCTION__,
2270
-                __LINE__
2271
-            );
2272
-        }
2273
-        $notices = EE_Error::get_notices(false, false, false);
2274
-        $this->_template_args = array(
2275
-            'data'      => $json_response_data,
2276
-            'success'   => $notices['success'],
2277
-            'error'     => $notices['errors'],
2278
-            'attention' => $notices['attention'],
2279
-        );
2280
-        $this->_return_json();
2281
-    }
2282
-
2283
-
2284
-    /**
2285
-     * _registration_payment_data_array
2286
-     * adds info for 'owing' and 'paid' for each registration to the json response
2287
-     *
2288
-     * @access protected
2289
-     * @param array $REG_IDs
2290
-     * @return array
2291
-     * @throws EE_Error
2292
-     * @throws InvalidArgumentException
2293
-     * @throws InvalidDataTypeException
2294
-     * @throws InvalidInterfaceException
2295
-     * @throws ReflectionException
2296
-     */
2297
-    protected function _registration_payment_data_array($REG_IDs)
2298
-    {
2299
-        $registration_payment_data = array();
2300
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2301
-        if (! empty($REG_IDs)) {
2302
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2303
-            foreach ($registrations as $registration) {
2304
-                if ($registration instanceof EE_Registration) {
2305
-                    $registration_payment_data[ $registration->ID() ] = array(
2306
-                        'paid'  => $registration->pretty_paid(),
2307
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2308
-                    );
2309
-                }
2310
-            }
2311
-        }
2312
-
2313
-        return $registration_payment_data;
2314
-    }
2315
-
2316
-
2317
-    /**
2318
-     * _maybe_send_notifications
2319
-     * determines whether or not the admin has indicated that notifications should be sent.
2320
-     * If so, will toggle a filter switch for delivering registration notices.
2321
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2322
-     *
2323
-     * @access protected
2324
-     * @param \EE_Payment | null $payment
2325
-     */
2326
-    protected function _maybe_send_notifications($payment = null)
2327
-    {
2328
-        switch ($payment instanceof EE_Payment) {
2329
-            // payment notifications
2330
-            case true:
2331
-                if (isset($this->_req_data['txn_payments']['send_notifications'])
2332
-                    && filter_var(
2333
-                        $this->_req_data['txn_payments']['send_notifications'],
2334
-                        FILTER_VALIDATE_BOOLEAN
2335
-                    )
2336
-                ) {
2337
-                    $this->_process_payment_notification($payment);
2338
-                }
2339
-                break;
2340
-            // registration notifications
2341
-            case false:
2342
-                if (isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2343
-                    && filter_var(
2344
-                        $this->_req_data['txn_reg_status_change']['send_notifications'],
2345
-                        FILTER_VALIDATE_BOOLEAN
2346
-                    )
2347
-                ) {
2348
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2349
-                }
2350
-                break;
2351
-        }
2352
-    }
2353
-
2354
-
2355
-    /**
2356
-     * _send_payment_reminder
2357
-     *    generates HTML for the View Transaction Details Admin page
2358
-     *
2359
-     * @access protected
2360
-     * @return void
2361
-     * @throws EE_Error
2362
-     * @throws InvalidArgumentException
2363
-     * @throws InvalidDataTypeException
2364
-     * @throws InvalidInterfaceException
2365
-     */
2366
-    protected function _send_payment_reminder()
2367
-    {
2368
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2369
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2370
-        $query_args = isset($this->_req_data['redirect_to']) ? array(
2371
-            'action' => $this->_req_data['redirect_to'],
2372
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2373
-        ) : array();
2374
-        do_action(
2375
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2376
-            $transaction
2377
-        );
2378
-        $this->_redirect_after_action(
2379
-            false,
2380
-            esc_html__('payment reminder', 'event_espresso'),
2381
-            esc_html__('sent', 'event_espresso'),
2382
-            $query_args,
2383
-            true
2384
-        );
2385
-    }
2386
-
2387
-
2388
-    /**
2389
-     *  get_transactions
2390
-     *    get transactions for given parameters (used by list table)
2391
-     *
2392
-     * @param  int     $perpage how many transactions displayed per page
2393
-     * @param  boolean $count   return the count or objects
2394
-     * @param string   $view
2395
-     * @return mixed int = count || array of transaction objects
2396
-     * @throws EE_Error
2397
-     * @throws InvalidArgumentException
2398
-     * @throws InvalidDataTypeException
2399
-     * @throws InvalidInterfaceException
2400
-     */
2401
-    public function get_transactions($perpage, $count = false, $view = '')
2402
-    {
2403
-
2404
-        $TXN = EEM_Transaction::instance();
2405
-
2406
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2407
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2408
-            : date(
2409
-                'm/d/Y',
2410
-                strtotime('-10 year')
2411
-            );
2412
-        $end_date = isset($this->_req_data['txn-filter-end-date'])
2413
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2414
-            : date('m/d/Y');
2415
-
2416
-        // make sure our timestamps start and end right at the boundaries for each day
2417
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2418
-        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2419
-
2420
-
2421
-        // convert to timestamps
2422
-        $start_date = strtotime($start_date);
2423
-        $end_date = strtotime($end_date);
2424
-
2425
-        // makes sure start date is the lowest value and vice versa
2426
-        $start_date = min($start_date, $end_date);
2427
-        $end_date = max($start_date, $end_date);
2428
-
2429
-        // convert to correct format for query
2430
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2431
-            'TXN_timestamp',
2432
-            date('Y-m-d H:i:s', $start_date),
2433
-            'Y-m-d H:i:s'
2434
-        );
2435
-        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2436
-            'TXN_timestamp',
2437
-            date('Y-m-d H:i:s', $end_date),
2438
-            'Y-m-d H:i:s'
2439
-        );
2440
-
2441
-
2442
-        // set orderby
2443
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2444
-
2445
-        switch ($this->_req_data['orderby']) {
2446
-            case 'TXN_ID':
2447
-                $orderby = 'TXN_ID';
2448
-                break;
2449
-            case 'ATT_fname':
2450
-                $orderby = 'Registration.Attendee.ATT_fname';
2451
-                break;
2452
-            case 'event_name':
2453
-                $orderby = 'Registration.Event.EVT_name';
2454
-                break;
2455
-            default: // 'TXN_timestamp'
2456
-                $orderby = 'TXN_timestamp';
2457
-        }
2458
-
2459
-        $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2460
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2461
-        $per_page = ! empty($perpage) ? $perpage : 10;
2462
-        $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2463
-
2464
-        $offset = ($current_page - 1) * $per_page;
2465
-        $limit = array($offset, $per_page);
2466
-
2467
-        $_where = array(
2468
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2469
-            'Registration.REG_count' => 1,
2470
-        );
2471
-
2472
-        if (isset($this->_req_data['EVT_ID'])) {
2473
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2474
-        }
2475
-
2476
-        if (isset($this->_req_data['s'])) {
2477
-            $search_string = '%' . $this->_req_data['s'] . '%';
2478
-            $_where['OR'] = array(
2479
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2480
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2481
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2482
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2483
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2484
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2485
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2486
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2487
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2488
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2489
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2490
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2491
-                'Registration.REG_code'               => array('LIKE', $search_string),
2492
-                'Registration.REG_count'              => array('LIKE', $search_string),
2493
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2494
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2495
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2496
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2497
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2498
-                'TXN_session_data'                    => array('LIKE', $search_string),
2499
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2500
-            );
2501
-        }
2502
-
2503
-        // failed transactions
2504
-        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2505
-                  || ($count && $view === 'failed');
2506
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2507
-                     || ($count && $view === 'abandoned');
2508
-        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2509
-                      || ($count && $view === 'incomplete');
2510
-
2511
-        if ($failed) {
2512
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2513
-        } elseif ($abandoned) {
2514
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2515
-        } elseif ($incomplete) {
2516
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2517
-        } else {
2518
-            $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2519
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2520
-        }
2521
-
2522
-        $query_params = apply_filters(
2523
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2524
-            array(
2525
-                $_where,
2526
-                'order_by'                 => array($orderby => $sort),
2527
-                'limit'                    => $limit,
2528
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2529
-            ),
2530
-            $this->_req_data,
2531
-            $view,
2532
-            $count
2533
-        );
2534
-
2535
-        $transactions = $count
2536
-            ? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2537
-            : $TXN->get_all($query_params);
2538
-
2539
-        return $transactions;
2540
-    }
2541
-
2542
-
2543
-    /**
2544
-     * @since 4.9.79.p
2545
-     * @throws EE_Error
2546
-     * @throws InvalidArgumentException
2547
-     * @throws InvalidDataTypeException
2548
-     * @throws InvalidInterfaceException
2549
-     * @throws ReflectionException
2550
-     * @throws RuntimeException
2551
-     */
2552
-    public function recalculateLineItems()
2553
-    {
2554
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2555
-        /** @var EE_Transaction $transaction */
2556
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2557
-        $total_line_item = $transaction->total_line_item(false);
2558
-        $success = $transaction->recalculateLineItems();
2559
-        $this->_redirect_after_action(
2560
-            (bool) $success,
2561
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2562
-            esc_html__('recalculated', 'event_espresso'),
2563
-            isset($this->_req_data['redirect_to'])
2564
-                ? array(
2565
-                'action' => $this->_req_data['redirect_to'],
2566
-                'TXN_ID' => $this->_req_data['TXN_ID'],
2567
-            )
2568
-                : array(),
2569
-            true
2570
-        );
2571
-    }
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug = TXN_PG_SLUG;
50
+		$this->page_label = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels = array(
78
+			'buttons' => array(
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			),
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 */
97
+	public function _set_page_routes()
98
+	{
99
+
100
+		$this->_set_transaction_status_array();
101
+
102
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
103
+				  && ! is_array($this->_req_data['TXN_ID'])
104
+			? $this->_req_data['TXN_ID']
105
+			: 0;
106
+
107
+		$this->_page_routes = array(
108
+
109
+			'default' => array(
110
+				'func'       => '_transactions_overview_list_table',
111
+				'capability' => 'ee_read_transactions',
112
+			),
113
+
114
+			'view_transaction' => array(
115
+				'func'       => '_transaction_details',
116
+				'capability' => 'ee_read_transaction',
117
+				'obj_id'     => $txn_id,
118
+			),
119
+
120
+			'send_payment_reminder' => array(
121
+				'func'       => '_send_payment_reminder',
122
+				'noheader'   => true,
123
+				'capability' => 'ee_send_message',
124
+			),
125
+
126
+			'espresso_apply_payment' => array(
127
+				'func'       => 'apply_payments_or_refunds',
128
+				'noheader'   => true,
129
+				'capability' => 'ee_edit_payments',
130
+			),
131
+
132
+			'espresso_apply_refund' => array(
133
+				'func'       => 'apply_payments_or_refunds',
134
+				'noheader'   => true,
135
+				'capability' => 'ee_edit_payments',
136
+			),
137
+
138
+			'espresso_delete_payment' => array(
139
+				'func'       => 'delete_payment',
140
+				'noheader'   => true,
141
+				'capability' => 'ee_delete_payments',
142
+			),
143
+
144
+			'espresso_recalculate_line_items' => array(
145
+				'func'       => 'recalculateLineItems',
146
+				'noheader'   => true,
147
+				'capability' => 'ee_edit_payments',
148
+			),
149
+
150
+		);
151
+	}
152
+
153
+
154
+	protected function _set_page_config()
155
+	{
156
+		$this->_page_config = array(
157
+			'default'          => array(
158
+				'nav'           => array(
159
+					'label' => esc_html__('Overview', 'event_espresso'),
160
+					'order' => 10,
161
+				),
162
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
163
+				'help_tabs'     => array(
164
+					'transactions_overview_help_tab'                       => array(
165
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
+						'filename' => 'transactions_overview',
167
+					),
168
+					'transactions_overview_table_column_headings_help_tab' => array(
169
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
+						'filename' => 'transactions_overview_table_column_headings',
171
+					),
172
+					'transactions_overview_views_filters_help_tab'         => array(
173
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
+						'filename' => 'transactions_overview_views_filters_search',
175
+					),
176
+				),
177
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
+				// 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
+				/**
180
+				 * commented out because currently we are not displaying tips for transaction list table status but this
181
+				 * may change in a later iteration so want to keep the code for then.
182
+				 */
183
+				// 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
+				'require_nonce' => false,
185
+			),
186
+			'view_transaction' => array(
187
+				'nav'       => array(
188
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
189
+					'order'      => 5,
190
+					'url'        => isset($this->_req_data['TXN_ID'])
191
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
+						: $this->_admin_base_url,
193
+					'persistent' => false,
194
+				),
195
+				'help_tabs' => array(
196
+					'transactions_view_transaction_help_tab'                                              => array(
197
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction',
199
+					),
200
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_transaction_details_table',
203
+					),
204
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
+						'filename' => 'transactions_view_transaction_attendees_registered',
207
+					),
208
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
+					),
212
+				),
213
+				'qtips'     => array('Transaction_Details_Tips'),
214
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
+				// 'help_tour' => array('Transaction_Details_Help_Tour'),
216
+				'metaboxes' => array('_transaction_details_metaboxes'),
217
+
218
+				'require_nonce' => false,
219
+			),
220
+		);
221
+	}
222
+
223
+
224
+	/**
225
+	 * The below methods aren't used by this class currently
226
+	 */
227
+	protected function _add_screen_options()
228
+	{
229
+		// noop
230
+	}
231
+
232
+
233
+	protected function _add_feature_pointers()
234
+	{
235
+		// noop
236
+	}
237
+
238
+
239
+	public function admin_init()
240
+	{
241
+		// IF a registration was JUST added via the admin...
242
+		if (isset(
243
+			$this->_req_data['redirect_from'],
244
+			$this->_req_data['EVT_ID'],
245
+			$this->_req_data['event_name']
246
+		)) {
247
+			// then set a cookie so that we can block any attempts to use
248
+			// the back button as a way to enter another registration.
249
+			setcookie(
250
+				'ee_registration_added',
251
+				$this->_req_data['EVT_ID'],
252
+				time() + WEEK_IN_SECONDS,
253
+				'/'
254
+			);
255
+			// and update the global
256
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
257
+		}
258
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
259
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
260
+			'event_espresso'
261
+		);
262
+		EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
263
+			'An error occurred! Please refresh the page and try again.',
264
+			'event_espresso'
265
+		);
266
+		EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
267
+		EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
268
+		EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
269
+		EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
270
+			'This transaction has been overpaid ! Payments Total',
271
+			'event_espresso'
272
+		);
273
+	}
274
+
275
+
276
+	public function admin_notices()
277
+	{
278
+		// noop
279
+	}
280
+
281
+
282
+	public function admin_footer_scripts()
283
+	{
284
+		// noop
285
+	}
286
+
287
+
288
+	/**
289
+	 * _set_transaction_status_array
290
+	 * sets list of transaction statuses
291
+	 *
292
+	 * @access private
293
+	 * @return void
294
+	 * @throws EE_Error
295
+	 * @throws InvalidArgumentException
296
+	 * @throws InvalidDataTypeException
297
+	 * @throws InvalidInterfaceException
298
+	 */
299
+	private function _set_transaction_status_array()
300
+	{
301
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
302
+	}
303
+
304
+
305
+	/**
306
+	 * get_transaction_status_array
307
+	 * return the transaction status array for wp_list_table
308
+	 *
309
+	 * @access public
310
+	 * @return array
311
+	 */
312
+	public function get_transaction_status_array()
313
+	{
314
+		return self::$_txn_status;
315
+	}
316
+
317
+
318
+	/**
319
+	 *    get list of payment statuses
320
+	 *
321
+	 * @access private
322
+	 * @return void
323
+	 * @throws EE_Error
324
+	 * @throws InvalidArgumentException
325
+	 * @throws InvalidDataTypeException
326
+	 * @throws InvalidInterfaceException
327
+	 */
328
+	private function _get_payment_status_array()
329
+	{
330
+		self::$_pay_status = EEM_Payment::instance()->status_array(true);
331
+		$this->_template_args['payment_status'] = self::$_pay_status;
332
+	}
333
+
334
+
335
+	/**
336
+	 *    _add_screen_options_default
337
+	 *
338
+	 * @access protected
339
+	 * @return void
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 */
344
+	protected function _add_screen_options_default()
345
+	{
346
+		$this->_per_page_screen_option();
347
+	}
348
+
349
+
350
+	/**
351
+	 * load_scripts_styles
352
+	 *
353
+	 * @access public
354
+	 * @return void
355
+	 */
356
+	public function load_scripts_styles()
357
+	{
358
+		// enqueue style
359
+		wp_register_style(
360
+			'espresso_txn',
361
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
362
+			array(),
363
+			EVENT_ESPRESSO_VERSION
364
+		);
365
+		wp_enqueue_style('espresso_txn');
366
+		// scripts
367
+		wp_register_script(
368
+			'espresso_txn',
369
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
370
+			array(
371
+				'ee_admin_js',
372
+				'ee-datepicker',
373
+				'jquery-ui-datepicker',
374
+				'jquery-ui-draggable',
375
+				'ee-dialog',
376
+				'ee-accounting',
377
+				'ee-serialize-full-array',
378
+			),
379
+			EVENT_ESPRESSO_VERSION,
380
+			true
381
+		);
382
+		wp_enqueue_script('espresso_txn');
383
+	}
384
+
385
+
386
+	/**
387
+	 *    load_scripts_styles_view_transaction
388
+	 *
389
+	 * @access public
390
+	 * @return void
391
+	 */
392
+	public function load_scripts_styles_view_transaction()
393
+	{
394
+		// styles
395
+		wp_enqueue_style('espresso-ui-theme');
396
+	}
397
+
398
+
399
+	/**
400
+	 *    load_scripts_styles_default
401
+	 *
402
+	 * @access public
403
+	 * @return void
404
+	 */
405
+	public function load_scripts_styles_default()
406
+	{
407
+		// styles
408
+		wp_enqueue_style('espresso-ui-theme');
409
+	}
410
+
411
+
412
+	/**
413
+	 *    _set_list_table_views_default
414
+	 *
415
+	 * @access protected
416
+	 * @return void
417
+	 */
418
+	protected function _set_list_table_views_default()
419
+	{
420
+		$this->_views = array(
421
+			'all'        => array(
422
+				'slug'  => 'all',
423
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
424
+				'count' => 0,
425
+			),
426
+			'abandoned'  => array(
427
+				'slug'  => 'abandoned',
428
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
+				'count' => 0,
430
+			),
431
+			'incomplete' => array(
432
+				'slug'  => 'incomplete',
433
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
434
+				'count' => 0,
435
+			),
436
+		);
437
+		if (/**
438
+		 * Filters whether a link to the "Failed Transactions" list table
439
+		 * appears on the Transactions Admin Page list table.
440
+		 * List display can be turned back on via the following:
441
+		 * add_filter(
442
+		 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
443
+		 *     '__return_true'
444
+		 * );
445
+		 *
446
+		 * @since 4.9.70.p
447
+		 * @param boolean                 $display_failed_txns_list
448
+		 * @param Transactions_Admin_Page $this
449
+		 */
450
+		apply_filters(
451
+			'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
452
+			false,
453
+			$this
454
+		)
455
+		) {
456
+			$this->_views['failed'] = array(
457
+				'slug'  => 'failed',
458
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
459
+				'count' => 0,
460
+			);
461
+		}
462
+	}
463
+
464
+
465
+	/**
466
+	 * _set_transaction_object
467
+	 * This sets the _transaction property for the transaction details screen
468
+	 *
469
+	 * @access private
470
+	 * @return void
471
+	 * @throws EE_Error
472
+	 * @throws InvalidArgumentException
473
+	 * @throws RuntimeException
474
+	 * @throws InvalidDataTypeException
475
+	 * @throws InvalidInterfaceException
476
+	 * @throws ReflectionException
477
+	 */
478
+	private function _set_transaction_object()
479
+	{
480
+		if ($this->_transaction instanceof EE_Transaction) {
481
+			return;
482
+		} //get out we've already set the object
483
+
484
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
485
+			? absint($this->_req_data['TXN_ID'])
486
+			: false;
487
+
488
+		// get transaction object
489
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
490
+		$this->_session = $this->_transaction instanceof EE_Transaction
491
+			? $this->_transaction->session_data()
492
+			: null;
493
+		if ($this->_transaction instanceof EE_Transaction) {
494
+			$this->_transaction->verify_abandoned_transaction_status();
495
+		}
496
+
497
+		if (! $this->_transaction instanceof EE_Transaction) {
498
+			$error_msg = sprintf(
499
+				esc_html__(
500
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
501
+					'event_espresso'
502
+				),
503
+				$TXN_ID
504
+			);
505
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
506
+		}
507
+	}
508
+
509
+
510
+	/**
511
+	 *    _transaction_legend_items
512
+	 *
513
+	 * @access protected
514
+	 * @return array
515
+	 * @throws EE_Error
516
+	 * @throws InvalidArgumentException
517
+	 * @throws ReflectionException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 */
521
+	protected function _transaction_legend_items()
522
+	{
523
+		EE_Registry::instance()->load_helper('MSG_Template');
524
+		$items = array();
525
+
526
+		if (EE_Registry::instance()->CAP->current_user_can(
527
+			'ee_read_global_messages',
528
+			'view_filtered_messages'
529
+		)) {
530
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
531
+			if (is_array($related_for_icon)
532
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
533
+			) {
534
+				$items['view_related_messages'] = array(
535
+					'class' => $related_for_icon['css_class'],
536
+					'desc'  => $related_for_icon['label'],
537
+				);
538
+			}
539
+		}
540
+
541
+		$items = apply_filters(
542
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
543
+			array_merge(
544
+				$items,
545
+				array(
546
+					'view_details'          => array(
547
+						'class' => 'dashicons dashicons-cart',
548
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
549
+					),
550
+					'view_invoice'          => array(
551
+						'class' => 'dashicons dashicons-media-spreadsheet',
552
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
553
+					),
554
+					'view_receipt'          => array(
555
+						'class' => 'dashicons dashicons-media-default',
556
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
557
+					),
558
+					'view_registration'     => array(
559
+						'class' => 'dashicons dashicons-clipboard',
560
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
561
+					),
562
+					'payment_overview_link' => array(
563
+						'class' => 'dashicons dashicons-money',
564
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
565
+					),
566
+				)
567
+			)
568
+		);
569
+
570
+		if (EEH_MSG_Template::is_mt_active('payment_reminder')
571
+			&& EE_Registry::instance()->CAP->current_user_can(
572
+				'ee_send_message',
573
+				'espresso_transactions_send_payment_reminder'
574
+			)
575
+		) {
576
+			$items['send_payment_reminder'] = array(
577
+				'class' => 'dashicons dashicons-email-alt',
578
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
579
+			);
580
+		} else {
581
+			$items['blank*'] = array(
582
+				'class' => '',
583
+				'desc'  => '',
584
+			);
585
+		}
586
+		$more_items = apply_filters(
587
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
588
+			array(
589
+				'overpaid'   => array(
590
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
591
+					'desc'  => EEH_Template::pretty_status(
592
+						EEM_Transaction::overpaid_status_code,
593
+						false,
594
+						'sentence'
595
+					),
596
+				),
597
+				'complete'   => array(
598
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
599
+					'desc'  => EEH_Template::pretty_status(
600
+						EEM_Transaction::complete_status_code,
601
+						false,
602
+						'sentence'
603
+					),
604
+				),
605
+				'incomplete' => array(
606
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
607
+					'desc'  => EEH_Template::pretty_status(
608
+						EEM_Transaction::incomplete_status_code,
609
+						false,
610
+						'sentence'
611
+					),
612
+				),
613
+				'abandoned'  => array(
614
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
615
+					'desc'  => EEH_Template::pretty_status(
616
+						EEM_Transaction::abandoned_status_code,
617
+						false,
618
+						'sentence'
619
+					),
620
+				),
621
+				'failed'     => array(
622
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
623
+					'desc'  => EEH_Template::pretty_status(
624
+						EEM_Transaction::failed_status_code,
625
+						false,
626
+						'sentence'
627
+					),
628
+				),
629
+			)
630
+		);
631
+
632
+		return array_merge($items, $more_items);
633
+	}
634
+
635
+
636
+	/**
637
+	 *    _transactions_overview_list_table
638
+	 *
639
+	 * @access protected
640
+	 * @return void
641
+	 * @throws DomainException
642
+	 * @throws EE_Error
643
+	 * @throws InvalidArgumentException
644
+	 * @throws InvalidDataTypeException
645
+	 * @throws InvalidInterfaceException
646
+	 * @throws ReflectionException
647
+	 */
648
+	protected function _transactions_overview_list_table()
649
+	{
650
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
651
+		$event = isset($this->_req_data['EVT_ID'])
652
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
653
+			: null;
654
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
655
+			? sprintf(
656
+				esc_html__(
657
+					'%sViewing Transactions for the Event: %s%s',
658
+					'event_espresso'
659
+				),
660
+				'<h3>',
661
+				'<a href="'
662
+				. EE_Admin_Page::add_query_args_and_nonce(
663
+					array('action' => 'edit', 'post' => $event->ID()),
664
+					EVENTS_ADMIN_URL
665
+				)
666
+				. '" title="'
667
+				. esc_attr__(
668
+					'Click to Edit event',
669
+					'event_espresso'
670
+				)
671
+				. '">' . $event->name() . '</a>',
672
+				'</h3>'
673
+			)
674
+			: '';
675
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
676
+		$this->display_admin_list_table_page_with_no_sidebar();
677
+	}
678
+
679
+
680
+	/**
681
+	 *    _transaction_details
682
+	 * generates HTML for the View Transaction Details Admin page
683
+	 *
684
+	 * @access protected
685
+	 * @return void
686
+	 * @throws DomainException
687
+	 * @throws EE_Error
688
+	 * @throws InvalidArgumentException
689
+	 * @throws InvalidDataTypeException
690
+	 * @throws InvalidInterfaceException
691
+	 * @throws RuntimeException
692
+	 * @throws ReflectionException
693
+	 */
694
+	protected function _transaction_details()
695
+	{
696
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
697
+
698
+		$this->_set_transaction_status_array();
699
+
700
+		$this->_template_args = array();
701
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
702
+
703
+		$this->_set_transaction_object();
704
+
705
+		if (! $this->_transaction instanceof EE_Transaction) {
706
+			return;
707
+		}
708
+		$primary_registration = $this->_transaction->primary_registration();
709
+		$attendee = $primary_registration instanceof EE_Registration
710
+			? $primary_registration->attendee()
711
+			: null;
712
+
713
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
714
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
715
+
716
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
717
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
718
+
719
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
720
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
721
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
722
+
723
+		$this->_template_args['grand_total'] = $this->_transaction->total();
724
+		$this->_template_args['total_paid'] = $this->_transaction->paid();
725
+
726
+		$amount_due = $this->_transaction->total() - $this->_transaction->paid();
727
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
728
+			$amount_due,
729
+			true
730
+		);
731
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
732
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
733
+												  . $this->_template_args['amount_due'];
734
+		} else {
735
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
736
+		}
737
+		$this->_template_args['amount_due_class'] = '';
738
+
739
+		if ($this->_transaction->paid() === $this->_transaction->total()) {
740
+			// paid in full
741
+			$this->_template_args['amount_due'] = false;
742
+		} elseif ($this->_transaction->paid() > $this->_transaction->total()) {
743
+			// overpaid
744
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
745
+		} elseif ($this->_transaction->total() > (float) 0) {
746
+			if ($this->_transaction->paid() > (float) 0) {
747
+				// monies owing
748
+				$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
749
+			} elseif ($this->_transaction->paid() === (float) 0) {
750
+				// no payments made yet
751
+				$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
752
+			}
753
+		} elseif ($this->_transaction->total() === (float) 0) {
754
+			// free event
755
+			$this->_template_args['amount_due'] = false;
756
+		}
757
+
758
+		$payment_method = $this->_transaction->payment_method();
759
+
760
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
761
+			? $payment_method->admin_name()
762
+			: esc_html__('Unknown', 'event_espresso');
763
+
764
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
765
+		// link back to overview
766
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
767
+			? $_SERVER['HTTP_REFERER']
768
+			: TXN_ADMIN_URL;
769
+
770
+
771
+		// next link
772
+		$next_txn = $this->_transaction->next(
773
+			null,
774
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
775
+			'TXN_ID'
776
+		);
777
+		$this->_template_args['next_transaction'] = $next_txn
778
+			? $this->_next_link(
779
+				EE_Admin_Page::add_query_args_and_nonce(
780
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
781
+					TXN_ADMIN_URL
782
+				),
783
+				'dashicons dashicons-arrow-right ee-icon-size-22'
784
+			)
785
+			: '';
786
+		// previous link
787
+		$previous_txn = $this->_transaction->previous(
788
+			null,
789
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
790
+			'TXN_ID'
791
+		);
792
+		$this->_template_args['previous_transaction'] = $previous_txn
793
+			? $this->_previous_link(
794
+				EE_Admin_Page::add_query_args_and_nonce(
795
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
796
+					TXN_ADMIN_URL
797
+				),
798
+				'dashicons dashicons-arrow-left ee-icon-size-22'
799
+			)
800
+			: '';
801
+
802
+		// were we just redirected here after adding a new registration ???
803
+		if (isset(
804
+			$this->_req_data['redirect_from'],
805
+			$this->_req_data['EVT_ID'],
806
+			$this->_req_data['event_name']
807
+		)) {
808
+			if (EE_Registry::instance()->CAP->current_user_can(
809
+				'ee_edit_registrations',
810
+				'espresso_registrations_new_registration',
811
+				$this->_req_data['EVT_ID']
812
+			)) {
813
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
814
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
815
+					array(
816
+						'page'     => 'espresso_registrations',
817
+						'action'   => 'new_registration',
818
+						'return'   => 'default',
819
+						'TXN_ID'   => $this->_transaction->ID(),
820
+						'event_id' => $this->_req_data['EVT_ID'],
821
+					),
822
+					REG_ADMIN_URL
823
+				);
824
+				$this->_admin_page_title .= '">';
825
+
826
+				$this->_admin_page_title .= sprintf(
827
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
828
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
829
+				);
830
+				$this->_admin_page_title .= '</a>';
831
+			}
832
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
833
+		}
834
+		// grab messages at the last second
835
+		$this->_template_args['notices'] = EE_Error::get_notices();
836
+		// path to template
837
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
838
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
839
+			$template_path,
840
+			$this->_template_args,
841
+			true
842
+		);
843
+
844
+		// the details template wrapper
845
+		$this->display_admin_page_with_sidebar();
846
+	}
847
+
848
+
849
+	/**
850
+	 *        _transaction_details_metaboxes
851
+	 *
852
+	 * @access protected
853
+	 * @return void
854
+	 * @throws EE_Error
855
+	 * @throws InvalidArgumentException
856
+	 * @throws InvalidDataTypeException
857
+	 * @throws InvalidInterfaceException
858
+	 * @throws RuntimeException
859
+	 * @throws ReflectionException
860
+	 */
861
+	protected function _transaction_details_metaboxes()
862
+	{
863
+
864
+		$this->_set_transaction_object();
865
+
866
+		if (! $this->_transaction instanceof EE_Transaction) {
867
+			return;
868
+		}
869
+		add_meta_box(
870
+			'edit-txn-details-mbox',
871
+			esc_html__('Transaction Details', 'event_espresso'),
872
+			array($this, 'txn_details_meta_box'),
873
+			$this->_wp_page_slug,
874
+			'normal',
875
+			'high'
876
+		);
877
+		add_meta_box(
878
+			'edit-txn-attendees-mbox',
879
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
+			array($this, 'txn_attendees_meta_box'),
881
+			$this->_wp_page_slug,
882
+			'normal',
883
+			'high',
884
+			array('TXN_ID' => $this->_transaction->ID())
885
+		);
886
+		add_meta_box(
887
+			'edit-txn-registrant-mbox',
888
+			esc_html__('Primary Contact', 'event_espresso'),
889
+			array($this, 'txn_registrant_side_meta_box'),
890
+			$this->_wp_page_slug,
891
+			'side',
892
+			'high'
893
+		);
894
+		add_meta_box(
895
+			'edit-txn-billing-info-mbox',
896
+			esc_html__('Billing Information', 'event_espresso'),
897
+			array($this, 'txn_billing_info_side_meta_box'),
898
+			$this->_wp_page_slug,
899
+			'side',
900
+			'high'
901
+		);
902
+	}
903
+
904
+
905
+	/**
906
+	 * Callback for transaction actions metabox.
907
+	 *
908
+	 * @param EE_Transaction|null $transaction
909
+	 * @return string
910
+	 * @throws DomainException
911
+	 * @throws EE_Error
912
+	 * @throws InvalidArgumentException
913
+	 * @throws InvalidDataTypeException
914
+	 * @throws InvalidInterfaceException
915
+	 * @throws ReflectionException
916
+	 * @throws RuntimeException
917
+	 */
918
+	public function getActionButtons(EE_Transaction $transaction = null)
919
+	{
920
+		$content = '';
921
+		$actions = array();
922
+		if (! $transaction instanceof EE_Transaction) {
923
+			return $content;
924
+		}
925
+		/** @var EE_Registration $primary_registration */
926
+		$primary_registration = $transaction->primary_registration();
927
+		$attendee = $primary_registration instanceof EE_Registration
928
+			? $primary_registration->attendee()
929
+			: null;
930
+
931
+		if ($attendee instanceof EE_Attendee
932
+			&& EE_Registry::instance()->CAP->current_user_can(
933
+				'ee_send_message',
934
+				'espresso_transactions_send_payment_reminder'
935
+			)
936
+		) {
937
+			$actions['payment_reminder'] =
938
+				EEH_MSG_Template::is_mt_active('payment_reminder')
939
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
940
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
941
+					? EEH_Template::get_button_or_link(
942
+						EE_Admin_Page::add_query_args_and_nonce(
943
+							array(
944
+								'action'      => 'send_payment_reminder',
945
+								'TXN_ID'      => $this->_transaction->ID(),
946
+								'redirect_to' => 'view_transaction',
947
+							),
948
+							TXN_ADMIN_URL
949
+						),
950
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
951
+						'button secondary-button',
952
+						'dashicons dashicons-email-alt'
953
+					)
954
+					: '';
955
+		}
956
+
957
+		if (EE_Registry::instance()->CAP->current_user_can(
958
+			'ee_edit_payments',
959
+			'espresso_transactions_recalculate_line_items'
960
+		)
961
+		) {
962
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
963
+				EE_Admin_Page::add_query_args_and_nonce(
964
+					array(
965
+						'action'      => 'espresso_recalculate_line_items',
966
+						'TXN_ID'      => $this->_transaction->ID(),
967
+						'redirect_to' => 'view_transaction',
968
+					),
969
+					TXN_ADMIN_URL
970
+				),
971
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
972
+				'button secondary-button',
973
+				'dashicons dashicons-update'
974
+			);
975
+		}
976
+
977
+		if ($primary_registration instanceof EE_Registration
978
+			&& EEH_MSG_Template::is_mt_active('receipt')
979
+		) {
980
+			$actions['receipt'] = EEH_Template::get_button_or_link(
981
+				$primary_registration->receipt_url(),
982
+				esc_html__('View Receipt', 'event_espresso'),
983
+				'button secondary-button',
984
+				'dashicons dashicons-media-default'
985
+			);
986
+		}
987
+
988
+		if ($primary_registration instanceof EE_Registration
989
+			&& EEH_MSG_Template::is_mt_active('invoice')
990
+		) {
991
+			$actions['invoice'] = EEH_Template::get_button_or_link(
992
+				$primary_registration->invoice_url(),
993
+				esc_html__('View Invoice', 'event_espresso'),
994
+				'button secondary-button',
995
+				'dashicons dashicons-media-spreadsheet'
996
+			);
997
+		}
998
+		$actions = array_filter(
999
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1000
+		);
1001
+		if ($actions) {
1002
+			$content = '<ul>';
1003
+			$content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1004
+			$content .= '</uL>';
1005
+		}
1006
+		return $content;
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * txn_details_meta_box
1012
+	 * generates HTML for the Transaction main meta box
1013
+	 *
1014
+	 * @return void
1015
+	 * @throws DomainException
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 * @throws RuntimeException
1021
+	 * @throws ReflectionException
1022
+	 */
1023
+	public function txn_details_meta_box()
1024
+	{
1025
+		$this->_set_transaction_object();
1026
+		$this->_template_args['TXN_ID'] = $this->_transaction->ID();
1027
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1028
+			? $this->_transaction->primary_registration()->attendee()
1029
+			: null;
1030
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1031
+			'ee_edit_payments',
1032
+			'apply_payment_or_refund_from_registration_details'
1033
+		);
1034
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1035
+			'ee_delete_payments',
1036
+			'delete_payment_from_registration_details'
1037
+		);
1038
+
1039
+		// get line table
1040
+		EEH_Autoloader::register_line_item_display_autoloaders();
1041
+		$Line_Item_Display = new EE_Line_Item_Display(
1042
+			'admin_table',
1043
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1044
+		);
1045
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1046
+			$this->_transaction->total_line_item()
1047
+		);
1048
+		$this->_template_args['REG_code'] = $this->_transaction->primary_registration()->reg_code();
1049
+
1050
+		// process taxes
1051
+		$taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1052
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1053
+
1054
+		$this->_template_args['grand_total'] = EEH_Template::format_currency(
1055
+			$this->_transaction->total(),
1056
+			false,
1057
+			false
1058
+		);
1059
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1060
+		$this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1061
+
1062
+		// process payment details
1063
+		$payments = $this->_transaction->payments();
1064
+		if (! empty($payments)) {
1065
+			$this->_template_args['payments'] = $payments;
1066
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1067
+		} else {
1068
+			$this->_template_args['payments'] = false;
1069
+			$this->_template_args['existing_reg_payments'] = array();
1070
+		}
1071
+
1072
+		$this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1073
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1074
+			array('action' => 'espresso_delete_payment'),
1075
+			TXN_ADMIN_URL
1076
+		);
1077
+
1078
+		if (isset($txn_details['invoice_number'])) {
1079
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1080
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1081
+				'Invoice Number',
1082
+				'event_espresso'
1083
+			);
1084
+		}
1085
+
1086
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1087
+			->primary_registration()
1088
+			->session_ID();
1089
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1090
+			'Registration Session',
1091
+			'event_espresso'
1092
+		);
1093
+
1094
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1095
+			? $this->_session['ip_address']
1096
+			: '';
1097
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1098
+			'Transaction placed from IP',
1099
+			'event_espresso'
1100
+		);
1101
+
1102
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1103
+			? $this->_session['user_agent']
1104
+			: '';
1105
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1106
+			'Registrant User Agent',
1107
+			'event_espresso'
1108
+		);
1109
+
1110
+		$reg_steps = '<ul>';
1111
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1112
+			if ($reg_step_status === true) {
1113
+				$reg_steps .= '<li style="color:#70cc50">'
1114
+							  . sprintf(
1115
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1116
+								  ucwords(str_replace('_', ' ', $reg_step))
1117
+							  )
1118
+							  . '</li>';
1119
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1120
+				$reg_steps .= '<li style="color:#2EA2CC">'
1121
+							  . sprintf(
1122
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1123
+								  ucwords(str_replace('_', ' ', $reg_step)),
1124
+								  date(
1125
+									  get_option('date_format') . ' ' . get_option('time_format'),
1126
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1127
+								  )
1128
+							  )
1129
+							  . '</li>';
1130
+			} else {
1131
+				$reg_steps .= '<li style="color:#E76700">'
1132
+							  . sprintf(
1133
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1134
+								  ucwords(str_replace('_', ' ', $reg_step))
1135
+							  )
1136
+							  . '</li>';
1137
+			}
1138
+		}
1139
+		$reg_steps .= '</ul>';
1140
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1141
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1142
+			'Registration Step Progress',
1143
+			'event_espresso'
1144
+		);
1145
+
1146
+
1147
+		$this->_get_registrations_to_apply_payment_to();
1148
+		$this->_get_payment_methods($payments);
1149
+		$this->_get_payment_status_array();
1150
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1151
+
1152
+		$this->_template_args['transaction_form_url'] = add_query_arg(
1153
+			array(
1154
+				'action'  => 'edit_transaction',
1155
+				'process' => 'transaction',
1156
+			),
1157
+			TXN_ADMIN_URL
1158
+		);
1159
+		$this->_template_args['apply_payment_form_url'] = add_query_arg(
1160
+			array(
1161
+				'page'   => 'espresso_transactions',
1162
+				'action' => 'espresso_apply_payment',
1163
+			),
1164
+			WP_AJAX_URL
1165
+		);
1166
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1167
+			array(
1168
+				'page'   => 'espresso_transactions',
1169
+				'action' => 'espresso_delete_payment',
1170
+			),
1171
+			WP_AJAX_URL
1172
+		);
1173
+
1174
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1175
+
1176
+		// 'espresso_delete_payment_nonce'
1177
+
1178
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1179
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1180
+	}
1181
+
1182
+
1183
+	/**
1184
+	 * _get_registration_payment_IDs
1185
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1186
+	 *
1187
+	 * @access protected
1188
+	 * @param EE_Payment[] $payments
1189
+	 * @return array
1190
+	 * @throws EE_Error
1191
+	 * @throws InvalidArgumentException
1192
+	 * @throws InvalidDataTypeException
1193
+	 * @throws InvalidInterfaceException
1194
+	 * @throws ReflectionException
1195
+	 */
1196
+	protected function _get_registration_payment_IDs($payments = array())
1197
+	{
1198
+		$existing_reg_payments = array();
1199
+		// get all reg payments for these payments
1200
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1201
+			array(
1202
+				array(
1203
+					'PAY_ID' => array(
1204
+						'IN',
1205
+						array_keys($payments),
1206
+					),
1207
+				),
1208
+			)
1209
+		);
1210
+		if (! empty($reg_payments)) {
1211
+			foreach ($payments as $payment) {
1212
+				if (! $payment instanceof EE_Payment) {
1213
+					continue;
1214
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1215
+					$existing_reg_payments[ $payment->ID() ] = array();
1216
+				}
1217
+				foreach ($reg_payments as $reg_payment) {
1218
+					if ($reg_payment instanceof EE_Registration_Payment
1219
+						&& $reg_payment->payment_ID() === $payment->ID()
1220
+					) {
1221
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1222
+					}
1223
+				}
1224
+			}
1225
+		}
1226
+
1227
+		return $existing_reg_payments;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * _get_registrations_to_apply_payment_to
1233
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1234
+	 * which allows the admin to only apply the payment to the specific registrations
1235
+	 *
1236
+	 * @access protected
1237
+	 * @return void
1238
+	 * @throws EE_Error
1239
+	 * @throws InvalidArgumentException
1240
+	 * @throws InvalidDataTypeException
1241
+	 * @throws InvalidInterfaceException
1242
+	 * @throws ReflectionException
1243
+	 */
1244
+	protected function _get_registrations_to_apply_payment_to()
1245
+	{
1246
+		// we want any registration with an active status (ie: not deleted or cancelled)
1247
+		$query_params = array(
1248
+			array(
1249
+				'STS_ID' => array(
1250
+					'IN',
1251
+					array(
1252
+						EEM_Registration::status_id_approved,
1253
+						EEM_Registration::status_id_pending_payment,
1254
+						EEM_Registration::status_id_not_approved,
1255
+					),
1256
+				),
1257
+			),
1258
+		);
1259
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1260
+			'',
1261
+			'txn-admin-apply-payment-to-registrations-dv',
1262
+			'',
1263
+			'clear: both; margin: 1.5em 0 0; display: none;'
1264
+		);
1265
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1266
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1267
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1268
+			EEH_HTML::tr(
1269
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1270
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1271
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1272
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1273
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1274
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1275
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1276
+			)
1277
+		);
1278
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1279
+		// get registrations for TXN
1280
+		$registrations = $this->_transaction->registrations($query_params);
1281
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1282
+		foreach ($registrations as $registration) {
1283
+			if ($registration instanceof EE_Registration) {
1284
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
1285
+					? $registration->attendee()->full_name()
1286
+					: esc_html__('Unknown Attendee', 'event_espresso');
1287
+				$owing = $registration->final_price() - $registration->paid();
1288
+				$taxable = $registration->ticket()->taxable()
1289
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1290
+					: '';
1291
+				$checked = empty($existing_reg_payments)
1292
+						   || in_array($registration->ID(), $existing_reg_payments, true)
1293
+					? ' checked="checked"'
1294
+					: '';
1295
+				$disabled = $registration->final_price() > 0 ? '' : ' disabled';
1296
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1297
+					EEH_HTML::td($registration->ID()) .
1298
+					EEH_HTML::td($attendee_name) .
1299
+					EEH_HTML::td(
1300
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1301
+					) .
1302
+					EEH_HTML::td($registration->event_name()) .
1303
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1304
+					EEH_HTML::td(
1305
+						EEH_Template::format_currency($owing),
1306
+						'',
1307
+						'txn-admin-payment-owing-td jst-cntr'
1308
+					) .
1309
+					EEH_HTML::td(
1310
+						'<input type="checkbox" value="' . $registration->ID()
1311
+						. '" name="txn_admin_payment[registrations]"'
1312
+						. $checked . $disabled . '>',
1313
+						'',
1314
+						'jst-cntr'
1315
+					),
1316
+					'apply-payment-registration-row-' . $registration->ID()
1317
+				);
1318
+			}
1319
+		}
1320
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1321
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1322
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1323
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1324
+			esc_html__(
1325
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1326
+				'event_espresso'
1327
+			),
1328
+			'',
1329
+			'clear description'
1330
+		);
1331
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1332
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1333
+	}
1334
+
1335
+
1336
+	/**
1337
+	 * _get_reg_status_selection
1338
+	 *
1339
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1340
+	 *         instead of events.
1341
+	 * @access protected
1342
+	 * @return void
1343
+	 * @throws EE_Error
1344
+	 */
1345
+	protected function _get_reg_status_selection()
1346
+	{
1347
+		// first get all possible statuses
1348
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1349
+		// let's add a "don't change" option.
1350
+		$status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1351
+		$status_array = array_merge($status_array, $statuses);
1352
+		$this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1353
+			'txn_reg_status_change[reg_status]',
1354
+			$status_array,
1355
+			'NAN',
1356
+			'id="txn-admin-payment-reg-status-inp"',
1357
+			'txn-reg-status-change-reg-status'
1358
+		);
1359
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1360
+			'delete_txn_reg_status_change[reg_status]',
1361
+			$status_array,
1362
+			'NAN',
1363
+			'delete-txn-admin-payment-reg-status-inp',
1364
+			'delete-txn-reg-status-change-reg-status'
1365
+		);
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 *    _get_payment_methods
1371
+	 * Gets all the payment methods available generally, or the ones that are already
1372
+	 * selected on these payments (in case their payment methods are no longer active).
1373
+	 * Has the side-effect of updating the template args' payment_methods item
1374
+	 *
1375
+	 * @access private
1376
+	 * @param EE_Payment[] to show on this page
1377
+	 * @return void
1378
+	 * @throws EE_Error
1379
+	 * @throws InvalidArgumentException
1380
+	 * @throws InvalidDataTypeException
1381
+	 * @throws InvalidInterfaceException
1382
+	 * @throws ReflectionException
1383
+	 */
1384
+	private function _get_payment_methods($payments = array())
1385
+	{
1386
+		$payment_methods_of_payments = array();
1387
+		foreach ($payments as $payment) {
1388
+			if ($payment instanceof EE_Payment) {
1389
+				$payment_methods_of_payments[] = $payment->ID();
1390
+			}
1391
+		}
1392
+		if ($payment_methods_of_payments) {
1393
+			$query_args = array(
1394
+				array(
1395
+					'OR*payment_method_for_payment' => array(
1396
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1397
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1398
+					),
1399
+				),
1400
+			);
1401
+		} else {
1402
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1403
+		}
1404
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1405
+	}
1406
+
1407
+
1408
+	/**
1409
+	 * txn_attendees_meta_box
1410
+	 *    generates HTML for the Attendees Transaction main meta box
1411
+	 *
1412
+	 * @access public
1413
+	 * @param WP_Post $post
1414
+	 * @param array   $metabox
1415
+	 * @return void
1416
+	 * @throws DomainException
1417
+	 * @throws EE_Error
1418
+	 * @throws InvalidArgumentException
1419
+	 * @throws InvalidDataTypeException
1420
+	 * @throws InvalidInterfaceException
1421
+	 * @throws ReflectionException
1422
+	 */
1423
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1424
+	{
1425
+
1426
+		/** @noinspection NonSecureExtractUsageInspection */
1427
+		extract($metabox['args']);
1428
+		$this->_template_args['post'] = $post;
1429
+		$this->_template_args['event_attendees'] = array();
1430
+		// process items in cart
1431
+		$line_items = $this->_transaction->get_many_related(
1432
+			'Line_Item',
1433
+			array(array('LIN_type' => 'line-item'))
1434
+		);
1435
+		if (! empty($line_items)) {
1436
+			foreach ($line_items as $item) {
1437
+				if ($item instanceof EE_Line_Item) {
1438
+					switch ($item->OBJ_type()) {
1439
+						case 'Event':
1440
+							break;
1441
+						case 'Ticket':
1442
+							$ticket = $item->ticket();
1443
+							// right now we're only handling tickets here.
1444
+							// Cause its expected that only tickets will have attendees right?
1445
+							if (! $ticket instanceof EE_Ticket) {
1446
+								break;
1447
+							}
1448
+							try {
1449
+								$event_name = $ticket->get_event_name();
1450
+							} catch (Exception $e) {
1451
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1452
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1453
+							}
1454
+							$event_name .= ' - ' . $item->name();
1455
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1456
+							// now get all of the registrations for this transaction that use this ticket
1457
+							$registrations = $ticket->registrations(
1458
+								array(array('TXN_ID' => $this->_transaction->ID()))
1459
+							);
1460
+							foreach ($registrations as $registration) {
1461
+								if (! $registration instanceof EE_Registration) {
1462
+									break;
1463
+								}
1464
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1465
+									= $registration->status_ID();
1466
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1467
+									= $registration->count();
1468
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1469
+									= $event_name;
1470
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1471
+									= $ticket_price;
1472
+								// attendee info
1473
+								$attendee = $registration->get_first_related('Attendee');
1474
+								if ($attendee instanceof EE_Attendee) {
1475
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1476
+										= $attendee->ID();
1477
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1478
+										= $attendee->full_name();
1479
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1480
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1481
+										  . esc_html__(
1482
+											  ' Event',
1483
+											  'event_espresso'
1484
+										  )
1485
+										  . '">' . $attendee->email() . '</a>';
1486
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1487
+										= EEH_Address::format($attendee, 'inline', false, false);
1488
+								} else {
1489
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1490
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1491
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1492
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1493
+								}
1494
+							}
1495
+							break;
1496
+					}
1497
+				}
1498
+			}
1499
+
1500
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1501
+				array(
1502
+					'action'  => 'edit_transaction',
1503
+					'process' => 'attendees',
1504
+				),
1505
+				TXN_ADMIN_URL
1506
+			);
1507
+			echo EEH_Template::display_template(
1508
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1509
+				$this->_template_args,
1510
+				true
1511
+			);
1512
+		} else {
1513
+			echo sprintf(
1514
+				esc_html__(
1515
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1516
+					'event_espresso'
1517
+				),
1518
+				'<p class="important-notice">',
1519
+				'</p>'
1520
+			);
1521
+		}
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * txn_registrant_side_meta_box
1527
+	 * generates HTML for the Edit Transaction side meta box
1528
+	 *
1529
+	 * @access public
1530
+	 * @return void
1531
+	 * @throws DomainException
1532
+	 * @throws EE_Error
1533
+	 * @throws InvalidArgumentException
1534
+	 * @throws InvalidDataTypeException
1535
+	 * @throws InvalidInterfaceException
1536
+	 * @throws ReflectionException
1537
+	 */
1538
+	public function txn_registrant_side_meta_box()
1539
+	{
1540
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1541
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1542
+			: null;
1543
+		if (! $primary_att instanceof EE_Attendee) {
1544
+			$this->_template_args['no_attendee_message'] = esc_html__(
1545
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1546
+				'event_espresso'
1547
+			);
1548
+			$primary_att = EEM_Attendee::instance()->create_default_object();
1549
+		}
1550
+		$this->_template_args['ATT_ID'] = $primary_att->ID();
1551
+		$this->_template_args['prime_reg_fname'] = $primary_att->fname();
1552
+		$this->_template_args['prime_reg_lname'] = $primary_att->lname();
1553
+		$this->_template_args['prime_reg_email'] = $primary_att->email();
1554
+		$this->_template_args['prime_reg_phone'] = $primary_att->phone();
1555
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1556
+			array(
1557
+				'action' => 'edit_attendee',
1558
+				'post'   => $primary_att->ID(),
1559
+			),
1560
+			REG_ADMIN_URL
1561
+		);
1562
+		// get formatted address for registrant
1563
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1564
+		echo EEH_Template::display_template(
1565
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1566
+			$this->_template_args,
1567
+			true
1568
+		);
1569
+	}
1570
+
1571
+
1572
+	/**
1573
+	 * txn_billing_info_side_meta_box
1574
+	 *    generates HTML for the Edit Transaction side meta box
1575
+	 *
1576
+	 * @access public
1577
+	 * @return void
1578
+	 * @throws DomainException
1579
+	 * @throws EE_Error
1580
+	 */
1581
+	public function txn_billing_info_side_meta_box()
1582
+	{
1583
+
1584
+		$this->_template_args['billing_form'] = $this->_transaction->billing_info();
1585
+		$this->_template_args['billing_form_url'] = add_query_arg(
1586
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1587
+			TXN_ADMIN_URL
1588
+		);
1589
+
1590
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1591
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1592
+	}
1593
+
1594
+
1595
+	/**
1596
+	 * apply_payments_or_refunds
1597
+	 *    registers a payment or refund made towards a transaction
1598
+	 *
1599
+	 * @access public
1600
+	 * @return void
1601
+	 * @throws EE_Error
1602
+	 * @throws InvalidArgumentException
1603
+	 * @throws ReflectionException
1604
+	 * @throws RuntimeException
1605
+	 * @throws InvalidDataTypeException
1606
+	 * @throws InvalidInterfaceException
1607
+	 */
1608
+	public function apply_payments_or_refunds()
1609
+	{
1610
+		$json_response_data = array('return_data' => false);
1611
+		$valid_data = $this->_validate_payment_request_data();
1612
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1613
+			'ee_edit_payments',
1614
+			'apply_payment_or_refund_from_registration_details'
1615
+		);
1616
+		if (! empty($valid_data) && $has_access) {
1617
+			$PAY_ID = $valid_data['PAY_ID'];
1618
+			// save  the new payment
1619
+			$payment = $this->_create_payment_from_request_data($valid_data);
1620
+			// get the TXN for this payment
1621
+			$transaction = $payment->transaction();
1622
+			// verify transaction
1623
+			if ($transaction instanceof EE_Transaction) {
1624
+				// calculate_total_payments_and_update_status
1625
+				$this->_process_transaction_payments($transaction);
1626
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1627
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1628
+				// apply payment to registrations (if applicable)
1629
+				if (! empty($REG_IDs)) {
1630
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1631
+					$this->_maybe_send_notifications();
1632
+					// now process status changes for the same registrations
1633
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1634
+				}
1635
+				$this->_maybe_send_notifications($payment);
1636
+				// prepare to render page
1637
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1638
+				do_action(
1639
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1640
+					$transaction,
1641
+					$payment
1642
+				);
1643
+			} else {
1644
+				EE_Error::add_error(
1645
+					esc_html__(
1646
+						'A valid Transaction for this payment could not be retrieved.',
1647
+						'event_espresso'
1648
+					),
1649
+					__FILE__,
1650
+					__FUNCTION__,
1651
+					__LINE__
1652
+				);
1653
+			}
1654
+		} elseif ($has_access) {
1655
+			EE_Error::add_error(
1656
+				esc_html__(
1657
+					'The payment form data could not be processed. Please try again.',
1658
+					'event_espresso'
1659
+				),
1660
+				__FILE__,
1661
+				__FUNCTION__,
1662
+				__LINE__
1663
+			);
1664
+		} else {
1665
+			EE_Error::add_error(
1666
+				esc_html__(
1667
+					'You do not have access to apply payments or refunds to a registration.',
1668
+					'event_espresso'
1669
+				),
1670
+				__FILE__,
1671
+				__FUNCTION__,
1672
+				__LINE__
1673
+			);
1674
+		}
1675
+		$notices = EE_Error::get_notices(
1676
+			false,
1677
+			false,
1678
+			false
1679
+		);
1680
+		$this->_template_args = array(
1681
+			'data'    => $json_response_data,
1682
+			'error'   => $notices['errors'],
1683
+			'success' => $notices['success'],
1684
+		);
1685
+		$this->_return_json();
1686
+	}
1687
+
1688
+
1689
+	/**
1690
+	 * _validate_payment_request_data
1691
+	 *
1692
+	 * @return array
1693
+	 * @throws EE_Error
1694
+	 * @throws InvalidArgumentException
1695
+	 * @throws InvalidDataTypeException
1696
+	 * @throws InvalidInterfaceException
1697
+	 */
1698
+	protected function _validate_payment_request_data()
1699
+	{
1700
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1701
+			return array();
1702
+		}
1703
+		$payment_form = $this->_generate_payment_form_section();
1704
+		try {
1705
+			if ($payment_form->was_submitted()) {
1706
+				$payment_form->receive_form_submission();
1707
+				if (! $payment_form->is_valid()) {
1708
+					$submission_error_messages = array();
1709
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1710
+						if ($validation_error instanceof EE_Validation_Error) {
1711
+							$submission_error_messages[] = sprintf(
1712
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1713
+								$validation_error->get_form_section()->html_label_text(),
1714
+								$validation_error->getMessage()
1715
+							);
1716
+						}
1717
+					}
1718
+					EE_Error::add_error(
1719
+						implode('<br />', $submission_error_messages),
1720
+						__FILE__,
1721
+						__FUNCTION__,
1722
+						__LINE__
1723
+					);
1724
+					return array();
1725
+				}
1726
+			}
1727
+		} catch (EE_Error $e) {
1728
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1729
+			return array();
1730
+		}
1731
+
1732
+		return $payment_form->valid_data();
1733
+	}
1734
+
1735
+
1736
+	/**
1737
+	 * _generate_payment_form_section
1738
+	 *
1739
+	 * @return EE_Form_Section_Proper
1740
+	 * @throws EE_Error
1741
+	 */
1742
+	protected function _generate_payment_form_section()
1743
+	{
1744
+		return new EE_Form_Section_Proper(
1745
+			array(
1746
+				'name'        => 'txn_admin_payment',
1747
+				'subsections' => array(
1748
+					'PAY_ID'          => new EE_Text_Input(
1749
+						array(
1750
+							'default'               => 0,
1751
+							'required'              => false,
1752
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1753
+							'validation_strategies' => array(new EE_Int_Normalization()),
1754
+						)
1755
+					),
1756
+					'TXN_ID'          => new EE_Text_Input(
1757
+						array(
1758
+							'default'               => 0,
1759
+							'required'              => true,
1760
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1761
+							'validation_strategies' => array(new EE_Int_Normalization()),
1762
+						)
1763
+					),
1764
+					'type'            => new EE_Text_Input(
1765
+						array(
1766
+							'default'               => 1,
1767
+							'required'              => true,
1768
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1769
+							'validation_strategies' => array(new EE_Int_Normalization()),
1770
+						)
1771
+					),
1772
+					'amount'          => new EE_Text_Input(
1773
+						array(
1774
+							'default'               => 0,
1775
+							'required'              => true,
1776
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1777
+							'validation_strategies' => array(new EE_Float_Normalization()),
1778
+						)
1779
+					),
1780
+					'status'          => new EE_Text_Input(
1781
+						array(
1782
+							'default'         => EEM_Payment::status_id_approved,
1783
+							'required'        => true,
1784
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1785
+						)
1786
+					),
1787
+					'PMD_ID'          => new EE_Text_Input(
1788
+						array(
1789
+							'default'               => 2,
1790
+							'required'              => true,
1791
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1792
+							'validation_strategies' => array(new EE_Int_Normalization()),
1793
+						)
1794
+					),
1795
+					'date'            => new EE_Text_Input(
1796
+						array(
1797
+							'default'         => time(),
1798
+							'required'        => true,
1799
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1800
+						)
1801
+					),
1802
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1803
+						array(
1804
+							'default'               => '',
1805
+							'required'              => false,
1806
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1807
+							'validation_strategies' => array(
1808
+								new EE_Max_Length_Validation_Strategy(
1809
+									esc_html__('Input too long', 'event_espresso'),
1810
+									100
1811
+								),
1812
+							),
1813
+						)
1814
+					),
1815
+					'po_number'       => new EE_Text_Input(
1816
+						array(
1817
+							'default'               => '',
1818
+							'required'              => false,
1819
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1820
+							'validation_strategies' => array(
1821
+								new EE_Max_Length_Validation_Strategy(
1822
+									esc_html__('Input too long', 'event_espresso'),
1823
+									100
1824
+								),
1825
+							),
1826
+						)
1827
+					),
1828
+					'accounting'      => new EE_Text_Input(
1829
+						array(
1830
+							'default'               => '',
1831
+							'required'              => false,
1832
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1833
+							'validation_strategies' => array(
1834
+								new EE_Max_Length_Validation_Strategy(
1835
+									esc_html__('Input too long', 'event_espresso'),
1836
+									100
1837
+								),
1838
+							),
1839
+						)
1840
+					),
1841
+				),
1842
+			)
1843
+		);
1844
+	}
1845
+
1846
+
1847
+	/**
1848
+	 * _create_payment_from_request_data
1849
+	 *
1850
+	 * @param array $valid_data
1851
+	 * @return EE_Payment
1852
+	 * @throws EE_Error
1853
+	 * @throws InvalidArgumentException
1854
+	 * @throws InvalidDataTypeException
1855
+	 * @throws InvalidInterfaceException
1856
+	 * @throws ReflectionException
1857
+	 */
1858
+	protected function _create_payment_from_request_data($valid_data)
1859
+	{
1860
+		$PAY_ID = $valid_data['PAY_ID'];
1861
+		// get payment amount
1862
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1863
+		// payments have a type value of 1 and refunds have a type value of -1
1864
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1865
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1866
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1867
+		$date = $valid_data['date']
1868
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1869
+			: date('Y-m-d g:i a', current_time('timestamp'));
1870
+		$payment = EE_Payment::new_instance(
1871
+			array(
1872
+				'TXN_ID'              => $valid_data['TXN_ID'],
1873
+				'STS_ID'              => $valid_data['status'],
1874
+				'PAY_timestamp'       => $date,
1875
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1876
+				'PMD_ID'              => $valid_data['PMD_ID'],
1877
+				'PAY_amount'          => $amount,
1878
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1879
+				'PAY_po_number'       => $valid_data['po_number'],
1880
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1881
+				'PAY_details'         => $valid_data,
1882
+				'PAY_ID'              => $PAY_ID,
1883
+			),
1884
+			'',
1885
+			array('Y-m-d', 'g:i a')
1886
+		);
1887
+
1888
+		if (! $payment->save()) {
1889
+			EE_Error::add_error(
1890
+				sprintf(
1891
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1892
+					$payment->ID()
1893
+				),
1894
+				__FILE__,
1895
+				__FUNCTION__,
1896
+				__LINE__
1897
+			);
1898
+		}
1899
+
1900
+		return $payment;
1901
+	}
1902
+
1903
+
1904
+	/**
1905
+	 * _process_transaction_payments
1906
+	 *
1907
+	 * @param \EE_Transaction $transaction
1908
+	 * @return void
1909
+	 * @throws EE_Error
1910
+	 * @throws InvalidArgumentException
1911
+	 * @throws ReflectionException
1912
+	 * @throws InvalidDataTypeException
1913
+	 * @throws InvalidInterfaceException
1914
+	 */
1915
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1916
+	{
1917
+		/** @type EE_Transaction_Payments $transaction_payments */
1918
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1919
+		// update the transaction with this payment
1920
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1921
+			EE_Error::add_success(
1922
+				esc_html__(
1923
+					'The payment has been processed successfully.',
1924
+					'event_espresso'
1925
+				),
1926
+				__FILE__,
1927
+				__FUNCTION__,
1928
+				__LINE__
1929
+			);
1930
+		} else {
1931
+			EE_Error::add_error(
1932
+				esc_html__(
1933
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1934
+					'event_espresso'
1935
+				),
1936
+				__FILE__,
1937
+				__FUNCTION__,
1938
+				__LINE__
1939
+			);
1940
+		}
1941
+	}
1942
+
1943
+
1944
+	/**
1945
+	 * _get_REG_IDs_to_apply_payment_to
1946
+	 * returns a list of registration IDs that the payment will apply to
1947
+	 *
1948
+	 * @param \EE_Payment $payment
1949
+	 * @return array
1950
+	 * @throws EE_Error
1951
+	 * @throws InvalidArgumentException
1952
+	 * @throws InvalidDataTypeException
1953
+	 * @throws InvalidInterfaceException
1954
+	 * @throws ReflectionException
1955
+	 */
1956
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1957
+	{
1958
+		$REG_IDs = array();
1959
+		// grab array of IDs for specific registrations to apply changes to
1960
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1961
+			$REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1962
+		}
1963
+		// nothing specified ? then get all reg IDs
1964
+		if (empty($REG_IDs)) {
1965
+			$registrations = $payment->transaction()->registrations();
1966
+			$REG_IDs = ! empty($registrations)
1967
+				? array_keys($registrations)
1968
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1969
+		}
1970
+
1971
+		// ensure that REG_IDs are integers and NOT strings
1972
+		return array_map('intval', $REG_IDs);
1973
+	}
1974
+
1975
+
1976
+	/**
1977
+	 * @return array
1978
+	 */
1979
+	public function existing_reg_payment_REG_IDs()
1980
+	{
1981
+		return $this->_existing_reg_payment_REG_IDs;
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * @param array $existing_reg_payment_REG_IDs
1987
+	 */
1988
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1989
+	{
1990
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1991
+	}
1992
+
1993
+
1994
+	/**
1995
+	 * _get_existing_reg_payment_REG_IDs
1996
+	 * returns a list of registration IDs that the payment is currently related to
1997
+	 * as recorded in the database
1998
+	 *
1999
+	 * @param \EE_Payment $payment
2000
+	 * @return array
2001
+	 * @throws EE_Error
2002
+	 * @throws InvalidArgumentException
2003
+	 * @throws InvalidDataTypeException
2004
+	 * @throws InvalidInterfaceException
2005
+	 * @throws ReflectionException
2006
+	 */
2007
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2008
+	{
2009
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2010
+			// let's get any existing reg payment records for this payment
2011
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2012
+			// but we only want the REG IDs, so grab the array keys
2013
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2014
+				? array_keys($existing_reg_payment_REG_IDs)
2015
+				: array();
2016
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2017
+		}
2018
+
2019
+		return $this->existing_reg_payment_REG_IDs();
2020
+	}
2021
+
2022
+
2023
+	/**
2024
+	 * _remove_existing_registration_payments
2025
+	 * this calculates the difference between existing relations
2026
+	 * to the supplied payment and the new list registration IDs,
2027
+	 * removes any related registrations that no longer apply,
2028
+	 * and then updates the registration paid fields
2029
+	 *
2030
+	 * @param \EE_Payment $payment
2031
+	 * @param int         $PAY_ID
2032
+	 * @return bool;
2033
+	 * @throws EE_Error
2034
+	 * @throws InvalidArgumentException
2035
+	 * @throws ReflectionException
2036
+	 * @throws InvalidDataTypeException
2037
+	 * @throws InvalidInterfaceException
2038
+	 */
2039
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2040
+	{
2041
+		// newly created payments will have nothing recorded for $PAY_ID
2042
+		if (absint($PAY_ID) === 0) {
2043
+			return false;
2044
+		}
2045
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2046
+		if (empty($existing_reg_payment_REG_IDs)) {
2047
+			return false;
2048
+		}
2049
+		/** @type EE_Transaction_Payments $transaction_payments */
2050
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2051
+
2052
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2053
+			$payment,
2054
+			array(
2055
+				array(
2056
+					'PAY_ID' => $payment->ID(),
2057
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2058
+				),
2059
+			)
2060
+		);
2061
+	}
2062
+
2063
+
2064
+	/**
2065
+	 * _update_registration_payments
2066
+	 * this applies the payments to the selected registrations
2067
+	 * but only if they have not already been paid for
2068
+	 *
2069
+	 * @param  EE_Transaction $transaction
2070
+	 * @param \EE_Payment     $payment
2071
+	 * @param array           $REG_IDs
2072
+	 * @return void
2073
+	 * @throws EE_Error
2074
+	 * @throws InvalidArgumentException
2075
+	 * @throws ReflectionException
2076
+	 * @throws RuntimeException
2077
+	 * @throws InvalidDataTypeException
2078
+	 * @throws InvalidInterfaceException
2079
+	 */
2080
+	protected function _update_registration_payments(
2081
+		EE_Transaction $transaction,
2082
+		EE_Payment $payment,
2083
+		$REG_IDs = array()
2084
+	) {
2085
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2086
+		// so let's do that using our set of REG_IDs from the form
2087
+		$registration_query_where_params = array(
2088
+			'REG_ID' => array('IN', $REG_IDs),
2089
+		);
2090
+		// but add in some conditions regarding payment,
2091
+		// so that we don't apply payments to registrations that are free or have already been paid for
2092
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2093
+		if (! $payment->is_a_refund()) {
2094
+			$registration_query_where_params['REG_final_price'] = array('!=', 0);
2095
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2096
+		}
2097
+		$registrations = $transaction->registrations(array($registration_query_where_params));
2098
+		if (! empty($registrations)) {
2099
+			/** @type EE_Payment_Processor $payment_processor */
2100
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2101
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2102
+		}
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * _process_registration_status_change
2108
+	 * This processes requested registration status changes for all the registrations
2109
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2110
+	 *
2111
+	 * @param  EE_Transaction $transaction
2112
+	 * @param array           $REG_IDs
2113
+	 * @return bool
2114
+	 * @throws EE_Error
2115
+	 * @throws InvalidArgumentException
2116
+	 * @throws ReflectionException
2117
+	 * @throws InvalidDataTypeException
2118
+	 * @throws InvalidInterfaceException
2119
+	 */
2120
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2121
+	{
2122
+		// first if there is no change in status then we get out.
2123
+		if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2124
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2125
+		) {
2126
+			// no error message, no change requested, just nothing to do man.
2127
+			return false;
2128
+		}
2129
+		/** @type EE_Transaction_Processor $transaction_processor */
2130
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2131
+
2132
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2133
+		return $transaction_processor->manually_update_registration_statuses(
2134
+			$transaction,
2135
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2136
+			array(array('REG_ID' => array('IN', $REG_IDs)))
2137
+		);
2138
+	}
2139
+
2140
+
2141
+	/**
2142
+	 * _build_payment_json_response
2143
+	 *
2144
+	 * @access public
2145
+	 * @param \EE_Payment $payment
2146
+	 * @param array       $REG_IDs
2147
+	 * @param bool | null $delete_txn_reg_status_change
2148
+	 * @return array
2149
+	 * @throws EE_Error
2150
+	 * @throws InvalidArgumentException
2151
+	 * @throws InvalidDataTypeException
2152
+	 * @throws InvalidInterfaceException
2153
+	 * @throws ReflectionException
2154
+	 */
2155
+	protected function _build_payment_json_response(
2156
+		EE_Payment $payment,
2157
+		$REG_IDs = array(),
2158
+		$delete_txn_reg_status_change = null
2159
+	) {
2160
+		// was the payment deleted ?
2161
+		if (is_bool($delete_txn_reg_status_change)) {
2162
+			return array(
2163
+				'PAY_ID'                       => $payment->ID(),
2164
+				'amount'                       => $payment->amount(),
2165
+				'total_paid'                   => $payment->transaction()->paid(),
2166
+				'txn_status'                   => $payment->transaction()->status_ID(),
2167
+				'pay_status'                   => $payment->STS_ID(),
2168
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2169
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2170
+			);
2171
+		} else {
2172
+			$this->_get_payment_status_array();
2173
+
2174
+			return array(
2175
+				'amount'           => $payment->amount(),
2176
+				'total_paid'       => $payment->transaction()->paid(),
2177
+				'txn_status'       => $payment->transaction()->status_ID(),
2178
+				'pay_status'       => $payment->STS_ID(),
2179
+				'PAY_ID'           => $payment->ID(),
2180
+				'STS_ID'           => $payment->STS_ID(),
2181
+				'status'           => self::$_pay_status[ $payment->STS_ID() ],
2182
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2183
+				'method'           => strtoupper($payment->source()),
2184
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2185
+				'gateway'          => $payment->payment_method()
2186
+					? $payment->payment_method()->admin_name()
2187
+					: esc_html__('Unknown', 'event_espresso'),
2188
+				'gateway_response' => $payment->gateway_response(),
2189
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2190
+				'po_number'        => $payment->po_number(),
2191
+				'extra_accntng'    => $payment->extra_accntng(),
2192
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2193
+			);
2194
+		}
2195
+	}
2196
+
2197
+
2198
+	/**
2199
+	 * delete_payment
2200
+	 *    delete a payment or refund made towards a transaction
2201
+	 *
2202
+	 * @access public
2203
+	 * @return void
2204
+	 * @throws EE_Error
2205
+	 * @throws InvalidArgumentException
2206
+	 * @throws ReflectionException
2207
+	 * @throws InvalidDataTypeException
2208
+	 * @throws InvalidInterfaceException
2209
+	 */
2210
+	public function delete_payment()
2211
+	{
2212
+		$json_response_data = array('return_data' => false);
2213
+		$PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2214
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2215
+			: 0;
2216
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2217
+			'ee_delete_payments',
2218
+			'delete_payment_from_registration_details'
2219
+		);
2220
+		if ($PAY_ID && $can_delete) {
2221
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2222
+				? $this->_req_data['delete_txn_reg_status_change']
2223
+				: false;
2224
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2225
+			if ($payment instanceof EE_Payment) {
2226
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2227
+				/** @type EE_Transaction_Payments $transaction_payments */
2228
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2229
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2230
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2231
+						$payment,
2232
+						$REG_IDs,
2233
+						$delete_txn_reg_status_change
2234
+					);
2235
+					if ($delete_txn_reg_status_change) {
2236
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2237
+						// MAKE sure we also add the delete_txn_req_status_change to the
2238
+						// $_REQUEST global because that's how messages will be looking for it.
2239
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2240
+						$this->_maybe_send_notifications();
2241
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2242
+					}
2243
+				}
2244
+			} else {
2245
+				EE_Error::add_error(
2246
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2247
+					__FILE__,
2248
+					__FUNCTION__,
2249
+					__LINE__
2250
+				);
2251
+			}
2252
+		} elseif ($can_delete) {
2253
+			EE_Error::add_error(
2254
+				esc_html__(
2255
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2256
+					'event_espresso'
2257
+				),
2258
+				__FILE__,
2259
+				__FUNCTION__,
2260
+				__LINE__
2261
+			);
2262
+		} else {
2263
+			EE_Error::add_error(
2264
+				esc_html__(
2265
+					'You do not have access to delete a payment.',
2266
+					'event_espresso'
2267
+				),
2268
+				__FILE__,
2269
+				__FUNCTION__,
2270
+				__LINE__
2271
+			);
2272
+		}
2273
+		$notices = EE_Error::get_notices(false, false, false);
2274
+		$this->_template_args = array(
2275
+			'data'      => $json_response_data,
2276
+			'success'   => $notices['success'],
2277
+			'error'     => $notices['errors'],
2278
+			'attention' => $notices['attention'],
2279
+		);
2280
+		$this->_return_json();
2281
+	}
2282
+
2283
+
2284
+	/**
2285
+	 * _registration_payment_data_array
2286
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2287
+	 *
2288
+	 * @access protected
2289
+	 * @param array $REG_IDs
2290
+	 * @return array
2291
+	 * @throws EE_Error
2292
+	 * @throws InvalidArgumentException
2293
+	 * @throws InvalidDataTypeException
2294
+	 * @throws InvalidInterfaceException
2295
+	 * @throws ReflectionException
2296
+	 */
2297
+	protected function _registration_payment_data_array($REG_IDs)
2298
+	{
2299
+		$registration_payment_data = array();
2300
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2301
+		if (! empty($REG_IDs)) {
2302
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2303
+			foreach ($registrations as $registration) {
2304
+				if ($registration instanceof EE_Registration) {
2305
+					$registration_payment_data[ $registration->ID() ] = array(
2306
+						'paid'  => $registration->pretty_paid(),
2307
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2308
+					);
2309
+				}
2310
+			}
2311
+		}
2312
+
2313
+		return $registration_payment_data;
2314
+	}
2315
+
2316
+
2317
+	/**
2318
+	 * _maybe_send_notifications
2319
+	 * determines whether or not the admin has indicated that notifications should be sent.
2320
+	 * If so, will toggle a filter switch for delivering registration notices.
2321
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2322
+	 *
2323
+	 * @access protected
2324
+	 * @param \EE_Payment | null $payment
2325
+	 */
2326
+	protected function _maybe_send_notifications($payment = null)
2327
+	{
2328
+		switch ($payment instanceof EE_Payment) {
2329
+			// payment notifications
2330
+			case true:
2331
+				if (isset($this->_req_data['txn_payments']['send_notifications'])
2332
+					&& filter_var(
2333
+						$this->_req_data['txn_payments']['send_notifications'],
2334
+						FILTER_VALIDATE_BOOLEAN
2335
+					)
2336
+				) {
2337
+					$this->_process_payment_notification($payment);
2338
+				}
2339
+				break;
2340
+			// registration notifications
2341
+			case false:
2342
+				if (isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2343
+					&& filter_var(
2344
+						$this->_req_data['txn_reg_status_change']['send_notifications'],
2345
+						FILTER_VALIDATE_BOOLEAN
2346
+					)
2347
+				) {
2348
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2349
+				}
2350
+				break;
2351
+		}
2352
+	}
2353
+
2354
+
2355
+	/**
2356
+	 * _send_payment_reminder
2357
+	 *    generates HTML for the View Transaction Details Admin page
2358
+	 *
2359
+	 * @access protected
2360
+	 * @return void
2361
+	 * @throws EE_Error
2362
+	 * @throws InvalidArgumentException
2363
+	 * @throws InvalidDataTypeException
2364
+	 * @throws InvalidInterfaceException
2365
+	 */
2366
+	protected function _send_payment_reminder()
2367
+	{
2368
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2369
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2370
+		$query_args = isset($this->_req_data['redirect_to']) ? array(
2371
+			'action' => $this->_req_data['redirect_to'],
2372
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2373
+		) : array();
2374
+		do_action(
2375
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2376
+			$transaction
2377
+		);
2378
+		$this->_redirect_after_action(
2379
+			false,
2380
+			esc_html__('payment reminder', 'event_espresso'),
2381
+			esc_html__('sent', 'event_espresso'),
2382
+			$query_args,
2383
+			true
2384
+		);
2385
+	}
2386
+
2387
+
2388
+	/**
2389
+	 *  get_transactions
2390
+	 *    get transactions for given parameters (used by list table)
2391
+	 *
2392
+	 * @param  int     $perpage how many transactions displayed per page
2393
+	 * @param  boolean $count   return the count or objects
2394
+	 * @param string   $view
2395
+	 * @return mixed int = count || array of transaction objects
2396
+	 * @throws EE_Error
2397
+	 * @throws InvalidArgumentException
2398
+	 * @throws InvalidDataTypeException
2399
+	 * @throws InvalidInterfaceException
2400
+	 */
2401
+	public function get_transactions($perpage, $count = false, $view = '')
2402
+	{
2403
+
2404
+		$TXN = EEM_Transaction::instance();
2405
+
2406
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2407
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2408
+			: date(
2409
+				'm/d/Y',
2410
+				strtotime('-10 year')
2411
+			);
2412
+		$end_date = isset($this->_req_data['txn-filter-end-date'])
2413
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2414
+			: date('m/d/Y');
2415
+
2416
+		// make sure our timestamps start and end right at the boundaries for each day
2417
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2418
+		$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2419
+
2420
+
2421
+		// convert to timestamps
2422
+		$start_date = strtotime($start_date);
2423
+		$end_date = strtotime($end_date);
2424
+
2425
+		// makes sure start date is the lowest value and vice versa
2426
+		$start_date = min($start_date, $end_date);
2427
+		$end_date = max($start_date, $end_date);
2428
+
2429
+		// convert to correct format for query
2430
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2431
+			'TXN_timestamp',
2432
+			date('Y-m-d H:i:s', $start_date),
2433
+			'Y-m-d H:i:s'
2434
+		);
2435
+		$end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2436
+			'TXN_timestamp',
2437
+			date('Y-m-d H:i:s', $end_date),
2438
+			'Y-m-d H:i:s'
2439
+		);
2440
+
2441
+
2442
+		// set orderby
2443
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2444
+
2445
+		switch ($this->_req_data['orderby']) {
2446
+			case 'TXN_ID':
2447
+				$orderby = 'TXN_ID';
2448
+				break;
2449
+			case 'ATT_fname':
2450
+				$orderby = 'Registration.Attendee.ATT_fname';
2451
+				break;
2452
+			case 'event_name':
2453
+				$orderby = 'Registration.Event.EVT_name';
2454
+				break;
2455
+			default: // 'TXN_timestamp'
2456
+				$orderby = 'TXN_timestamp';
2457
+		}
2458
+
2459
+		$sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2460
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2461
+		$per_page = ! empty($perpage) ? $perpage : 10;
2462
+		$per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2463
+
2464
+		$offset = ($current_page - 1) * $per_page;
2465
+		$limit = array($offset, $per_page);
2466
+
2467
+		$_where = array(
2468
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2469
+			'Registration.REG_count' => 1,
2470
+		);
2471
+
2472
+		if (isset($this->_req_data['EVT_ID'])) {
2473
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2474
+		}
2475
+
2476
+		if (isset($this->_req_data['s'])) {
2477
+			$search_string = '%' . $this->_req_data['s'] . '%';
2478
+			$_where['OR'] = array(
2479
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2480
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2481
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2482
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2483
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2484
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2485
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2486
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2487
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2488
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2489
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2490
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2491
+				'Registration.REG_code'               => array('LIKE', $search_string),
2492
+				'Registration.REG_count'              => array('LIKE', $search_string),
2493
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2494
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2495
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2496
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2497
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2498
+				'TXN_session_data'                    => array('LIKE', $search_string),
2499
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2500
+			);
2501
+		}
2502
+
2503
+		// failed transactions
2504
+		$failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2505
+				  || ($count && $view === 'failed');
2506
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2507
+					 || ($count && $view === 'abandoned');
2508
+		$incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2509
+					  || ($count && $view === 'incomplete');
2510
+
2511
+		if ($failed) {
2512
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2513
+		} elseif ($abandoned) {
2514
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2515
+		} elseif ($incomplete) {
2516
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2517
+		} else {
2518
+			$_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2519
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2520
+		}
2521
+
2522
+		$query_params = apply_filters(
2523
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2524
+			array(
2525
+				$_where,
2526
+				'order_by'                 => array($orderby => $sort),
2527
+				'limit'                    => $limit,
2528
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2529
+			),
2530
+			$this->_req_data,
2531
+			$view,
2532
+			$count
2533
+		);
2534
+
2535
+		$transactions = $count
2536
+			? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2537
+			: $TXN->get_all($query_params);
2538
+
2539
+		return $transactions;
2540
+	}
2541
+
2542
+
2543
+	/**
2544
+	 * @since 4.9.79.p
2545
+	 * @throws EE_Error
2546
+	 * @throws InvalidArgumentException
2547
+	 * @throws InvalidDataTypeException
2548
+	 * @throws InvalidInterfaceException
2549
+	 * @throws ReflectionException
2550
+	 * @throws RuntimeException
2551
+	 */
2552
+	public function recalculateLineItems()
2553
+	{
2554
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2555
+		/** @var EE_Transaction $transaction */
2556
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2557
+		$total_line_item = $transaction->total_line_item(false);
2558
+		$success = $transaction->recalculateLineItems();
2559
+		$this->_redirect_after_action(
2560
+			(bool) $success,
2561
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2562
+			esc_html__('recalculated', 'event_espresso'),
2563
+			isset($this->_req_data['redirect_to'])
2564
+				? array(
2565
+				'action' => $this->_req_data['redirect_to'],
2566
+				'TXN_ID' => $this->_req_data['TXN_ID'],
2567
+			)
2568
+				: array(),
2569
+			true
2570
+		);
2571
+	}
2572 2572
 }
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page.core.php 1 patch
Indentation   +698 added lines, -698 removed lines patch added patch discarded remove patch
@@ -15,649 +15,649 @@  discard block
 block discarded – undo
15 15
 class Registration_Form_Admin_Page extends EE_Admin_Page
16 16
 {
17 17
 
18
-    /**
19
-     * _question
20
-     * holds the specific question object for the question details screen
21
-     *
22
-     * @var EE_Question $_question
23
-     */
24
-    protected $_question;
25
-
26
-    /**
27
-     * _question_group
28
-     * holds the specific question group object for the question group details screen
29
-     *
30
-     * @var EE_Question_Group $_question_group
31
-     */
32
-    protected $_question_group;
33
-
34
-    /**
35
-     *_question_model EEM_Question model instance (for queries)
36
-     *
37
-     * @var EEM_Question $_question_model ;
38
-     */
39
-    protected $_question_model;
40
-
41
-    /**
42
-     * _question_group_model EEM_Question_group instance (for queries)
43
-     *
44
-     * @var EEM_Question_Group $_question_group_model
45
-     */
46
-    protected $_question_group_model;
47
-
48
-
49
-    /**
50
-     * @Constructor
51
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
52
-     * @access public
53
-     */
54
-    public function __construct($routing = true)
55
-    {
56
-        require_once(EE_MODELS . 'EEM_Question.model.php');
57
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
-        $this->_question_model = EEM_Question::instance();
59
-        $this->_question_group_model = EEM_Question_Group::instance();
60
-        parent::__construct($routing);
61
-    }
62
-
63
-
64
-    protected function _init_page_props()
65
-    {
66
-        $this->page_slug = REGISTRATION_FORM_PG_SLUG;
67
-        $this->page_label = esc_html__('Registration Form', 'event_espresso');
68
-        $this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL;
69
-        $this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
-    }
71
-
72
-
73
-    protected function _ajax_hooks()
74
-    {
75
-    }
76
-
77
-
78
-    protected function _define_page_props()
79
-    {
80
-        $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
-        $this->_labels = array(
82
-            'buttons' => array(
83
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
-            ),
85
-        );
86
-    }
87
-
88
-
89
-    /**
90
-     *_set_page_routes
91
-     */
92
-    protected function _set_page_routes()
93
-    {
94
-        $qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0;
95
-        $this->_page_routes = array(
96
-            'default' => array(
97
-                'func'       => '_questions_overview_list_table',
98
-                'capability' => 'ee_read_questions',
99
-            ),
100
-
101
-            'edit_question' => array(
102
-                'func'       => '_edit_question',
103
-                'capability' => 'ee_edit_question',
104
-                'obj_id'     => $qst_id,
105
-                'args'       => array('edit'),
106
-            ),
107
-
108
-            'question_groups' => array(
109
-                'func'       => '_questions_groups_preview',
110
-                'capability' => 'ee_read_question_groups',
111
-            ),
112
-
113
-            'update_question' => array(
114
-                'func'       => '_insert_or_update_question',
115
-                'args'       => array('new_question' => false),
116
-                'capability' => 'ee_edit_question',
117
-                'obj_id'     => $qst_id,
118
-                'noheader'   => true,
119
-            ),
120
-        );
121
-    }
122
-
123
-
124
-    protected function _set_page_config()
125
-    {
126
-        $this->_page_config = array(
127
-            'default' => array(
128
-                'nav'           => array(
129
-                    'label' => esc_html__('Questions', 'event_espresso'),
130
-                    'order' => 10,
131
-                ),
132
-                'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
133
-                'metaboxes'     => $this->_default_espresso_metaboxes,
134
-                'help_tabs'     => array(
135
-                    'registration_form_questions_overview_help_tab'                           => array(
136
-                        'title'    => esc_html__('Questions Overview', 'event_espresso'),
137
-                        'filename' => 'registration_form_questions_overview',
138
-                    ),
139
-                    'registration_form_questions_overview_table_column_headings_help_tab'     => array(
140
-                        'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
141
-                        'filename' => 'registration_form_questions_overview_table_column_headings',
142
-                    ),
143
-                    'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array(
144
-                        'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
145
-                        'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
146
-                    ),
147
-                ),
148
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
149
-                // 'help_tour'     => array('Registration_Form_Questions_Overview_Help_Tour'),
150
-                'require_nonce' => false,
151
-                'qtips'         => array(
152
-                    'EE_Registration_Form_Tips',
153
-                )/**/
154
-            ),
155
-
156
-            'question_groups' => array(
157
-                'nav'           => array(
158
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
159
-                    'order' => 20,
160
-                ),
161
-                'metaboxes'     => $this->_default_espresso_metaboxes,
162
-                'help_tabs'     => array(
163
-                    'registration_form_question_groups_help_tab' => array(
164
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
165
-                        'filename' => 'registration_form_question_groups',
166
-                    ),
167
-                ),
168
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
169
-                // 'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
170
-                'require_nonce' => false,
171
-            ),
172
-
173
-            'edit_question' => array(
174
-                'nav'           => array(
175
-                    'label'      => esc_html__('Edit Question', 'event_espresso'),
176
-                    'order'      => 15,
177
-                    'persistent' => false,
178
-                    'url'        => isset($this->_req_data['question_id']) ? add_query_arg(
179
-                        array('question_id' => $this->_req_data['question_id']),
180
-                        $this->_current_page_view_url
181
-                    ) : $this->_admin_base_url,
182
-                ),
183
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
184
-                'help_tabs'     => array(
185
-                    'registration_form_edit_question_group_help_tab' => array(
186
-                        'title'    => esc_html__('Edit Question', 'event_espresso'),
187
-                        'filename' => 'registration_form_edit_question',
188
-                    ),
189
-                ),
190
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
191
-                // 'help_tour'     => array('Registration_Form_Edit_Question_Help_Tour'),
192
-                'require_nonce' => false,
193
-            ),
194
-        );
195
-    }
196
-
197
-
198
-    protected function _add_screen_options()
199
-    {
200
-        // todo
201
-    }
202
-
203
-    protected function _add_screen_options_default()
204
-    {
205
-        $page_title = $this->_admin_page_title;
206
-        $this->_admin_page_title = esc_html__('Questions', 'event_espresso');
207
-        $this->_per_page_screen_option();
208
-        $this->_admin_page_title = $page_title;
209
-    }
210
-
211
-    protected function _add_screen_options_question_groups()
212
-    {
213
-        $page_title = $this->_admin_page_title;
214
-        $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
215
-        $this->_per_page_screen_option();
216
-        $this->_admin_page_title = $page_title;
217
-    }
218
-
219
-    // none of the below group are currently used for Event Categories
220
-    protected function _add_feature_pointers()
221
-    {
222
-    }
223
-
224
-    public function load_scripts_styles()
225
-    {
226
-        wp_register_style(
227
-            'espresso_registration',
228
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
229
-            array(),
230
-            EVENT_ESPRESSO_VERSION
231
-        );
232
-        wp_enqueue_style('espresso_registration');
233
-    }
234
-
235
-    public function admin_init()
236
-    {
237
-    }
238
-
239
-    public function admin_notices()
240
-    {
241
-    }
242
-
243
-    public function admin_footer_scripts()
244
-    {
245
-    }
246
-
247
-
248
-    public function load_scripts_styles_default()
249
-    {
250
-    }
251
-
252
-
253
-    public function load_scripts_styles_add_question()
254
-    {
255
-        $this->load_scripts_styles_question_details();
256
-    }
257
-
258
-    public function load_scripts_styles_edit_question()
259
-    {
260
-        $this->load_scripts_styles_question_details();
261
-    }
262
-
263
-    /**
264
-     * Loads the JS required for adding or editing a question
265
-     */
266
-    protected function load_scripts_styles_question_details()
267
-    {
268
-        $this->load_scripts_styles_forms();
269
-        wp_register_script(
270
-            'espresso_registration_form_single',
271
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
272
-            array('jquery-ui-sortable'),
273
-            EVENT_ESPRESSO_VERSION,
274
-            true
275
-        );
276
-        wp_enqueue_script('espresso_registration_form_single');
277
-        wp_localize_script(
278
-            'espresso_registration_form_single',
279
-            'ee_question_data',
280
-            array(
281
-                'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
282
-                'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
283
-            )
284
-        );
285
-    }
286
-
287
-
288
-    public function recaptcha_info_help_tab()
289
-    {
290
-        $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
291
-        EEH_Template::display_template($template, array());
292
-    }
293
-
294
-
295
-    public function load_scripts_styles_forms()
296
-    {
297
-        // styles
298
-        wp_enqueue_style('espresso-ui-theme');
299
-        // scripts
300
-        wp_enqueue_script('ee_admin_js');
301
-    }
302
-
303
-
304
-    protected function _set_list_table_views_default()
305
-    {
306
-        $this->_views = array(
307
-            'all' => array(
308
-                'slug'  => 'all',
309
-                'label' => esc_html__('View All Questions', 'event_espresso'),
310
-                'count' => 0,
311
-            ),
312
-        );
313
-
314
-        if (EE_Registry::instance()->CAP->current_user_can(
315
-            'ee_delete_questions',
316
-            'espresso_registration_form_trash_questions'
317
-        )
318
-        ) {
319
-            $this->_views['trash'] = array(
320
-                'slug'  => 'trash',
321
-                'label' => esc_html__('Trash', 'event_espresso'),
322
-                'count' => 0,
323
-            );
324
-        }
325
-    }
326
-
327
-    /**
328
-     * This just previews the question groups tab that comes in caffeinated.
329
-     *
330
-     * @return string html
331
-     */
332
-    protected function _questions_groups_preview()
333
-    {
334
-        $this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso');
335
-        $this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
336
-                                               . esc_attr__(
337
-                                                   'Preview Question Groups Overview List Table screenshot',
338
-                                                   'event_espresso'
339
-                                               ) . '" />';
340
-        $this->_template_args['preview_text'] = '<strong>'
341
-                                                . esc_html__(
342
-                                                    'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
343
-                                                    'event_espresso'
344
-                                                ) . '</strong>';
345
-        $this->display_admin_caf_preview_page('question_groups_tab');
346
-    }
347
-
348
-
349
-    /**
350
-     * Extracts the question field's values from the POST request to update or insert them
351
-     *
352
-     * @param \EEM_Base $model
353
-     * @return array where each key is the name of a model's field/db column, and each value is its value.
354
-     */
355
-    protected function _set_column_values_for(EEM_Base $model)
356
-    {
357
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
358
-        $set_column_values = array();
359
-
360
-        // some initial checks for proper values.
361
-        // if QST_admin_only, then no matter what QST_required is we disable.
362
-        if (! empty($this->_req_data['QST_admin_only'])) {
363
-            $this->_req_data['QST_required'] = 0;
364
-        }
365
-        // if the question shouldn't have a max length, don't let them set one
366
-        if (! isset(
367
-            $this->_req_data['QST_type'],
368
-            $this->_req_data['QST_max']
369
-        )
370
-            || ! in_array(
371
-                $this->_req_data['QST_type'],
372
-                EEM_Question::instance()->questionTypesWithMaxLength(),
373
-                true
374
-            )
375
-        ) {
376
-            // they're not allowed to set the max
377
-            $this->_req_data['QST_max'] = null;
378
-        }
379
-        foreach ($model->field_settings() as $fieldName => $settings) {
380
-            // basically if QSG_identifier is empty or not set
381
-            if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) {
382
-                $QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : '';
383
-                $set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
384
-            } //if the admin label is blank, use a slug version of the question text
385
-            elseif ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) {
386
-                $QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : '';
387
-                $set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
388
-            } elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
389
-                $set_column_values[ $fieldName ] = 0;
390
-            } elseif ($fieldName === 'QST_max') {
391
-                $qst_system = EEM_Question::instance()->get_var(
392
-                    array(
393
-                        array(
394
-                            'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0,
395
-                        ),
396
-                    ),
397
-                    'QST_system'
398
-                );
399
-                $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system);
400
-                if (empty($this->_req_data['QST_max']) ||
401
-                    $this->_req_data['QST_max'] > $max_max
402
-                ) {
403
-                    $set_column_values[ $fieldName ] = $max_max;
404
-                }
405
-            }
406
-
407
-
408
-            // only add a property to the array if it's not null (otherwise the model should just use the default value)
409
-            if (! isset($set_column_values[ $fieldName ]) &&
410
-                isset($this->_req_data[ $fieldName ])
411
-            ) {
412
-                $set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
413
-            }
414
-        }
415
-        return $set_column_values;// validation fo this data to be performed by the model before insertion.
416
-    }
417
-
418
-
419
-    /**
420
-     *_questions_overview_list_table
421
-     */
422
-    protected function _questions_overview_list_table()
423
-    {
424
-        $this->_search_btn_label = esc_html__('Questions', 'event_espresso');
425
-        $this->display_admin_list_table_page_with_sidebar();
426
-    }
427
-
428
-
429
-    /**
430
-     * _edit_question
431
-     */
432
-    protected function _edit_question()
433
-    {
434
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
435
-        $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint(
436
-            $this->_req_data['QST_ID']
437
-        ) : false;
438
-
439
-        switch ($this->_req_action) {
440
-            case 'add_question':
441
-                $this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
442
-                break;
443
-            case 'edit_question':
444
-                $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
445
-                break;
446
-            default:
447
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
448
-        }
449
-
450
-        // add PRC_ID to title if editing
451
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
452
-        if ($ID) {
453
-            $question = $this->_question_model->get_one_by_ID($ID);
454
-            $additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID));
455
-            $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
456
-        } else {
457
-            $question = EE_Question::new_instance();
458
-            $question->set_order_to_latest();
459
-            $this->_set_add_edit_form_tags('insert_question');
460
-        }
461
-        if ($question->system_ID() === EEM_Attendee::system_question_phone) {
462
-            $question_types = array_intersect_key(
463
-                EEM_Question::instance()->allowed_question_types(),
464
-                array_flip(
465
-                    array(
466
-                        EEM_Question::QST_type_text,
467
-                        EEM_Question::QST_type_us_phone,
468
-                    )
469
-                )
470
-            );
471
-        } else {
472
-            $question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category(
473
-                $question->type()
474
-            ) : $this->_question_model->allowed_question_types();
475
-        }
476
-        $this->_template_args['QST_ID'] = $ID;
477
-        $this->_template_args['question'] = $question;
478
-        $this->_template_args['question_types'] = $question_types;
479
-        $this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question(
480
-            $question->system_ID()
481
-        );
482
-        $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
483
-        $this->_set_publish_post_box_vars('id', $ID);
484
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
485
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
486
-            $this->_template_args,
487
-            true
488
-        );
489
-
490
-        // the details template wrapper
491
-        $this->display_admin_page_with_sidebar();
492
-    }
493
-
494
-
495
-    /**
496
-     * @return string
497
-     */
498
-    protected function _get_question_type_descriptions()
499
-    {
500
-        EE_Registry::instance()->load_helper('HTML');
501
-        $descriptions = '';
502
-        $question_type_descriptions = EEM_Question::instance()->question_descriptions();
503
-        foreach ($question_type_descriptions as $type => $question_type_description) {
504
-            if ($type == 'HTML_TEXTAREA') {
505
-                $html = new EE_Simple_HTML_Validation_Strategy();
506
-                $question_type_description .= sprintf(
507
-                    esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
508
-                    '<br/>',
509
-                    $html->get_list_of_allowed_tags()
510
-                );
511
-            }
512
-            $descriptions .= EEH_HTML::p(
513
-                $question_type_description,
514
-                'question_type_description-' . $type,
515
-                'question_type_description description',
516
-                'display:none;'
517
-            );
518
-        }
519
-        return $descriptions;
520
-    }
521
-
522
-
523
-    /**
524
-     * @param bool|true $new_question
525
-     * @throws \EE_Error
526
-     */
527
-    protected function _insert_or_update_question($new_question = true)
528
-    {
529
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
530
-        $set_column_values = $this->_set_column_values_for($this->_question_model);
531
-        if ($new_question) {
532
-            $question = EE_Question::new_instance($set_column_values);
533
-            $action_desc = 'added';
534
-        } else {
535
-            $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
536
-            foreach ($set_column_values as $field => $new_value) {
537
-                $question->set($field, $new_value);
538
-            }
539
-            $action_desc = 'updated';
540
-        }
541
-        $success = $question->save();
542
-        $ID = $question->ID();
543
-        if ($ID && $question->should_have_question_options()) {
544
-            // save the related options
545
-            // trash removed options, save old ones
546
-            // get list of all options
547
-            $options = $question->options();
548
-            if (! empty($options)) {
549
-                foreach ($options as $option_ID => $option) {
550
-                    $option_req_index = $this->_get_option_req_data_index($option_ID);
551
-                    if ($option_req_index !== false) {
552
-                        $option->save($this->_req_data['question_options'][ $option_req_index ]);
553
-                    } else {
554
-                        // not found, remove it
555
-                        $option->delete();
556
-                    }
557
-                }
558
-            }
559
-            // save new related options
560
-            foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
561
-                // skip $index that is from our sample
562
-                if ($index === 'xxcountxx') {
563
-                    continue;
564
-                }
565
-                // note we allow saving blank options.
566
-                if (empty($option_req_data['QSO_ID'])
567
-                ) {// no ID! save it!
568
-                    $new_option = EE_Question_Option::new_instance(
569
-                        array(
570
-                            'QSO_value' => $option_req_data['QSO_value'],
571
-                            'QSO_desc'  => $option_req_data['QSO_desc'],
572
-                            'QSO_order' => $option_req_data['QSO_order'],
573
-                            'QST_ID'    => $question->ID(),
574
-                        )
575
-                    );
576
-                    $new_option->save();
577
-                }
578
-            }
579
-        }
580
-        $query_args = array('action' => 'edit_question', 'QST_ID' => $ID);
581
-        if ($success !== false) {
582
-            $msg = $new_question
583
-                ? sprintf(
584
-                    esc_html__('The %s has been created', 'event_espresso'),
585
-                    $this->_question_model->item_name()
586
-                )
587
-                : sprintf(
588
-                    esc_html__('The %s has been updated', 'event_espresso'),
589
-                    $this->_question_model->item_name()
590
-                );
591
-            EE_Error::add_success($msg);
592
-        }
593
-
594
-        $this->_redirect_after_action(false, '', $action_desc, $query_args, true);
595
-    }
596
-
597
-
598
-    /**
599
-     * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
600
-     * by ID
601
-     * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
602
-     * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
603
-     *
604
-     * @param int $ID of the question option to find
605
-     * @return int index in question_options array if successful, FALSE if unsuccessful
606
-     */
607
-    protected function _get_option_req_data_index($ID)
608
-    {
609
-        $req_data_for_question_options = $this->_req_data['question_options'];
610
-        foreach ($req_data_for_question_options as $num => $option_data) {
611
-            if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
612
-                return $num;
613
-            }
614
-        }
615
-        return false;
616
-    }
617
-
618
-
619
-
620
-
621
-    /***********/
622
-    /* QUERIES */
623
-    /**
624
-     * For internal use in getting all the query parameters
625
-     * (because it's pretty well the same between question, question groups,
626
-     * and for both when searching for trashed and untrashed ones)
627
-     *
628
-     * @param EEM_Base $model either EEM_Question or EEM_Question_Group
629
-     * @param int      $per_page
630
-     * @param int      $current_page
631
-     * @return array model query params, @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
632
-     */
633
-    protected function get_query_params($model, $per_page = 10, $current_page = 10)
634
-    {
635
-        $query_params = array();
636
-        $offset = ($current_page - 1) * $per_page;
637
-        $query_params['limit'] = array($offset, $per_page);
638
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
639
-            : 'ASC';
640
-        $orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
641
-        $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
642
-        $query_params['order_by'] = array($field_to_order_by => $order);
643
-        $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
644
-        if (! empty($search_string)) {
645
-            if ($model instanceof EEM_Question_Group) {
646
-                $query_params[0] = array(
647
-                    'OR' => array(
648
-                        'QSG_name' => array('LIKE', "%$search_string%"),
649
-                        'QSG_desc' => array('LIKE', "%$search_string%"),
650
-                    ),
651
-                );
652
-            } else {
653
-                $query_params[0] = array(
654
-                    'QST_display_text' => array('LIKE', "%$search_string%"),
655
-                );
656
-            }
657
-        }
658
-
659
-        // capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
660
-        /*if ( $model instanceof EEM_Question_Group ) {
18
+	/**
19
+	 * _question
20
+	 * holds the specific question object for the question details screen
21
+	 *
22
+	 * @var EE_Question $_question
23
+	 */
24
+	protected $_question;
25
+
26
+	/**
27
+	 * _question_group
28
+	 * holds the specific question group object for the question group details screen
29
+	 *
30
+	 * @var EE_Question_Group $_question_group
31
+	 */
32
+	protected $_question_group;
33
+
34
+	/**
35
+	 *_question_model EEM_Question model instance (for queries)
36
+	 *
37
+	 * @var EEM_Question $_question_model ;
38
+	 */
39
+	protected $_question_model;
40
+
41
+	/**
42
+	 * _question_group_model EEM_Question_group instance (for queries)
43
+	 *
44
+	 * @var EEM_Question_Group $_question_group_model
45
+	 */
46
+	protected $_question_group_model;
47
+
48
+
49
+	/**
50
+	 * @Constructor
51
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
52
+	 * @access public
53
+	 */
54
+	public function __construct($routing = true)
55
+	{
56
+		require_once(EE_MODELS . 'EEM_Question.model.php');
57
+		require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
+		$this->_question_model = EEM_Question::instance();
59
+		$this->_question_group_model = EEM_Question_Group::instance();
60
+		parent::__construct($routing);
61
+	}
62
+
63
+
64
+	protected function _init_page_props()
65
+	{
66
+		$this->page_slug = REGISTRATION_FORM_PG_SLUG;
67
+		$this->page_label = esc_html__('Registration Form', 'event_espresso');
68
+		$this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL;
69
+		$this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
+	}
71
+
72
+
73
+	protected function _ajax_hooks()
74
+	{
75
+	}
76
+
77
+
78
+	protected function _define_page_props()
79
+	{
80
+		$this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
+		$this->_labels = array(
82
+			'buttons' => array(
83
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
+			),
85
+		);
86
+	}
87
+
88
+
89
+	/**
90
+	 *_set_page_routes
91
+	 */
92
+	protected function _set_page_routes()
93
+	{
94
+		$qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0;
95
+		$this->_page_routes = array(
96
+			'default' => array(
97
+				'func'       => '_questions_overview_list_table',
98
+				'capability' => 'ee_read_questions',
99
+			),
100
+
101
+			'edit_question' => array(
102
+				'func'       => '_edit_question',
103
+				'capability' => 'ee_edit_question',
104
+				'obj_id'     => $qst_id,
105
+				'args'       => array('edit'),
106
+			),
107
+
108
+			'question_groups' => array(
109
+				'func'       => '_questions_groups_preview',
110
+				'capability' => 'ee_read_question_groups',
111
+			),
112
+
113
+			'update_question' => array(
114
+				'func'       => '_insert_or_update_question',
115
+				'args'       => array('new_question' => false),
116
+				'capability' => 'ee_edit_question',
117
+				'obj_id'     => $qst_id,
118
+				'noheader'   => true,
119
+			),
120
+		);
121
+	}
122
+
123
+
124
+	protected function _set_page_config()
125
+	{
126
+		$this->_page_config = array(
127
+			'default' => array(
128
+				'nav'           => array(
129
+					'label' => esc_html__('Questions', 'event_espresso'),
130
+					'order' => 10,
131
+				),
132
+				'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
133
+				'metaboxes'     => $this->_default_espresso_metaboxes,
134
+				'help_tabs'     => array(
135
+					'registration_form_questions_overview_help_tab'                           => array(
136
+						'title'    => esc_html__('Questions Overview', 'event_espresso'),
137
+						'filename' => 'registration_form_questions_overview',
138
+					),
139
+					'registration_form_questions_overview_table_column_headings_help_tab'     => array(
140
+						'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
141
+						'filename' => 'registration_form_questions_overview_table_column_headings',
142
+					),
143
+					'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array(
144
+						'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
145
+						'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
146
+					),
147
+				),
148
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
149
+				// 'help_tour'     => array('Registration_Form_Questions_Overview_Help_Tour'),
150
+				'require_nonce' => false,
151
+				'qtips'         => array(
152
+					'EE_Registration_Form_Tips',
153
+				)/**/
154
+			),
155
+
156
+			'question_groups' => array(
157
+				'nav'           => array(
158
+					'label' => esc_html__('Question Groups', 'event_espresso'),
159
+					'order' => 20,
160
+				),
161
+				'metaboxes'     => $this->_default_espresso_metaboxes,
162
+				'help_tabs'     => array(
163
+					'registration_form_question_groups_help_tab' => array(
164
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
165
+						'filename' => 'registration_form_question_groups',
166
+					),
167
+				),
168
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
169
+				// 'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
170
+				'require_nonce' => false,
171
+			),
172
+
173
+			'edit_question' => array(
174
+				'nav'           => array(
175
+					'label'      => esc_html__('Edit Question', 'event_espresso'),
176
+					'order'      => 15,
177
+					'persistent' => false,
178
+					'url'        => isset($this->_req_data['question_id']) ? add_query_arg(
179
+						array('question_id' => $this->_req_data['question_id']),
180
+						$this->_current_page_view_url
181
+					) : $this->_admin_base_url,
182
+				),
183
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
184
+				'help_tabs'     => array(
185
+					'registration_form_edit_question_group_help_tab' => array(
186
+						'title'    => esc_html__('Edit Question', 'event_espresso'),
187
+						'filename' => 'registration_form_edit_question',
188
+					),
189
+				),
190
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
191
+				// 'help_tour'     => array('Registration_Form_Edit_Question_Help_Tour'),
192
+				'require_nonce' => false,
193
+			),
194
+		);
195
+	}
196
+
197
+
198
+	protected function _add_screen_options()
199
+	{
200
+		// todo
201
+	}
202
+
203
+	protected function _add_screen_options_default()
204
+	{
205
+		$page_title = $this->_admin_page_title;
206
+		$this->_admin_page_title = esc_html__('Questions', 'event_espresso');
207
+		$this->_per_page_screen_option();
208
+		$this->_admin_page_title = $page_title;
209
+	}
210
+
211
+	protected function _add_screen_options_question_groups()
212
+	{
213
+		$page_title = $this->_admin_page_title;
214
+		$this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
215
+		$this->_per_page_screen_option();
216
+		$this->_admin_page_title = $page_title;
217
+	}
218
+
219
+	// none of the below group are currently used for Event Categories
220
+	protected function _add_feature_pointers()
221
+	{
222
+	}
223
+
224
+	public function load_scripts_styles()
225
+	{
226
+		wp_register_style(
227
+			'espresso_registration',
228
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
229
+			array(),
230
+			EVENT_ESPRESSO_VERSION
231
+		);
232
+		wp_enqueue_style('espresso_registration');
233
+	}
234
+
235
+	public function admin_init()
236
+	{
237
+	}
238
+
239
+	public function admin_notices()
240
+	{
241
+	}
242
+
243
+	public function admin_footer_scripts()
244
+	{
245
+	}
246
+
247
+
248
+	public function load_scripts_styles_default()
249
+	{
250
+	}
251
+
252
+
253
+	public function load_scripts_styles_add_question()
254
+	{
255
+		$this->load_scripts_styles_question_details();
256
+	}
257
+
258
+	public function load_scripts_styles_edit_question()
259
+	{
260
+		$this->load_scripts_styles_question_details();
261
+	}
262
+
263
+	/**
264
+	 * Loads the JS required for adding or editing a question
265
+	 */
266
+	protected function load_scripts_styles_question_details()
267
+	{
268
+		$this->load_scripts_styles_forms();
269
+		wp_register_script(
270
+			'espresso_registration_form_single',
271
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
272
+			array('jquery-ui-sortable'),
273
+			EVENT_ESPRESSO_VERSION,
274
+			true
275
+		);
276
+		wp_enqueue_script('espresso_registration_form_single');
277
+		wp_localize_script(
278
+			'espresso_registration_form_single',
279
+			'ee_question_data',
280
+			array(
281
+				'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
282
+				'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
283
+			)
284
+		);
285
+	}
286
+
287
+
288
+	public function recaptcha_info_help_tab()
289
+	{
290
+		$template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
291
+		EEH_Template::display_template($template, array());
292
+	}
293
+
294
+
295
+	public function load_scripts_styles_forms()
296
+	{
297
+		// styles
298
+		wp_enqueue_style('espresso-ui-theme');
299
+		// scripts
300
+		wp_enqueue_script('ee_admin_js');
301
+	}
302
+
303
+
304
+	protected function _set_list_table_views_default()
305
+	{
306
+		$this->_views = array(
307
+			'all' => array(
308
+				'slug'  => 'all',
309
+				'label' => esc_html__('View All Questions', 'event_espresso'),
310
+				'count' => 0,
311
+			),
312
+		);
313
+
314
+		if (EE_Registry::instance()->CAP->current_user_can(
315
+			'ee_delete_questions',
316
+			'espresso_registration_form_trash_questions'
317
+		)
318
+		) {
319
+			$this->_views['trash'] = array(
320
+				'slug'  => 'trash',
321
+				'label' => esc_html__('Trash', 'event_espresso'),
322
+				'count' => 0,
323
+			);
324
+		}
325
+	}
326
+
327
+	/**
328
+	 * This just previews the question groups tab that comes in caffeinated.
329
+	 *
330
+	 * @return string html
331
+	 */
332
+	protected function _questions_groups_preview()
333
+	{
334
+		$this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso');
335
+		$this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
336
+											   . esc_attr__(
337
+												   'Preview Question Groups Overview List Table screenshot',
338
+												   'event_espresso'
339
+											   ) . '" />';
340
+		$this->_template_args['preview_text'] = '<strong>'
341
+												. esc_html__(
342
+													'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
343
+													'event_espresso'
344
+												) . '</strong>';
345
+		$this->display_admin_caf_preview_page('question_groups_tab');
346
+	}
347
+
348
+
349
+	/**
350
+	 * Extracts the question field's values from the POST request to update or insert them
351
+	 *
352
+	 * @param \EEM_Base $model
353
+	 * @return array where each key is the name of a model's field/db column, and each value is its value.
354
+	 */
355
+	protected function _set_column_values_for(EEM_Base $model)
356
+	{
357
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
358
+		$set_column_values = array();
359
+
360
+		// some initial checks for proper values.
361
+		// if QST_admin_only, then no matter what QST_required is we disable.
362
+		if (! empty($this->_req_data['QST_admin_only'])) {
363
+			$this->_req_data['QST_required'] = 0;
364
+		}
365
+		// if the question shouldn't have a max length, don't let them set one
366
+		if (! isset(
367
+			$this->_req_data['QST_type'],
368
+			$this->_req_data['QST_max']
369
+		)
370
+			|| ! in_array(
371
+				$this->_req_data['QST_type'],
372
+				EEM_Question::instance()->questionTypesWithMaxLength(),
373
+				true
374
+			)
375
+		) {
376
+			// they're not allowed to set the max
377
+			$this->_req_data['QST_max'] = null;
378
+		}
379
+		foreach ($model->field_settings() as $fieldName => $settings) {
380
+			// basically if QSG_identifier is empty or not set
381
+			if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) {
382
+				$QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : '';
383
+				$set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
384
+			} //if the admin label is blank, use a slug version of the question text
385
+			elseif ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) {
386
+				$QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : '';
387
+				$set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
388
+			} elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
389
+				$set_column_values[ $fieldName ] = 0;
390
+			} elseif ($fieldName === 'QST_max') {
391
+				$qst_system = EEM_Question::instance()->get_var(
392
+					array(
393
+						array(
394
+							'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0,
395
+						),
396
+					),
397
+					'QST_system'
398
+				);
399
+				$max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system);
400
+				if (empty($this->_req_data['QST_max']) ||
401
+					$this->_req_data['QST_max'] > $max_max
402
+				) {
403
+					$set_column_values[ $fieldName ] = $max_max;
404
+				}
405
+			}
406
+
407
+
408
+			// only add a property to the array if it's not null (otherwise the model should just use the default value)
409
+			if (! isset($set_column_values[ $fieldName ]) &&
410
+				isset($this->_req_data[ $fieldName ])
411
+			) {
412
+				$set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
413
+			}
414
+		}
415
+		return $set_column_values;// validation fo this data to be performed by the model before insertion.
416
+	}
417
+
418
+
419
+	/**
420
+	 *_questions_overview_list_table
421
+	 */
422
+	protected function _questions_overview_list_table()
423
+	{
424
+		$this->_search_btn_label = esc_html__('Questions', 'event_espresso');
425
+		$this->display_admin_list_table_page_with_sidebar();
426
+	}
427
+
428
+
429
+	/**
430
+	 * _edit_question
431
+	 */
432
+	protected function _edit_question()
433
+	{
434
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
435
+		$ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint(
436
+			$this->_req_data['QST_ID']
437
+		) : false;
438
+
439
+		switch ($this->_req_action) {
440
+			case 'add_question':
441
+				$this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
442
+				break;
443
+			case 'edit_question':
444
+				$this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
445
+				break;
446
+			default:
447
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
448
+		}
449
+
450
+		// add PRC_ID to title if editing
451
+		$this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
452
+		if ($ID) {
453
+			$question = $this->_question_model->get_one_by_ID($ID);
454
+			$additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID));
455
+			$this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
456
+		} else {
457
+			$question = EE_Question::new_instance();
458
+			$question->set_order_to_latest();
459
+			$this->_set_add_edit_form_tags('insert_question');
460
+		}
461
+		if ($question->system_ID() === EEM_Attendee::system_question_phone) {
462
+			$question_types = array_intersect_key(
463
+				EEM_Question::instance()->allowed_question_types(),
464
+				array_flip(
465
+					array(
466
+						EEM_Question::QST_type_text,
467
+						EEM_Question::QST_type_us_phone,
468
+					)
469
+				)
470
+			);
471
+		} else {
472
+			$question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category(
473
+				$question->type()
474
+			) : $this->_question_model->allowed_question_types();
475
+		}
476
+		$this->_template_args['QST_ID'] = $ID;
477
+		$this->_template_args['question'] = $question;
478
+		$this->_template_args['question_types'] = $question_types;
479
+		$this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question(
480
+			$question->system_ID()
481
+		);
482
+		$this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
483
+		$this->_set_publish_post_box_vars('id', $ID);
484
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
485
+			REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
486
+			$this->_template_args,
487
+			true
488
+		);
489
+
490
+		// the details template wrapper
491
+		$this->display_admin_page_with_sidebar();
492
+	}
493
+
494
+
495
+	/**
496
+	 * @return string
497
+	 */
498
+	protected function _get_question_type_descriptions()
499
+	{
500
+		EE_Registry::instance()->load_helper('HTML');
501
+		$descriptions = '';
502
+		$question_type_descriptions = EEM_Question::instance()->question_descriptions();
503
+		foreach ($question_type_descriptions as $type => $question_type_description) {
504
+			if ($type == 'HTML_TEXTAREA') {
505
+				$html = new EE_Simple_HTML_Validation_Strategy();
506
+				$question_type_description .= sprintf(
507
+					esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
508
+					'<br/>',
509
+					$html->get_list_of_allowed_tags()
510
+				);
511
+			}
512
+			$descriptions .= EEH_HTML::p(
513
+				$question_type_description,
514
+				'question_type_description-' . $type,
515
+				'question_type_description description',
516
+				'display:none;'
517
+			);
518
+		}
519
+		return $descriptions;
520
+	}
521
+
522
+
523
+	/**
524
+	 * @param bool|true $new_question
525
+	 * @throws \EE_Error
526
+	 */
527
+	protected function _insert_or_update_question($new_question = true)
528
+	{
529
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
530
+		$set_column_values = $this->_set_column_values_for($this->_question_model);
531
+		if ($new_question) {
532
+			$question = EE_Question::new_instance($set_column_values);
533
+			$action_desc = 'added';
534
+		} else {
535
+			$question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
536
+			foreach ($set_column_values as $field => $new_value) {
537
+				$question->set($field, $new_value);
538
+			}
539
+			$action_desc = 'updated';
540
+		}
541
+		$success = $question->save();
542
+		$ID = $question->ID();
543
+		if ($ID && $question->should_have_question_options()) {
544
+			// save the related options
545
+			// trash removed options, save old ones
546
+			// get list of all options
547
+			$options = $question->options();
548
+			if (! empty($options)) {
549
+				foreach ($options as $option_ID => $option) {
550
+					$option_req_index = $this->_get_option_req_data_index($option_ID);
551
+					if ($option_req_index !== false) {
552
+						$option->save($this->_req_data['question_options'][ $option_req_index ]);
553
+					} else {
554
+						// not found, remove it
555
+						$option->delete();
556
+					}
557
+				}
558
+			}
559
+			// save new related options
560
+			foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
561
+				// skip $index that is from our sample
562
+				if ($index === 'xxcountxx') {
563
+					continue;
564
+				}
565
+				// note we allow saving blank options.
566
+				if (empty($option_req_data['QSO_ID'])
567
+				) {// no ID! save it!
568
+					$new_option = EE_Question_Option::new_instance(
569
+						array(
570
+							'QSO_value' => $option_req_data['QSO_value'],
571
+							'QSO_desc'  => $option_req_data['QSO_desc'],
572
+							'QSO_order' => $option_req_data['QSO_order'],
573
+							'QST_ID'    => $question->ID(),
574
+						)
575
+					);
576
+					$new_option->save();
577
+				}
578
+			}
579
+		}
580
+		$query_args = array('action' => 'edit_question', 'QST_ID' => $ID);
581
+		if ($success !== false) {
582
+			$msg = $new_question
583
+				? sprintf(
584
+					esc_html__('The %s has been created', 'event_espresso'),
585
+					$this->_question_model->item_name()
586
+				)
587
+				: sprintf(
588
+					esc_html__('The %s has been updated', 'event_espresso'),
589
+					$this->_question_model->item_name()
590
+				);
591
+			EE_Error::add_success($msg);
592
+		}
593
+
594
+		$this->_redirect_after_action(false, '', $action_desc, $query_args, true);
595
+	}
596
+
597
+
598
+	/**
599
+	 * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
600
+	 * by ID
601
+	 * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
602
+	 * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
603
+	 *
604
+	 * @param int $ID of the question option to find
605
+	 * @return int index in question_options array if successful, FALSE if unsuccessful
606
+	 */
607
+	protected function _get_option_req_data_index($ID)
608
+	{
609
+		$req_data_for_question_options = $this->_req_data['question_options'];
610
+		foreach ($req_data_for_question_options as $num => $option_data) {
611
+			if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
612
+				return $num;
613
+			}
614
+		}
615
+		return false;
616
+	}
617
+
618
+
619
+
620
+
621
+	/***********/
622
+	/* QUERIES */
623
+	/**
624
+	 * For internal use in getting all the query parameters
625
+	 * (because it's pretty well the same between question, question groups,
626
+	 * and for both when searching for trashed and untrashed ones)
627
+	 *
628
+	 * @param EEM_Base $model either EEM_Question or EEM_Question_Group
629
+	 * @param int      $per_page
630
+	 * @param int      $current_page
631
+	 * @return array model query params, @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
632
+	 */
633
+	protected function get_query_params($model, $per_page = 10, $current_page = 10)
634
+	{
635
+		$query_params = array();
636
+		$offset = ($current_page - 1) * $per_page;
637
+		$query_params['limit'] = array($offset, $per_page);
638
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
639
+			: 'ASC';
640
+		$orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
641
+		$field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
642
+		$query_params['order_by'] = array($field_to_order_by => $order);
643
+		$search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
644
+		if (! empty($search_string)) {
645
+			if ($model instanceof EEM_Question_Group) {
646
+				$query_params[0] = array(
647
+					'OR' => array(
648
+						'QSG_name' => array('LIKE', "%$search_string%"),
649
+						'QSG_desc' => array('LIKE', "%$search_string%"),
650
+					),
651
+				);
652
+			} else {
653
+				$query_params[0] = array(
654
+					'QST_display_text' => array('LIKE', "%$search_string%"),
655
+				);
656
+			}
657
+		}
658
+
659
+		// capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
660
+		/*if ( $model instanceof EEM_Question_Group ) {
661 661
             if ( ! EE_Registry::instance()->CAP->current_user_can( 'edit_others_question_groups', 'espresso_registration_form_edit_question_group' ) ) {
662 662
                 $query_params[0] = array(
663 663
                     'AND' => array(
@@ -687,59 +687,59 @@  discard block
 block discarded – undo
687 687
             }
688 688
         }/**/
689 689
 
690
-        return $query_params;
691
-    }
692
-
693
-
694
-    /**
695
-     * @param int        $per_page
696
-     * @param int        $current_page
697
-     * @param bool|false $count
698
-     * @return \EE_Soft_Delete_Base_Class[]|int
699
-     */
700
-    public function get_questions($per_page = 10, $current_page = 1, $count = false)
701
-    {
702
-        $QST = EEM_Question::instance();
703
-        $query_params = $this->get_query_params($QST, $per_page, $current_page);
704
-        if ($count) {
705
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
706
-            $results = $QST->count($where);
707
-        } else {
708
-            $results = $QST->get_all($query_params);
709
-        }
710
-        return $results;
711
-    }
712
-
713
-
714
-    /**
715
-     * @param            $per_page
716
-     * @param int        $current_page
717
-     * @param bool|false $count
718
-     * @return \EE_Soft_Delete_Base_Class[]|int
719
-     */
720
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
721
-    {
722
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
723
-        $where = isset($query_params[0]) ? array($query_params[0]) : array();
724
-        $questions = $count ? EEM_Question::instance()->count_deleted($where)
725
-            : EEM_Question::instance()->get_all_deleted($query_params);
726
-        return $questions;
727
-    }
728
-
729
-
730
-    /**
731
-     * @param            $per_page
732
-     * @param int        $current_page
733
-     * @param bool|false $count
734
-     * @return \EE_Soft_Delete_Base_Class[]
735
-     */
736
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
737
-    {
738
-        /** @type EEM_Question_Group $questionGroupModel */
739
-        $questionGroupModel = EEM_Question_Group::instance();
740
-        // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
741
-        return $questionGroupModel->get_all(
742
-            $this->get_query_params($questionGroupModel, $per_page, $current_page)
743
-        );
744
-    }
690
+		return $query_params;
691
+	}
692
+
693
+
694
+	/**
695
+	 * @param int        $per_page
696
+	 * @param int        $current_page
697
+	 * @param bool|false $count
698
+	 * @return \EE_Soft_Delete_Base_Class[]|int
699
+	 */
700
+	public function get_questions($per_page = 10, $current_page = 1, $count = false)
701
+	{
702
+		$QST = EEM_Question::instance();
703
+		$query_params = $this->get_query_params($QST, $per_page, $current_page);
704
+		if ($count) {
705
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
706
+			$results = $QST->count($where);
707
+		} else {
708
+			$results = $QST->get_all($query_params);
709
+		}
710
+		return $results;
711
+	}
712
+
713
+
714
+	/**
715
+	 * @param            $per_page
716
+	 * @param int        $current_page
717
+	 * @param bool|false $count
718
+	 * @return \EE_Soft_Delete_Base_Class[]|int
719
+	 */
720
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
721
+	{
722
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
723
+		$where = isset($query_params[0]) ? array($query_params[0]) : array();
724
+		$questions = $count ? EEM_Question::instance()->count_deleted($where)
725
+			: EEM_Question::instance()->get_all_deleted($query_params);
726
+		return $questions;
727
+	}
728
+
729
+
730
+	/**
731
+	 * @param            $per_page
732
+	 * @param int        $current_page
733
+	 * @param bool|false $count
734
+	 * @return \EE_Soft_Delete_Base_Class[]
735
+	 */
736
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
737
+	{
738
+		/** @type EEM_Question_Group $questionGroupModel */
739
+		$questionGroupModel = EEM_Question_Group::instance();
740
+		// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
741
+		return $questionGroupModel->get_all(
742
+			$this->get_query_params($questionGroupModel, $per_page, $current_page)
743
+		);
744
+	}
745 745
 }
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 1 patch
Indentation   +3708 added lines, -3708 removed lines patch added patch discarded remove patch
@@ -18,2230 +18,2230 @@  discard block
 block discarded – undo
18 18
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
19 19
 {
20 20
 
21
-    /**
22
-     * @var EE_Registration
23
-     */
24
-    private $_registration;
25
-
26
-    /**
27
-     * @var EE_Event
28
-     */
29
-    private $_reg_event;
30
-
31
-    /**
32
-     * @var EE_Session
33
-     */
34
-    private $_session;
35
-
36
-    private static $_reg_status;
37
-
38
-    /**
39
-     * Form for displaying the custom questions for this registration.
40
-     * This gets used a few times throughout the request so its best to cache it
41
-     *
42
-     * @var EE_Registration_Custom_Questions_Form
43
-     */
44
-    protected $_reg_custom_questions_form = null;
45
-
46
-    /**
47
-     * @var EEM_Registration $registration_model
48
-     */
49
-    private $registration_model;
50
-
51
-    /**
52
-     * @var EEM_Attendee $attendee_model
53
-     */
54
-    private $attendee_model;
55
-
56
-    /**
57
-     * @var EEM_Event $event_model
58
-     */
59
-    private $event_model;
60
-
61
-    /**
62
-     * @var EEM_Status $status_model
63
-     */
64
-    private $status_model;
65
-
66
-
67
-    /**
68
-     * @param bool $routing
69
-     * @throws EE_Error
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws ReflectionException
74
-     */
75
-    public function __construct($routing = true)
76
-    {
77
-        parent::__construct($routing);
78
-        add_action('wp_loaded', array($this, 'wp_loaded'));
79
-    }
80
-
81
-    /**
82
-     * @return EEM_Registration
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidInterfaceException
86
-     * @since 4.10.2.p
87
-     */
88
-    protected function getRegistrationModel()
89
-    {
90
-        if (! $this->registration_model instanceof EEM_Registration) {
91
-            $this->registration_model = $this->getLoader()->getShared('EEM_Registration');
92
-        }
93
-        return $this->registration_model;
94
-    }
95
-
96
-    /**
97
-     * @return EEM_Attendee
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidDataTypeException
100
-     * @throws InvalidInterfaceException
101
-     * @since 4.10.2.p
102
-     */
103
-    protected function getAttendeeModel()
104
-    {
105
-        if (! $this->attendee_model instanceof EEM_Attendee) {
106
-            $this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
107
-        }
108
-        return $this->attendee_model;
109
-    }
110
-
111
-
112
-    /**
113
-     * @return EEM_Event
114
-     * @throws InvalidArgumentException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidInterfaceException
117
-     * @since 4.10.2.p
118
-     */
119
-    protected function getEventModel()
120
-    {
121
-        if (! $this->event_model instanceof EEM_Event) {
122
-            $this->event_model = $this->getLoader()->getShared('EEM_Event');
123
-        }
124
-        return $this->event_model;
125
-    }
126
-
127
-    /**
128
-     * @return EEM_Status
129
-     * @throws InvalidArgumentException
130
-     * @throws InvalidDataTypeException
131
-     * @throws InvalidInterfaceException
132
-     * @since 4.10.2.p
133
-     */
134
-    protected function getStatusModel()
135
-    {
136
-        if (! $this->status_model instanceof EEM_Status) {
137
-            $this->status_model = $this->getLoader()->getShared('EEM_Status');
138
-        }
139
-        return $this->status_model;
140
-    }
141
-
142
-
143
-    public function wp_loaded()
144
-    {
145
-        // when adding a new registration...
146
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
147
-            EE_System::do_not_cache();
148
-            if (! isset($this->_req_data['processing_registration'])
149
-                || absint($this->_req_data['processing_registration']) !== 1
150
-            ) {
151
-                // and it's NOT the attendee information reg step
152
-                // force cookie expiration by setting time to last week
153
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
154
-                // and update the global
155
-                $_COOKIE['ee_registration_added'] = 0;
156
-            }
157
-        }
158
-    }
159
-
160
-
161
-    protected function _init_page_props()
162
-    {
163
-        $this->page_slug = REG_PG_SLUG;
164
-        $this->_admin_base_url = REG_ADMIN_URL;
165
-        $this->_admin_base_path = REG_ADMIN;
166
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
167
-        $this->_cpt_routes = array(
168
-            'add_new_attendee' => 'espresso_attendees',
169
-            'edit_attendee'    => 'espresso_attendees',
170
-            'insert_attendee'  => 'espresso_attendees',
171
-            'update_attendee'  => 'espresso_attendees',
172
-        );
173
-        $this->_cpt_model_names = array(
174
-            'add_new_attendee' => 'EEM_Attendee',
175
-            'edit_attendee'    => 'EEM_Attendee',
176
-        );
177
-        $this->_cpt_edit_routes = array(
178
-            'espresso_attendees' => 'edit_attendee',
179
-        );
180
-        $this->_pagenow_map = array(
181
-            'add_new_attendee' => 'post-new.php',
182
-            'edit_attendee'    => 'post.php',
183
-            'trash'            => 'post.php',
184
-        );
185
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
186
-        // add filters so that the comment urls don't take users to a confusing 404 page
187
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
188
-    }
189
-
190
-
191
-    public function clear_comment_link($link, $comment, $args)
192
-    {
193
-        // gotta make sure this only happens on this route
194
-        $post_type = get_post_type($comment->comment_post_ID);
195
-        if ($post_type === 'espresso_attendees') {
196
-            return '#commentsdiv';
197
-        }
198
-        return $link;
199
-    }
200
-
201
-
202
-    protected function _ajax_hooks()
203
-    {
204
-        // todo: all hooks for registrations ajax goes in here
205
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
206
-    }
207
-
208
-
209
-    protected function _define_page_props()
210
-    {
211
-        $this->_admin_page_title = $this->page_label;
212
-        $this->_labels = array(
213
-            'buttons'                      => array(
214
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
215
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
216
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
217
-                'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
218
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
219
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
220
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
221
-                'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
222
-            ),
223
-            'publishbox'                   => array(
224
-                'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
225
-                'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
226
-            ),
227
-            'hide_add_button_on_cpt_route' => array(
228
-                'edit_attendee' => true,
229
-            ),
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     *        grab url requests and route them
236
-     *
237
-     * @access private
238
-     * @return void
239
-     * @throws EE_Error
240
-     */
241
-    public function _set_page_routes()
242
-    {
243
-        $this->_get_registration_status_array();
244
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
245
-            ? $this->_req_data['_REG_ID'] : 0;
246
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
247
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
248
-            : $reg_id;
249
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
250
-            ? $this->_req_data['ATT_ID'] : 0;
251
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
252
-            ? $this->_req_data['post']
253
-            : $att_id;
254
-        $this->_page_routes = array(
255
-            'default'                             => array(
256
-                'func'       => '_registrations_overview_list_table',
257
-                'capability' => 'ee_read_registrations',
258
-            ),
259
-            'view_registration'                   => array(
260
-                'func'       => '_registration_details',
261
-                'capability' => 'ee_read_registration',
262
-                'obj_id'     => $reg_id,
263
-            ),
264
-            'edit_registration'                   => array(
265
-                'func'               => '_update_attendee_registration_form',
266
-                'noheader'           => true,
267
-                'headers_sent_route' => 'view_registration',
268
-                'capability'         => 'ee_edit_registration',
269
-                'obj_id'             => $reg_id,
270
-                '_REG_ID'            => $reg_id,
271
-            ),
272
-            'trash_registrations'                 => array(
273
-                'func'       => '_trash_or_restore_registrations',
274
-                'args'       => array('trash' => true),
275
-                'noheader'   => true,
276
-                'capability' => 'ee_delete_registrations',
277
-            ),
278
-            'restore_registrations'               => array(
279
-                'func'       => '_trash_or_restore_registrations',
280
-                'args'       => array('trash' => false),
281
-                'noheader'   => true,
282
-                'capability' => 'ee_delete_registrations',
283
-            ),
284
-            'delete_registrations'                => array(
285
-                'func'       => '_delete_registrations',
286
-                'noheader'   => true,
287
-                'capability' => 'ee_delete_registrations',
288
-            ),
289
-            'new_registration'                    => array(
290
-                'func'       => 'new_registration',
291
-                'capability' => 'ee_edit_registrations',
292
-            ),
293
-            'process_reg_step'                    => array(
294
-                'func'       => 'process_reg_step',
295
-                'noheader'   => true,
296
-                'capability' => 'ee_edit_registrations',
297
-            ),
298
-            'redirect_to_txn'                     => array(
299
-                'func'       => 'redirect_to_txn',
300
-                'noheader'   => true,
301
-                'capability' => 'ee_edit_registrations',
302
-            ),
303
-            'change_reg_status'                   => array(
304
-                'func'       => '_change_reg_status',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'approve_registration'                => array(
310
-                'func'       => 'approve_registration',
311
-                'noheader'   => true,
312
-                'capability' => 'ee_edit_registration',
313
-                'obj_id'     => $reg_id,
314
-            ),
315
-            'approve_and_notify_registration'     => array(
316
-                'func'       => 'approve_registration',
317
-                'noheader'   => true,
318
-                'args'       => array(true),
319
-                'capability' => 'ee_edit_registration',
320
-                'obj_id'     => $reg_id,
321
-            ),
322
-            'approve_registrations'               => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('approve'),
327
-            ),
328
-            'approve_and_notify_registrations'    => array(
329
-                'func'       => 'bulk_action_on_registrations',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registrations',
332
-                'args'       => array('approve', true),
333
-            ),
334
-            'decline_registration'                => array(
335
-                'func'       => 'decline_registration',
336
-                'noheader'   => true,
337
-                'capability' => 'ee_edit_registration',
338
-                'obj_id'     => $reg_id,
339
-            ),
340
-            'decline_and_notify_registration'     => array(
341
-                'func'       => 'decline_registration',
342
-                'noheader'   => true,
343
-                'args'       => array(true),
344
-                'capability' => 'ee_edit_registration',
345
-                'obj_id'     => $reg_id,
346
-            ),
347
-            'decline_registrations'               => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('decline'),
352
-            ),
353
-            'decline_and_notify_registrations'    => array(
354
-                'func'       => 'bulk_action_on_registrations',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registrations',
357
-                'args'       => array('decline', true),
358
-            ),
359
-            'pending_registration'                => array(
360
-                'func'       => 'pending_registration',
361
-                'noheader'   => true,
362
-                'capability' => 'ee_edit_registration',
363
-                'obj_id'     => $reg_id,
364
-            ),
365
-            'pending_and_notify_registration'     => array(
366
-                'func'       => 'pending_registration',
367
-                'noheader'   => true,
368
-                'args'       => array(true),
369
-                'capability' => 'ee_edit_registration',
370
-                'obj_id'     => $reg_id,
371
-            ),
372
-            'pending_registrations'               => array(
373
-                'func'       => 'bulk_action_on_registrations',
374
-                'noheader'   => true,
375
-                'capability' => 'ee_edit_registrations',
376
-                'args'       => array('pending'),
377
-            ),
378
-            'pending_and_notify_registrations'    => array(
379
-                'func'       => 'bulk_action_on_registrations',
380
-                'noheader'   => true,
381
-                'capability' => 'ee_edit_registrations',
382
-                'args'       => array('pending', true),
383
-            ),
384
-            'no_approve_registration'             => array(
385
-                'func'       => 'not_approve_registration',
386
-                'noheader'   => true,
387
-                'capability' => 'ee_edit_registration',
388
-                'obj_id'     => $reg_id,
389
-            ),
390
-            'no_approve_and_notify_registration'  => array(
391
-                'func'       => 'not_approve_registration',
392
-                'noheader'   => true,
393
-                'args'       => array(true),
394
-                'capability' => 'ee_edit_registration',
395
-                'obj_id'     => $reg_id,
396
-            ),
397
-            'no_approve_registrations'            => array(
398
-                'func'       => 'bulk_action_on_registrations',
399
-                'noheader'   => true,
400
-                'capability' => 'ee_edit_registrations',
401
-                'args'       => array('not_approve'),
402
-            ),
403
-            'no_approve_and_notify_registrations' => array(
404
-                'func'       => 'bulk_action_on_registrations',
405
-                'noheader'   => true,
406
-                'capability' => 'ee_edit_registrations',
407
-                'args'       => array('not_approve', true),
408
-            ),
409
-            'cancel_registration'                 => array(
410
-                'func'       => 'cancel_registration',
411
-                'noheader'   => true,
412
-                'capability' => 'ee_edit_registration',
413
-                'obj_id'     => $reg_id,
414
-            ),
415
-            'cancel_and_notify_registration'      => array(
416
-                'func'       => 'cancel_registration',
417
-                'noheader'   => true,
418
-                'args'       => array(true),
419
-                'capability' => 'ee_edit_registration',
420
-                'obj_id'     => $reg_id,
421
-            ),
422
-            'cancel_registrations'                => array(
423
-                'func'       => 'bulk_action_on_registrations',
424
-                'noheader'   => true,
425
-                'capability' => 'ee_edit_registrations',
426
-                'args'       => array('cancel'),
427
-            ),
428
-            'cancel_and_notify_registrations'     => array(
429
-                'func'       => 'bulk_action_on_registrations',
430
-                'noheader'   => true,
431
-                'capability' => 'ee_edit_registrations',
432
-                'args'       => array('cancel', true),
433
-            ),
434
-            'wait_list_registration'              => array(
435
-                'func'       => 'wait_list_registration',
436
-                'noheader'   => true,
437
-                'capability' => 'ee_edit_registration',
438
-                'obj_id'     => $reg_id,
439
-            ),
440
-            'wait_list_and_notify_registration'   => array(
441
-                'func'       => 'wait_list_registration',
442
-                'noheader'   => true,
443
-                'args'       => array(true),
444
-                'capability' => 'ee_edit_registration',
445
-                'obj_id'     => $reg_id,
446
-            ),
447
-            'contact_list'                        => array(
448
-                'func'       => '_attendee_contact_list_table',
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-            'add_new_attendee'                    => array(
452
-                'func' => '_create_new_cpt_item',
453
-                'args' => array(
454
-                    'new_attendee' => true,
455
-                    'capability'   => 'ee_edit_contacts',
456
-                ),
457
-            ),
458
-            'edit_attendee'                       => array(
459
-                'func'       => '_edit_cpt_item',
460
-                'capability' => 'ee_edit_contacts',
461
-                'obj_id'     => $att_id,
462
-            ),
463
-            'duplicate_attendee'                  => array(
464
-                'func'       => '_duplicate_attendee',
465
-                'noheader'   => true,
466
-                'capability' => 'ee_edit_contacts',
467
-                'obj_id'     => $att_id,
468
-            ),
469
-            'insert_attendee'                     => array(
470
-                'func'       => '_insert_or_update_attendee',
471
-                'args'       => array(
472
-                    'new_attendee' => true,
473
-                ),
474
-                'noheader'   => true,
475
-                'capability' => 'ee_edit_contacts',
476
-            ),
477
-            'update_attendee'                     => array(
478
-                'func'       => '_insert_or_update_attendee',
479
-                'args'       => array(
480
-                    'new_attendee' => false,
481
-                ),
482
-                'noheader'   => true,
483
-                'capability' => 'ee_edit_contacts',
484
-                'obj_id'     => $att_id,
485
-            ),
486
-            'trash_attendees'                     => array(
487
-                'func'       => '_trash_or_restore_attendees',
488
-                'args'       => array(
489
-                    'trash' => 'true',
490
-                ),
491
-                'noheader'   => true,
492
-                'capability' => 'ee_delete_contacts',
493
-            ),
494
-            'trash_attendee'                      => array(
495
-                'func'       => '_trash_or_restore_attendees',
496
-                'args'       => array(
497
-                    'trash' => true,
498
-                ),
499
-                'noheader'   => true,
500
-                'capability' => 'ee_delete_contacts',
501
-                'obj_id'     => $att_id,
502
-            ),
503
-            'restore_attendees'                   => array(
504
-                'func'       => '_trash_or_restore_attendees',
505
-                'args'       => array(
506
-                    'trash' => false,
507
-                ),
508
-                'noheader'   => true,
509
-                'capability' => 'ee_delete_contacts',
510
-                'obj_id'     => $att_id,
511
-            ),
512
-            'resend_registration'                 => array(
513
-                'func'       => '_resend_registration',
514
-                'noheader'   => true,
515
-                'capability' => 'ee_send_message',
516
-            ),
517
-            'registrations_report'                => array(
518
-                'func'       => '_registrations_report',
519
-                'noheader'   => true,
520
-                'capability' => 'ee_read_registrations',
521
-            ),
522
-            'contact_list_export'                 => array(
523
-                'func'       => '_contact_list_export',
524
-                'noheader'   => true,
525
-                'capability' => 'export',
526
-            ),
527
-            'contact_list_report'                 => array(
528
-                'func'       => '_contact_list_report',
529
-                'noheader'   => true,
530
-                'capability' => 'ee_read_contacts',
531
-            ),
532
-        );
533
-    }
534
-
535
-
536
-    protected function _set_page_config()
537
-    {
538
-        $this->_page_config = array(
539
-            'default'           => array(
540
-                'nav'           => array(
541
-                    'label' => esc_html__('Overview', 'event_espresso'),
542
-                    'order' => 5,
543
-                ),
544
-                'help_tabs'     => array(
545
-                    'registrations_overview_help_tab'                       => array(
546
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
547
-                        'filename' => 'registrations_overview',
548
-                    ),
549
-                    'registrations_overview_table_column_headings_help_tab' => array(
550
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
551
-                        'filename' => 'registrations_overview_table_column_headings',
552
-                    ),
553
-                    'registrations_overview_filters_help_tab'               => array(
554
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
555
-                        'filename' => 'registrations_overview_filters',
556
-                    ),
557
-                    'registrations_overview_views_help_tab'                 => array(
558
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
559
-                        'filename' => 'registrations_overview_views',
560
-                    ),
561
-                    'registrations_regoverview_other_help_tab'              => array(
562
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
563
-                        'filename' => 'registrations_overview_other',
564
-                    ),
565
-                ),
566
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
567
-                // 'help_tour'     => array('Registration_Overview_Help_Tour'),
568
-                'qtips'         => array('Registration_List_Table_Tips'),
569
-                'list_table'    => 'EE_Registrations_List_Table',
570
-                'require_nonce' => false,
571
-            ),
572
-            'view_registration' => array(
573
-                'nav'           => array(
574
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
575
-                    'order'      => 15,
576
-                    'url'        => isset($this->_req_data['_REG_ID'])
577
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
578
-                        : $this->_admin_base_url,
579
-                    'persistent' => false,
580
-                ),
581
-                'help_tabs'     => array(
582
-                    'registrations_details_help_tab'                    => array(
583
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
584
-                        'filename' => 'registrations_details',
585
-                    ),
586
-                    'registrations_details_table_help_tab'              => array(
587
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
588
-                        'filename' => 'registrations_details_table',
589
-                    ),
590
-                    'registrations_details_form_answers_help_tab'       => array(
591
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
592
-                        'filename' => 'registrations_details_form_answers',
593
-                    ),
594
-                    'registrations_details_registrant_details_help_tab' => array(
595
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
596
-                        'filename' => 'registrations_details_registrant_details',
597
-                    ),
598
-                ),
599
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
600
-                // 'help_tour'     => array('Registration_Details_Help_Tour'),
601
-                'metaboxes'     => array_merge(
602
-                    $this->_default_espresso_metaboxes,
603
-                    array('_registration_details_metaboxes')
604
-                ),
605
-                'require_nonce' => false,
606
-            ),
607
-            'new_registration'  => array(
608
-                'nav'           => array(
609
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
610
-                    'url'        => '#',
611
-                    'order'      => 15,
612
-                    'persistent' => false,
613
-                ),
614
-                'metaboxes'     => $this->_default_espresso_metaboxes,
615
-                'labels'        => array(
616
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
617
-                ),
618
-                'require_nonce' => false,
619
-            ),
620
-            'add_new_attendee'  => array(
621
-                'nav'           => array(
622
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
623
-                    'order'      => 15,
624
-                    'persistent' => false,
625
-                ),
626
-                'metaboxes'     => array_merge(
627
-                    $this->_default_espresso_metaboxes,
628
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
629
-                ),
630
-                'require_nonce' => false,
631
-            ),
632
-            'edit_attendee'     => array(
633
-                'nav'           => array(
634
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
635
-                    'order'      => 15,
636
-                    'persistent' => false,
637
-                    'url'        => isset($this->_req_data['ATT_ID'])
638
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
639
-                        : $this->_admin_base_url,
640
-                ),
641
-                'metaboxes'     => array('attendee_editor_metaboxes'),
642
-                'require_nonce' => false,
643
-            ),
644
-            'contact_list'      => array(
645
-                'nav'           => array(
646
-                    'label' => esc_html__('Contact List', 'event_espresso'),
647
-                    'order' => 20,
648
-                ),
649
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
650
-                'help_tabs'     => array(
651
-                    'registrations_contact_list_help_tab'                       => array(
652
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
653
-                        'filename' => 'registrations_contact_list',
654
-                    ),
655
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
656
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
657
-                        'filename' => 'registrations_contact_list_table_column_headings',
658
-                    ),
659
-                    'registrations_contact_list_views_help_tab'                 => array(
660
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
661
-                        'filename' => 'registrations_contact_list_views',
662
-                    ),
663
-                    'registrations_contact_list_other_help_tab'                 => array(
664
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
665
-                        'filename' => 'registrations_contact_list_other',
666
-                    ),
667
-                ),
668
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
669
-                // 'help_tour'     => array('Contact_List_Help_Tour'),
670
-                'metaboxes'     => array(),
671
-                'require_nonce' => false,
672
-            ),
673
-            // override default cpt routes
674
-            'create_new'        => '',
675
-            'edit'              => '',
676
-        );
677
-    }
678
-
679
-
680
-    /**
681
-     * The below methods aren't used by this class currently
682
-     */
683
-    protected function _add_screen_options()
684
-    {
685
-    }
686
-
687
-
688
-    protected function _add_feature_pointers()
689
-    {
690
-    }
691
-
692
-
693
-    public function admin_init()
694
-    {
695
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
696
-            'click "Update Registration Questions" to save your changes',
697
-            'event_espresso'
698
-        );
699
-    }
700
-
701
-
702
-    public function admin_notices()
703
-    {
704
-    }
705
-
706
-
707
-    public function admin_footer_scripts()
708
-    {
709
-    }
710
-
711
-
712
-    /**
713
-     *        get list of registration statuses
714
-     *
715
-     * @access private
716
-     * @return void
717
-     * @throws EE_Error
718
-     */
719
-    private function _get_registration_status_array()
720
-    {
721
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
722
-    }
723
-
724
-
725
-    /**
726
-     * @throws InvalidArgumentException
727
-     * @throws InvalidDataTypeException
728
-     * @throws InvalidInterfaceException
729
-     * @since 4.10.2.p
730
-     */
731
-    protected function _add_screen_options_default()
732
-    {
733
-        $this->_per_page_screen_option();
734
-    }
735
-
736
-
737
-    /**
738
-     * @throws InvalidArgumentException
739
-     * @throws InvalidDataTypeException
740
-     * @throws InvalidInterfaceException
741
-     * @since 4.10.2.p
742
-     */
743
-    protected function _add_screen_options_contact_list()
744
-    {
745
-        $page_title = $this->_admin_page_title;
746
-        $this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
747
-        $this->_per_page_screen_option();
748
-        $this->_admin_page_title = $page_title;
749
-    }
750
-
751
-
752
-    public function load_scripts_styles()
753
-    {
754
-        // style
755
-        wp_register_style(
756
-            'espresso_reg',
757
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
758
-            array('ee-admin-css'),
759
-            EVENT_ESPRESSO_VERSION
760
-        );
761
-        wp_enqueue_style('espresso_reg');
762
-        // script
763
-        wp_register_script(
764
-            'espresso_reg',
765
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
766
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
767
-            EVENT_ESPRESSO_VERSION,
768
-            true
769
-        );
770
-        wp_enqueue_script('espresso_reg');
771
-    }
772
-
773
-
774
-    /**
775
-     * @throws EE_Error
776
-     * @throws InvalidArgumentException
777
-     * @throws InvalidDataTypeException
778
-     * @throws InvalidInterfaceException
779
-     * @throws ReflectionException
780
-     * @since 4.10.2.p
781
-     */
782
-    public function load_scripts_styles_edit_attendee()
783
-    {
784
-        // stuff to only show up on our attendee edit details page.
785
-        $attendee_details_translations = array(
786
-            'att_publish_text' => sprintf(
787
-                /* translators: The date and time */
788
-                wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
789
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
790
-            ),
791
-        );
792
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
793
-        wp_enqueue_script('jquery-validate');
794
-    }
795
-
796
-
797
-    /**
798
-     * @throws EE_Error
799
-     * @throws InvalidArgumentException
800
-     * @throws InvalidDataTypeException
801
-     * @throws InvalidInterfaceException
802
-     * @throws ReflectionException
803
-     * @since 4.10.2.p
804
-     */
805
-    public function load_scripts_styles_view_registration()
806
-    {
807
-        // styles
808
-        wp_enqueue_style('espresso-ui-theme');
809
-        // scripts
810
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
811
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
812
-    }
813
-
814
-
815
-    public function load_scripts_styles_contact_list()
816
-    {
817
-        wp_dequeue_style('espresso_reg');
818
-        wp_register_style(
819
-            'espresso_att',
820
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
821
-            array('ee-admin-css'),
822
-            EVENT_ESPRESSO_VERSION
823
-        );
824
-        wp_enqueue_style('espresso_att');
825
-    }
826
-
827
-
828
-    public function load_scripts_styles_new_registration()
829
-    {
830
-        wp_register_script(
831
-            'ee-spco-for-admin',
832
-            REG_ASSETS_URL . 'spco_for_admin.js',
833
-            array('underscore', 'jquery'),
834
-            EVENT_ESPRESSO_VERSION,
835
-            true
836
-        );
837
-        wp_enqueue_script('ee-spco-for-admin');
838
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
839
-        EE_Form_Section_Proper::wp_enqueue_scripts();
840
-        EED_Ticket_Selector::load_tckt_slctr_assets();
841
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
842
-    }
843
-
844
-
845
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
846
-    {
847
-        add_filter('FHEE_load_EE_messages', '__return_true');
848
-    }
849
-
850
-
851
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
852
-    {
853
-        add_filter('FHEE_load_EE_messages', '__return_true');
854
-    }
855
-
856
-
857
-    /**
858
-     * @throws EE_Error
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidDataTypeException
861
-     * @throws InvalidInterfaceException
862
-     * @throws ReflectionException
863
-     * @since 4.10.2.p
864
-     */
865
-    protected function _set_list_table_views_default()
866
-    {
867
-        // for notification related bulk actions we need to make sure only active messengers have an option.
868
-        EED_Messages::set_autoloaders();
869
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
870
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
871
-        $active_mts = $message_resource_manager->list_of_active_message_types();
872
-        // key= bulk_action_slug, value= message type.
873
-        $match_array = array(
874
-            'approve_registrations'    => 'registration',
875
-            'decline_registrations'    => 'declined_registration',
876
-            'pending_registrations'    => 'pending_approval',
877
-            'no_approve_registrations' => 'not_approved_registration',
878
-            'cancel_registrations'     => 'cancelled_registration',
879
-        );
880
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
881
-            'ee_send_message',
882
-            'batch_send_messages'
883
-        );
884
-        /** setup reg status bulk actions **/
885
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
886
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
887
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
888
-                'Approve and Notify Registrations',
889
-                'event_espresso'
890
-            );
891
-        }
892
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
893
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
894
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
895
-                'Decline and Notify Registrations',
896
-                'event_espresso'
897
-            );
898
-        }
899
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
900
-            'Set Registrations to Pending Payment',
901
-            'event_espresso'
902
-        );
903
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
904
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
905
-                'Set Registrations to Pending Payment and Notify',
906
-                'event_espresso'
907
-            );
908
-        }
909
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
910
-            'Set Registrations to Not Approved',
911
-            'event_espresso'
912
-        );
913
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
914
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
915
-                'Set Registrations to Not Approved and Notify',
916
-                'event_espresso'
917
-            );
918
-        }
919
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
920
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
921
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
922
-                'Cancel Registrations and Notify',
923
-                'event_espresso'
924
-            );
925
-        }
926
-        $def_reg_status_actions = apply_filters(
927
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
928
-            $def_reg_status_actions,
929
-            $active_mts,
930
-            $can_send
931
-        );
932
-
933
-        $this->_views = array(
934
-            'all'   => array(
935
-                'slug'        => 'all',
936
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
937
-                'count'       => 0,
938
-                'bulk_action' => array_merge(
939
-                    $def_reg_status_actions,
940
-                    array(
941
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
942
-                    )
943
-                ),
944
-            ),
945
-            'month' => array(
946
-                'slug'        => 'month',
947
-                'label'       => esc_html__('This Month', 'event_espresso'),
948
-                'count'       => 0,
949
-                'bulk_action' => array_merge(
950
-                    $def_reg_status_actions,
951
-                    array(
952
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
953
-                    )
954
-                ),
955
-            ),
956
-            'today' => array(
957
-                'slug'        => 'today',
958
-                'label'       => sprintf(
959
-                    esc_html__('Today - %s', 'event_espresso'),
960
-                    date('M d, Y', current_time('timestamp'))
961
-                ),
962
-                'count'       => 0,
963
-                'bulk_action' => array_merge(
964
-                    $def_reg_status_actions,
965
-                    array(
966
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
967
-                    )
968
-                ),
969
-            ),
970
-        );
971
-        if (EE_Registry::instance()->CAP->current_user_can(
972
-            'ee_delete_registrations',
973
-            'espresso_registrations_delete_registration'
974
-        )) {
975
-            $this->_views['incomplete'] = array(
976
-                'slug'        => 'incomplete',
977
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
978
-                'count'       => 0,
979
-                'bulk_action' => array(
980
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
981
-                ),
982
-            );
983
-            $this->_views['trash'] = array(
984
-                'slug'        => 'trash',
985
-                'label'       => esc_html__('Trash', 'event_espresso'),
986
-                'count'       => 0,
987
-                'bulk_action' => array(
988
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
989
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
990
-                ),
991
-            );
992
-        }
993
-    }
994
-
995
-
996
-    protected function _set_list_table_views_contact_list()
997
-    {
998
-        $this->_views = array(
999
-            'in_use' => array(
1000
-                'slug'        => 'in_use',
1001
-                'label'       => esc_html__('In Use', 'event_espresso'),
1002
-                'count'       => 0,
1003
-                'bulk_action' => array(
1004
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1005
-                ),
1006
-            ),
1007
-        );
1008
-        if (EE_Registry::instance()->CAP->current_user_can(
1009
-            'ee_delete_contacts',
1010
-            'espresso_registrations_trash_attendees'
1011
-        )
1012
-        ) {
1013
-            $this->_views['trash'] = array(
1014
-                'slug'        => 'trash',
1015
-                'label'       => esc_html__('Trash', 'event_espresso'),
1016
-                'count'       => 0,
1017
-                'bulk_action' => array(
1018
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1019
-                ),
1020
-            );
1021
-        }
1022
-    }
1023
-
1024
-
1025
-    protected function _registration_legend_items()
1026
-    {
1027
-        $fc_items = array(
1028
-            'star-icon'        => array(
1029
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1030
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1031
-            ),
1032
-            'view_details'     => array(
1033
-                'class' => 'dashicons dashicons-clipboard',
1034
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1035
-            ),
1036
-            'edit_attendee'    => array(
1037
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1038
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1039
-            ),
1040
-            'view_transaction' => array(
1041
-                'class' => 'dashicons dashicons-cart',
1042
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1043
-            ),
1044
-            'view_invoice'     => array(
1045
-                'class' => 'dashicons dashicons-media-spreadsheet',
1046
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1047
-            ),
1048
-        );
1049
-        if (EE_Registry::instance()->CAP->current_user_can(
1050
-            'ee_send_message',
1051
-            'espresso_registrations_resend_registration'
1052
-        )) {
1053
-            $fc_items['resend_registration'] = array(
1054
-                'class' => 'dashicons dashicons-email-alt',
1055
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1056
-            );
1057
-        } else {
1058
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
1059
-        }
1060
-        if (EE_Registry::instance()->CAP->current_user_can(
1061
-            'ee_read_global_messages',
1062
-            'view_filtered_messages'
1063
-        )) {
1064
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1065
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1066
-                $fc_items['view_related_messages'] = array(
1067
-                    'class' => $related_for_icon['css_class'],
1068
-                    'desc'  => $related_for_icon['label'],
1069
-                );
1070
-            }
1071
-        }
1072
-        $sc_items = array(
1073
-            'approved_status'   => array(
1074
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1075
-                'desc'  => EEH_Template::pretty_status(
1076
-                    EEM_Registration::status_id_approved,
1077
-                    false,
1078
-                    'sentence'
1079
-                ),
1080
-            ),
1081
-            'pending_status'    => array(
1082
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1083
-                'desc'  => EEH_Template::pretty_status(
1084
-                    EEM_Registration::status_id_pending_payment,
1085
-                    false,
1086
-                    'sentence'
1087
-                ),
1088
-            ),
1089
-            'wait_list'         => array(
1090
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1091
-                'desc'  => EEH_Template::pretty_status(
1092
-                    EEM_Registration::status_id_wait_list,
1093
-                    false,
1094
-                    'sentence'
1095
-                ),
1096
-            ),
1097
-            'incomplete_status' => array(
1098
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1099
-                'desc'  => EEH_Template::pretty_status(
1100
-                    EEM_Registration::status_id_incomplete,
1101
-                    false,
1102
-                    'sentence'
1103
-                ),
1104
-            ),
1105
-            'not_approved'      => array(
1106
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1107
-                'desc'  => EEH_Template::pretty_status(
1108
-                    EEM_Registration::status_id_not_approved,
1109
-                    false,
1110
-                    'sentence'
1111
-                ),
1112
-            ),
1113
-            'declined_status'   => array(
1114
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1115
-                'desc'  => EEH_Template::pretty_status(
1116
-                    EEM_Registration::status_id_declined,
1117
-                    false,
1118
-                    'sentence'
1119
-                ),
1120
-            ),
1121
-            'cancelled_status'  => array(
1122
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1123
-                'desc'  => EEH_Template::pretty_status(
1124
-                    EEM_Registration::status_id_cancelled,
1125
-                    false,
1126
-                    'sentence'
1127
-                ),
1128
-            ),
1129
-        );
1130
-        return array_merge($fc_items, $sc_items);
1131
-    }
1132
-
1133
-
1134
-
1135
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1136
-
1137
-
1138
-
1139
-    /**
1140
-     * @throws DomainException
1141
-     * @throws EE_Error
1142
-     * @throws InvalidArgumentException
1143
-     * @throws InvalidDataTypeException
1144
-     * @throws InvalidInterfaceException
1145
-     * @throws ReflectionException
1146
-     */
1147
-    protected function _registrations_overview_list_table()
1148
-    {
1149
-        $this->appendAddNewRegistrationButtonToPageTitle();
1150
-        $header_text = '';
1151
-        $admin_page_header_decorators = [
1152
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1153
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1154
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1155
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1156
-        ];
1157
-        foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1158
-            $filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1159
-            $header_text = $filter_header_decorator->getHeaderText($header_text);
1160
-        }
1161
-        $this->_template_args['admin_page_header'] = $header_text;
1162
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1163
-        $this->display_admin_list_table_page_with_no_sidebar();
1164
-    }
1165
-
1166
-
1167
-    /**
1168
-     * @throws EE_Error
1169
-     * @throws InvalidArgumentException
1170
-     * @throws InvalidDataTypeException
1171
-     * @throws InvalidInterfaceException
1172
-     */
1173
-    private function appendAddNewRegistrationButtonToPageTitle()
1174
-    {
1175
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1176
-            ? absint($this->_req_data['event_id'])
1177
-            : 0;
1178
-        if ($EVT_ID
1179
-            && EE_Registry::instance()->CAP->current_user_can(
1180
-                'ee_edit_registrations',
1181
-                'espresso_registrations_new_registration',
1182
-                $EVT_ID
1183
-            )
1184
-        ) {
1185
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1186
-                'new_registration',
1187
-                'add-registrant',
1188
-                array('event_id' => $EVT_ID),
1189
-                'add-new-h2'
1190
-            );
1191
-        }
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * This sets the _registration property for the registration details screen
1197
-     *
1198
-     * @access private
1199
-     * @return bool
1200
-     * @throws EE_Error
1201
-     * @throws InvalidArgumentException
1202
-     * @throws InvalidDataTypeException
1203
-     * @throws InvalidInterfaceException
1204
-     */
1205
-    private function _set_registration_object()
1206
-    {
1207
-        // get out if we've already set the object
1208
-        if ($this->_registration instanceof EE_Registration) {
1209
-            return true;
1210
-        }
1211
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1212
-        if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1213
-            return true;
1214
-        }
1215
-        $error_msg = sprintf(
1216
-            esc_html__(
1217
-                'An error occurred and the details for Registration ID #%s could not be retrieved.',
1218
-                'event_espresso'
1219
-            ),
1220
-            $REG_ID
1221
-        );
1222
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1223
-        $this->_registration = null;
1224
-        return false;
1225
-    }
1226
-
1227
-
1228
-    /**
1229
-     * Used to retrieve registrations for the list table.
1230
-     *
1231
-     * @param int  $per_page
1232
-     * @param bool $count
1233
-     * @param bool $this_month
1234
-     * @param bool $today
1235
-     * @return EE_Registration[]|int
1236
-     * @throws EE_Error
1237
-     * @throws InvalidArgumentException
1238
-     * @throws InvalidDataTypeException
1239
-     * @throws InvalidInterfaceException
1240
-     */
1241
-    public function get_registrations(
1242
-        $per_page = 10,
1243
-        $count = false,
1244
-        $this_month = false,
1245
-        $today = false
1246
-    ) {
1247
-        if ($this_month) {
1248
-            $this->_req_data['status'] = 'month';
1249
-        }
1250
-        if ($today) {
1251
-            $this->_req_data['status'] = 'today';
1252
-        }
1253
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1254
-        /**
1255
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1256
-         *
1257
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1258
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1259
-         *                             or if you have the development copy of EE you can view this at the path:
1260
-         *                             /docs/G--Model-System/model-query-params.md
1261
-         */
1262
-        $query_params['group_by'] = '';
1263
-
1264
-        return $count
1265
-            ? $this->getRegistrationModel()->count($query_params)
1266
-            /** @type EE_Registration[] */
1267
-            : $this->getRegistrationModel()->get_all($query_params);
1268
-    }
1269
-
1270
-
1271
-    /**
1272
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1273
-     * Note: this listens to values on the request for some of the query parameters.
1274
-     *
1275
-     * @param array $request
1276
-     * @param int   $per_page
1277
-     * @param bool  $count
1278
-     * @return array
1279
-     * @throws EE_Error
1280
-     * @throws InvalidArgumentException
1281
-     * @throws InvalidDataTypeException
1282
-     * @throws InvalidInterfaceException
1283
-     */
1284
-    protected function _get_registration_query_parameters(
1285
-        $request = array(),
1286
-        $per_page = 10,
1287
-        $count = false
1288
-    ) {
1289
-        /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1290
-        $list_table_query_builder = $this->getLoader()->getNew(
1291
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1292
-            [ $request ]
1293
-        );
1294
-        return $list_table_query_builder->getQueryParams($per_page, $count);
1295
-    }
1296
-
1297
-
1298
-    public function get_registration_status_array()
1299
-    {
1300
-        return self::$_reg_status;
1301
-    }
1302
-
1303
-
1304
-
1305
-
1306
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1307
-    /**
1308
-     *        generates HTML for the View Registration Details Admin page
1309
-     *
1310
-     * @access protected
1311
-     * @return void
1312
-     * @throws DomainException
1313
-     * @throws EE_Error
1314
-     * @throws InvalidArgumentException
1315
-     * @throws InvalidDataTypeException
1316
-     * @throws InvalidInterfaceException
1317
-     * @throws EntityNotFoundException
1318
-     * @throws ReflectionException
1319
-     */
1320
-    protected function _registration_details()
1321
-    {
1322
-        $this->_template_args = array();
1323
-        $this->_set_registration_object();
1324
-        if (is_object($this->_registration)) {
1325
-            $transaction = $this->_registration->transaction()
1326
-                ? $this->_registration->transaction()
1327
-                : EE_Transaction::new_instance();
1328
-            $this->_session = $transaction->session_data();
1329
-            $event_id = $this->_registration->event_ID();
1330
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1331
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1332
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1333
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1334
-            $this->_template_args['grand_total'] = $transaction->total();
1335
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1336
-            // link back to overview
1337
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1338
-            $this->_template_args['registration'] = $this->_registration;
1339
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1340
-                array(
1341
-                    'action'   => 'default',
1342
-                    'event_id' => $event_id,
1343
-                ),
1344
-                REG_ADMIN_URL
1345
-            );
1346
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1347
-                array(
1348
-                    'action' => 'default',
1349
-                    'EVT_ID' => $event_id,
1350
-                    'page'   => 'espresso_transactions',
1351
-                ),
1352
-                admin_url('admin.php')
1353
-            );
1354
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1355
-                array(
1356
-                    'page'   => 'espresso_events',
1357
-                    'action' => 'edit',
1358
-                    'post'   => $event_id,
1359
-                ),
1360
-                admin_url('admin.php')
1361
-            );
1362
-            // next and previous links
1363
-            $next_reg = $this->_registration->next(
1364
-                null,
1365
-                array(),
1366
-                'REG_ID'
1367
-            );
1368
-            $this->_template_args['next_registration'] = $next_reg
1369
-                ? $this->_next_link(
1370
-                    EE_Admin_Page::add_query_args_and_nonce(
1371
-                        array(
1372
-                            'action'  => 'view_registration',
1373
-                            '_REG_ID' => $next_reg['REG_ID'],
1374
-                        ),
1375
-                        REG_ADMIN_URL
1376
-                    ),
1377
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1378
-                )
1379
-                : '';
1380
-            $previous_reg = $this->_registration->previous(
1381
-                null,
1382
-                array(),
1383
-                'REG_ID'
1384
-            );
1385
-            $this->_template_args['previous_registration'] = $previous_reg
1386
-                ? $this->_previous_link(
1387
-                    EE_Admin_Page::add_query_args_and_nonce(
1388
-                        array(
1389
-                            'action'  => 'view_registration',
1390
-                            '_REG_ID' => $previous_reg['REG_ID'],
1391
-                        ),
1392
-                        REG_ADMIN_URL
1393
-                    ),
1394
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1395
-                )
1396
-                : '';
1397
-            // grab header
1398
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1399
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1400
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1401
-                $template_path,
1402
-                $this->_template_args,
1403
-                true
1404
-            );
1405
-        } else {
1406
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1407
-        }
1408
-        // the details template wrapper
1409
-        $this->display_admin_page_with_sidebar();
1410
-    }
1411
-
1412
-
1413
-    /**
1414
-     * @throws EE_Error
1415
-     * @throws InvalidArgumentException
1416
-     * @throws InvalidDataTypeException
1417
-     * @throws InvalidInterfaceException
1418
-     * @throws ReflectionException
1419
-     * @since 4.10.2.p
1420
-     */
1421
-    protected function _registration_details_metaboxes()
1422
-    {
1423
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1424
-        $this->_set_registration_object();
1425
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1426
-        add_meta_box(
1427
-            'edit-reg-status-mbox',
1428
-            esc_html__('Registration Status', 'event_espresso'),
1429
-            array($this, 'set_reg_status_buttons_metabox'),
1430
-            $this->wp_page_slug,
1431
-            'normal',
1432
-            'high'
1433
-        );
1434
-        add_meta_box(
1435
-            'edit-reg-details-mbox',
1436
-            esc_html__('Registration Details', 'event_espresso'),
1437
-            array($this, '_reg_details_meta_box'),
1438
-            $this->wp_page_slug,
1439
-            'normal',
1440
-            'high'
1441
-        );
1442
-        if ($attendee instanceof EE_Attendee
1443
-            && EE_Registry::instance()->CAP->current_user_can(
1444
-                'ee_read_registration',
1445
-                'edit-reg-questions-mbox',
1446
-                $this->_registration->ID()
1447
-            )
1448
-        ) {
1449
-            add_meta_box(
1450
-                'edit-reg-questions-mbox',
1451
-                esc_html__('Registration Form Answers', 'event_espresso'),
1452
-                array($this, '_reg_questions_meta_box'),
1453
-                $this->wp_page_slug,
1454
-                'normal',
1455
-                'high'
1456
-            );
1457
-        }
1458
-        add_meta_box(
1459
-            'edit-reg-registrant-mbox',
1460
-            esc_html__('Contact Details', 'event_espresso'),
1461
-            array($this, '_reg_registrant_side_meta_box'),
1462
-            $this->wp_page_slug,
1463
-            'side',
1464
-            'high'
1465
-        );
1466
-        if ($this->_registration->group_size() > 1) {
1467
-            add_meta_box(
1468
-                'edit-reg-attendees-mbox',
1469
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1470
-                array($this, '_reg_attendees_meta_box'),
1471
-                $this->wp_page_slug,
1472
-                'normal',
1473
-                'high'
1474
-            );
1475
-        }
1476
-    }
1477
-
1478
-
1479
-    /**
1480
-     * set_reg_status_buttons_metabox
1481
-     *
1482
-     * @access protected
1483
-     * @return string
1484
-     * @throws EE_Error
1485
-     * @throws EntityNotFoundException
1486
-     * @throws InvalidArgumentException
1487
-     * @throws InvalidDataTypeException
1488
-     * @throws InvalidInterfaceException
1489
-     * @throws ReflectionException
1490
-     */
1491
-    public function set_reg_status_buttons_metabox()
1492
-    {
1493
-        $this->_set_registration_object();
1494
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1495
-        echo $change_reg_status_form->form_open(
1496
-            self::add_query_args_and_nonce(
1497
-                array(
1498
-                    'action' => 'change_reg_status',
1499
-                ),
1500
-                REG_ADMIN_URL
1501
-            )
1502
-        );
1503
-        echo $change_reg_status_form->get_html();
1504
-        echo $change_reg_status_form->form_close();
1505
-    }
1506
-
1507
-
1508
-    /**
1509
-     * @return EE_Form_Section_Proper
1510
-     * @throws EE_Error
1511
-     * @throws InvalidArgumentException
1512
-     * @throws InvalidDataTypeException
1513
-     * @throws InvalidInterfaceException
1514
-     * @throws EntityNotFoundException
1515
-     * @throws ReflectionException
1516
-     */
1517
-    protected function _generate_reg_status_change_form()
1518
-    {
1519
-        $reg_status_change_form_array = array(
1520
-            'name'            => 'reg_status_change_form',
1521
-            'html_id'         => 'reg-status-change-form',
1522
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1523
-            'subsections'     => array(
1524
-                'return'             => new EE_Hidden_Input(
1525
-                    array(
1526
-                        'name'    => 'return',
1527
-                        'default' => 'view_registration',
1528
-                    )
1529
-                ),
1530
-                'REG_ID'             => new EE_Hidden_Input(
1531
-                    array(
1532
-                        'name'    => 'REG_ID',
1533
-                        'default' => $this->_registration->ID(),
1534
-                    )
1535
-                ),
1536
-                'current_status'     => new EE_Form_Section_HTML(
1537
-                    EEH_HTML::table(
1538
-                        EEH_HTML::tr(
1539
-                            EEH_HTML::th(
1540
-                                EEH_HTML::label(
1541
-                                    EEH_HTML::strong(
1542
-                                        esc_html__('Current Registration Status', 'event_espresso')
1543
-                                    )
1544
-                                )
1545
-                            )
1546
-                            . EEH_HTML::td(
1547
-                                EEH_HTML::strong(
1548
-                                    $this->_registration->pretty_status(),
1549
-                                    '',
1550
-                                    'status-' . $this->_registration->status_ID(),
1551
-                                    'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1552
-                                )
1553
-                            )
1554
-                        )
1555
-                    )
1556
-                )
1557
-            )
1558
-        );
1559
-        if (EE_Registry::instance()->CAP->current_user_can(
1560
-            'ee_edit_registration',
1561
-            'toggle_registration_status',
1562
-            $this->_registration->ID()
1563
-        )) {
1564
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1565
-                $this->_get_reg_statuses(),
1566
-                array(
1567
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1568
-                    'default'         => $this->_registration->status_ID(),
1569
-                )
1570
-            );
1571
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1572
-                array(
1573
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1574
-                    'default'         => false,
1575
-                    'html_help_text'  => esc_html__(
1576
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1577
-                        'event_espresso'
1578
-                    )
1579
-                )
1580
-            );
1581
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1582
-                array(
1583
-                    'html_class'      => 'button-primary',
1584
-                    'html_label_text' => '&nbsp;',
1585
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1586
-                )
1587
-            );
1588
-        }
1589
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1590
-    }
1591
-
1592
-
1593
-    /**
1594
-     * Returns an array of all the buttons for the various statuses and switch status actions
1595
-     *
1596
-     * @return array
1597
-     * @throws EE_Error
1598
-     * @throws InvalidArgumentException
1599
-     * @throws InvalidDataTypeException
1600
-     * @throws InvalidInterfaceException
1601
-     * @throws EntityNotFoundException
1602
-     */
1603
-    protected function _get_reg_statuses()
1604
-    {
1605
-        $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1606
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1607
-        // get current reg status
1608
-        $current_status = $this->_registration->status_ID();
1609
-        // is registration for free event? This will determine whether to display the pending payment option
1610
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1611
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1612
-        ) {
1613
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1614
-        }
1615
-        return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1616
-    }
1617
-
1618
-
1619
-    /**
1620
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1621
-     *
1622
-     * @param bool $status REG status given for changing registrations to.
1623
-     * @param bool $notify Whether to send messages notifications or not.
1624
-     * @return array (array with reg_id(s) updated and whether update was successful.
1625
-     * @throws DomainException
1626
-     * @throws EE_Error
1627
-     * @throws EntityNotFoundException
1628
-     * @throws InvalidArgumentException
1629
-     * @throws InvalidDataTypeException
1630
-     * @throws InvalidInterfaceException
1631
-     * @throws ReflectionException
1632
-     * @throws RuntimeException
1633
-     */
1634
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1635
-    {
1636
-        if (isset($this->_req_data['reg_status_change_form'])) {
1637
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1638
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1639
-                : array();
1640
-        } else {
1641
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1642
-                ? (array) $this->_req_data['_REG_ID']
1643
-                : array();
1644
-        }
1645
-        // sanitize $REG_IDs
1646
-        $REG_IDs = array_map('absint', $REG_IDs);
1647
-        // and remove empty entries
1648
-        $REG_IDs = array_filter($REG_IDs);
1649
-
1650
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1651
-
1652
-        /**
1653
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1654
-         * Currently this value is used downstream by the _process_resend_registration method.
1655
-         *
1656
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1657
-         * @param bool                     $status           The status registrations were changed to.
1658
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1659
-         * @param Registrations_Admin_Page $admin_page_object
1660
-         */
1661
-        $this->_req_data['_REG_ID'] = apply_filters(
1662
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1663
-            $result['REG_ID'],
1664
-            $status,
1665
-            $result['success'],
1666
-            $this
1667
-        );
1668
-
1669
-        // notify?
1670
-        if ($notify
1671
-            && $result['success']
1672
-            && ! empty($this->_req_data['_REG_ID'])
1673
-            && EE_Registry::instance()->CAP->current_user_can(
1674
-                'ee_send_message',
1675
-                'espresso_registrations_resend_registration'
1676
-            )
1677
-        ) {
1678
-            $this->_process_resend_registration();
1679
-        }
1680
-        return $result;
1681
-    }
1682
-
1683
-
1684
-    /**
1685
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1686
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1687
-     *
1688
-     * @param array  $REG_IDs
1689
-     * @param string $status
1690
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1691
-     *                        slug sent with setting the registration status.
1692
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1693
-     * @throws EE_Error
1694
-     * @throws InvalidArgumentException
1695
-     * @throws InvalidDataTypeException
1696
-     * @throws InvalidInterfaceException
1697
-     * @throws ReflectionException
1698
-     * @throws RuntimeException
1699
-     * @throws EntityNotFoundException
1700
-     * @throws DomainException
1701
-     */
1702
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1703
-    {
1704
-        $success = false;
1705
-        // typecast $REG_IDs
1706
-        $REG_IDs = (array) $REG_IDs;
1707
-        if (! empty($REG_IDs)) {
1708
-            $success = true;
1709
-            // set default status if none is passed
1710
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1711
-            $status_context = $notify
1712
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1713
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1714
-            // loop through REG_ID's and change status
1715
-            foreach ($REG_IDs as $REG_ID) {
1716
-                $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1717
-                if ($registration instanceof EE_Registration) {
1718
-                    $registration->set_status(
1719
-                        $status,
1720
-                        false,
1721
-                        new Context(
1722
-                            $status_context,
1723
-                            esc_html__(
1724
-                                'Manually triggered status change on a Registration Admin Page route.',
1725
-                                'event_espresso'
1726
-                            )
1727
-                        )
1728
-                    );
1729
-                    $result = $registration->save();
1730
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1731
-                    $success = $result !== false ? $success : false;
1732
-                }
1733
-            }
1734
-        }
1735
-
1736
-        // return $success and processed registrations
1737
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * Common logic for setting up success message and redirecting to appropriate route
1743
-     *
1744
-     * @param string $STS_ID status id for the registration changed to
1745
-     * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1746
-     * @return void
1747
-     * @throws DomainException
1748
-     * @throws EE_Error
1749
-     * @throws EntityNotFoundException
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws ReflectionException
1754
-     * @throws RuntimeException
1755
-     */
1756
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1757
-    {
1758
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1759
-            : array('success' => false);
1760
-        $success = isset($result['success']) && $result['success'];
1761
-        // setup success message
1762
-        if ($success) {
1763
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1764
-                $msg = sprintf(
1765
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1766
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1767
-                );
1768
-            } else {
1769
-                $msg = sprintf(
1770
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1771
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1772
-                );
1773
-            }
1774
-            EE_Error::add_success($msg);
1775
-        } else {
1776
-            EE_Error::add_error(
1777
-                esc_html__(
1778
-                    'Something went wrong, and the status was not changed',
1779
-                    'event_espresso'
1780
-                ),
1781
-                __FILE__,
1782
-                __LINE__,
1783
-                __FUNCTION__
1784
-            );
1785
-        }
1786
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] === 'view_registration') {
1787
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1788
-        } else {
1789
-            $route = array('action' => 'default');
1790
-        }
1791
-        $route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1792
-        $this->_redirect_after_action($success, '', '', $route, true);
1793
-    }
1794
-
1795
-
1796
-    /**
1797
-     * incoming reg status change from reg details page.
1798
-     *
1799
-     * @return void
1800
-     * @throws EE_Error
1801
-     * @throws EntityNotFoundException
1802
-     * @throws InvalidArgumentException
1803
-     * @throws InvalidDataTypeException
1804
-     * @throws InvalidInterfaceException
1805
-     * @throws ReflectionException
1806
-     * @throws RuntimeException
1807
-     * @throws DomainException
1808
-     */
1809
-    protected function _change_reg_status()
1810
-    {
1811
-        $this->_req_data['return'] = 'view_registration';
1812
-        // set notify based on whether the send notifications toggle is set or not
1813
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1814
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1815
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1816
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1817
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1818
-            case EEM_Registration::status_id_approved:
1819
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1820
-                $this->approve_registration($notify);
1821
-                break;
1822
-            case EEM_Registration::status_id_pending_payment:
1823
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1824
-                $this->pending_registration($notify);
1825
-                break;
1826
-            case EEM_Registration::status_id_not_approved:
1827
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1828
-                $this->not_approve_registration($notify);
1829
-                break;
1830
-            case EEM_Registration::status_id_declined:
1831
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1832
-                $this->decline_registration($notify);
1833
-                break;
1834
-            case EEM_Registration::status_id_cancelled:
1835
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1836
-                $this->cancel_registration($notify);
1837
-                break;
1838
-            case EEM_Registration::status_id_wait_list:
1839
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1840
-                $this->wait_list_registration($notify);
1841
-                break;
1842
-            case EEM_Registration::status_id_incomplete:
1843
-            default:
1844
-                $result['success'] = false;
1845
-                unset($this->_req_data['return']);
1846
-                $this->_reg_status_change_return('', false);
1847
-                break;
1848
-        }
1849
-    }
1850
-
1851
-
1852
-    /**
1853
-     * Callback for bulk action routes.
1854
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1855
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
1856
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1857
-     * when an action is happening on just a single registration).
1858
-     *
1859
-     * @param      $action
1860
-     * @param bool $notify
1861
-     */
1862
-    protected function bulk_action_on_registrations($action, $notify = false)
1863
-    {
1864
-        do_action(
1865
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1866
-            $this,
1867
-            $action,
1868
-            $notify
1869
-        );
1870
-        $method = $action . '_registration';
1871
-        if (method_exists($this, $method)) {
1872
-            $this->$method($notify);
1873
-        }
1874
-    }
1875
-
1876
-
1877
-    /**
1878
-     * approve_registration
1879
-     *
1880
-     * @access protected
1881
-     * @param bool $notify whether or not to notify the registrant about their approval.
1882
-     * @return void
1883
-     * @throws EE_Error
1884
-     * @throws EntityNotFoundException
1885
-     * @throws InvalidArgumentException
1886
-     * @throws InvalidDataTypeException
1887
-     * @throws InvalidInterfaceException
1888
-     * @throws ReflectionException
1889
-     * @throws RuntimeException
1890
-     * @throws DomainException
1891
-     */
1892
-    protected function approve_registration($notify = false)
1893
-    {
1894
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1895
-    }
1896
-
1897
-
1898
-    /**
1899
-     *        decline_registration
1900
-     *
1901
-     * @access protected
1902
-     * @param bool $notify whether or not to notify the registrant about their status change.
1903
-     * @return void
1904
-     * @throws EE_Error
1905
-     * @throws EntityNotFoundException
1906
-     * @throws InvalidArgumentException
1907
-     * @throws InvalidDataTypeException
1908
-     * @throws InvalidInterfaceException
1909
-     * @throws ReflectionException
1910
-     * @throws RuntimeException
1911
-     * @throws DomainException
1912
-     */
1913
-    protected function decline_registration($notify = false)
1914
-    {
1915
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     *        cancel_registration
1921
-     *
1922
-     * @access protected
1923
-     * @param bool $notify whether or not to notify the registrant about their status change.
1924
-     * @return void
1925
-     * @throws EE_Error
1926
-     * @throws EntityNotFoundException
1927
-     * @throws InvalidArgumentException
1928
-     * @throws InvalidDataTypeException
1929
-     * @throws InvalidInterfaceException
1930
-     * @throws ReflectionException
1931
-     * @throws RuntimeException
1932
-     * @throws DomainException
1933
-     */
1934
-    protected function cancel_registration($notify = false)
1935
-    {
1936
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1937
-    }
1938
-
1939
-
1940
-    /**
1941
-     *        not_approve_registration
1942
-     *
1943
-     * @access protected
1944
-     * @param bool $notify whether or not to notify the registrant about their status change.
1945
-     * @return void
1946
-     * @throws EE_Error
1947
-     * @throws EntityNotFoundException
1948
-     * @throws InvalidArgumentException
1949
-     * @throws InvalidDataTypeException
1950
-     * @throws InvalidInterfaceException
1951
-     * @throws ReflectionException
1952
-     * @throws RuntimeException
1953
-     * @throws DomainException
1954
-     */
1955
-    protected function not_approve_registration($notify = false)
1956
-    {
1957
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1958
-    }
1959
-
1960
-
1961
-    /**
1962
-     *        decline_registration
1963
-     *
1964
-     * @access protected
1965
-     * @param bool $notify whether or not to notify the registrant about their status change.
1966
-     * @return void
1967
-     * @throws EE_Error
1968
-     * @throws EntityNotFoundException
1969
-     * @throws InvalidArgumentException
1970
-     * @throws InvalidDataTypeException
1971
-     * @throws InvalidInterfaceException
1972
-     * @throws ReflectionException
1973
-     * @throws RuntimeException
1974
-     * @throws DomainException
1975
-     */
1976
-    protected function pending_registration($notify = false)
1977
-    {
1978
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1979
-    }
1980
-
1981
-
1982
-    /**
1983
-     * waitlist_registration
1984
-     *
1985
-     * @access protected
1986
-     * @param bool $notify whether or not to notify the registrant about their status change.
1987
-     * @return void
1988
-     * @throws EE_Error
1989
-     * @throws EntityNotFoundException
1990
-     * @throws InvalidArgumentException
1991
-     * @throws InvalidDataTypeException
1992
-     * @throws InvalidInterfaceException
1993
-     * @throws ReflectionException
1994
-     * @throws RuntimeException
1995
-     * @throws DomainException
1996
-     */
1997
-    protected function wait_list_registration($notify = false)
1998
-    {
1999
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2000
-    }
2001
-
2002
-
2003
-    /**
2004
-     *        generates HTML for the Registration main meta box
2005
-     *
2006
-     * @access public
2007
-     * @return void
2008
-     * @throws DomainException
2009
-     * @throws EE_Error
2010
-     * @throws InvalidArgumentException
2011
-     * @throws InvalidDataTypeException
2012
-     * @throws InvalidInterfaceException
2013
-     * @throws ReflectionException
2014
-     * @throws EntityNotFoundException
2015
-     */
2016
-    public function _reg_details_meta_box()
2017
-    {
2018
-        EEH_Autoloader::register_line_item_display_autoloaders();
2019
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2020
-        EE_Registry::instance()->load_helper('Line_Item');
2021
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2022
-            : EE_Transaction::new_instance();
2023
-        $this->_session = $transaction->session_data();
2024
-        $filters = new EE_Line_Item_Filter_Collection();
2025
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2026
-        $filters->add(new EE_Non_Zero_Line_Item_Filter());
2027
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2028
-            $filters,
2029
-            $transaction->total_line_item()
2030
-        );
2031
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2032
-        $line_item_display = new EE_Line_Item_Display(
2033
-            'reg_admin_table',
2034
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2035
-        );
2036
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2037
-            $filtered_line_item_tree,
2038
-            array('EE_Registration' => $this->_registration)
2039
-        );
2040
-        $attendee = $this->_registration->attendee();
2041
-        if (EE_Registry::instance()->CAP->current_user_can(
2042
-            'ee_read_transaction',
2043
-            'espresso_transactions_view_transaction'
2044
-        )) {
2045
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2046
-                EE_Admin_Page::add_query_args_and_nonce(
2047
-                    array(
2048
-                        'action' => 'view_transaction',
2049
-                        'TXN_ID' => $transaction->ID(),
2050
-                    ),
2051
-                    TXN_ADMIN_URL
2052
-                ),
2053
-                esc_html__(' View Transaction', 'event_espresso'),
2054
-                'button secondary-button right',
2055
-                'dashicons dashicons-cart'
2056
-            );
2057
-        } else {
2058
-            $this->_template_args['view_transaction_button'] = '';
2059
-        }
2060
-        if ($attendee instanceof EE_Attendee
2061
-            && EE_Registry::instance()->CAP->current_user_can(
2062
-                'ee_send_message',
2063
-                'espresso_registrations_resend_registration'
2064
-            )
2065
-        ) {
2066
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2067
-                EE_Admin_Page::add_query_args_and_nonce(
2068
-                    array(
2069
-                        'action'      => 'resend_registration',
2070
-                        '_REG_ID'     => $this->_registration->ID(),
2071
-                        'redirect_to' => 'view_registration',
2072
-                    ),
2073
-                    REG_ADMIN_URL
2074
-                ),
2075
-                esc_html__(' Resend Registration', 'event_espresso'),
2076
-                'button secondary-button right',
2077
-                'dashicons dashicons-email-alt'
2078
-            );
2079
-        } else {
2080
-            $this->_template_args['resend_registration_button'] = '';
2081
-        }
2082
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2083
-        $payment = $transaction->get_first_related('Payment');
2084
-        $payment = ! $payment instanceof EE_Payment
2085
-            ? EE_Payment::new_instance()
2086
-            : $payment;
2087
-        $payment_method = $payment->get_first_related('Payment_Method');
2088
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2089
-            ? EE_Payment_Method::new_instance()
2090
-            : $payment_method;
2091
-        $reg_details = array(
2092
-            'payment_method'       => $payment_method->name(),
2093
-            'response_msg'         => $payment->gateway_response(),
2094
-            'registration_id'      => $this->_registration->get('REG_code'),
2095
-            'registration_session' => $this->_registration->session_ID(),
2096
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2097
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2098
-        );
2099
-        if (isset($reg_details['registration_id'])) {
2100
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2101
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2102
-                'Registration ID',
2103
-                'event_espresso'
2104
-            );
2105
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2106
-        }
2107
-        if (isset($reg_details['payment_method'])) {
2108
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2109
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2110
-                'Most Recent Payment Method',
2111
-                'event_espresso'
2112
-            );
2113
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2114
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2115
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2116
-                'Payment method response',
2117
-                'event_espresso'
2118
-            );
2119
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2120
-        }
2121
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2122
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2123
-            'Registration Session',
2124
-            'event_espresso'
2125
-        );
2126
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2127
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2128
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2129
-            'Registration placed from IP',
2130
-            'event_espresso'
2131
-        );
2132
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2133
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2134
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2135
-            'Registrant User Agent',
2136
-            'event_espresso'
2137
-        );
2138
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2139
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2140
-            array(
2141
-                'action'   => 'default',
2142
-                'event_id' => $this->_registration->event_ID(),
2143
-            ),
2144
-            REG_ADMIN_URL
2145
-        );
2146
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2147
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2148
-        $template_path =
2149
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2150
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2151
-    }
2152
-
2153
-
2154
-    /**
2155
-     * generates HTML for the Registration Questions meta box.
2156
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2157
-     * otherwise uses new forms system
2158
-     *
2159
-     * @access public
2160
-     * @return void
2161
-     * @throws DomainException
2162
-     * @throws EE_Error
2163
-     * @throws InvalidArgumentException
2164
-     * @throws InvalidDataTypeException
2165
-     * @throws InvalidInterfaceException
2166
-     * @throws ReflectionException
2167
-     */
2168
-    public function _reg_questions_meta_box()
2169
-    {
2170
-        // allow someone to override this method entirely
2171
-        if (apply_filters(
2172
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2173
-            true,
2174
-            $this,
2175
-            $this->_registration
2176
-        )) {
2177
-            $form = $this->_get_reg_custom_questions_form(
2178
-                $this->_registration->ID()
2179
-            );
2180
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2181
-                ? $form->get_html_and_js()
2182
-                : '';
2183
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2184
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2185
-            $template_path =
2186
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2187
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2188
-        }
2189
-    }
2190
-
2191
-
2192
-    /**
2193
-     * form_before_question_group
2194
-     *
2195
-     * @deprecated    as of 4.8.32.rc.000
2196
-     * @access        public
2197
-     * @param        string $output
2198
-     * @return        string
2199
-     */
2200
-    public function form_before_question_group($output)
2201
-    {
2202
-        EE_Error::doing_it_wrong(
2203
-            __CLASS__ . '::' . __FUNCTION__,
2204
-            esc_html__(
2205
-                '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.',
2206
-                'event_espresso'
2207
-            ),
2208
-            '4.8.32.rc.000'
2209
-        );
2210
-        return '
21
+	/**
22
+	 * @var EE_Registration
23
+	 */
24
+	private $_registration;
25
+
26
+	/**
27
+	 * @var EE_Event
28
+	 */
29
+	private $_reg_event;
30
+
31
+	/**
32
+	 * @var EE_Session
33
+	 */
34
+	private $_session;
35
+
36
+	private static $_reg_status;
37
+
38
+	/**
39
+	 * Form for displaying the custom questions for this registration.
40
+	 * This gets used a few times throughout the request so its best to cache it
41
+	 *
42
+	 * @var EE_Registration_Custom_Questions_Form
43
+	 */
44
+	protected $_reg_custom_questions_form = null;
45
+
46
+	/**
47
+	 * @var EEM_Registration $registration_model
48
+	 */
49
+	private $registration_model;
50
+
51
+	/**
52
+	 * @var EEM_Attendee $attendee_model
53
+	 */
54
+	private $attendee_model;
55
+
56
+	/**
57
+	 * @var EEM_Event $event_model
58
+	 */
59
+	private $event_model;
60
+
61
+	/**
62
+	 * @var EEM_Status $status_model
63
+	 */
64
+	private $status_model;
65
+
66
+
67
+	/**
68
+	 * @param bool $routing
69
+	 * @throws EE_Error
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws ReflectionException
74
+	 */
75
+	public function __construct($routing = true)
76
+	{
77
+		parent::__construct($routing);
78
+		add_action('wp_loaded', array($this, 'wp_loaded'));
79
+	}
80
+
81
+	/**
82
+	 * @return EEM_Registration
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidInterfaceException
86
+	 * @since 4.10.2.p
87
+	 */
88
+	protected function getRegistrationModel()
89
+	{
90
+		if (! $this->registration_model instanceof EEM_Registration) {
91
+			$this->registration_model = $this->getLoader()->getShared('EEM_Registration');
92
+		}
93
+		return $this->registration_model;
94
+	}
95
+
96
+	/**
97
+	 * @return EEM_Attendee
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidDataTypeException
100
+	 * @throws InvalidInterfaceException
101
+	 * @since 4.10.2.p
102
+	 */
103
+	protected function getAttendeeModel()
104
+	{
105
+		if (! $this->attendee_model instanceof EEM_Attendee) {
106
+			$this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
107
+		}
108
+		return $this->attendee_model;
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return EEM_Event
114
+	 * @throws InvalidArgumentException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidInterfaceException
117
+	 * @since 4.10.2.p
118
+	 */
119
+	protected function getEventModel()
120
+	{
121
+		if (! $this->event_model instanceof EEM_Event) {
122
+			$this->event_model = $this->getLoader()->getShared('EEM_Event');
123
+		}
124
+		return $this->event_model;
125
+	}
126
+
127
+	/**
128
+	 * @return EEM_Status
129
+	 * @throws InvalidArgumentException
130
+	 * @throws InvalidDataTypeException
131
+	 * @throws InvalidInterfaceException
132
+	 * @since 4.10.2.p
133
+	 */
134
+	protected function getStatusModel()
135
+	{
136
+		if (! $this->status_model instanceof EEM_Status) {
137
+			$this->status_model = $this->getLoader()->getShared('EEM_Status');
138
+		}
139
+		return $this->status_model;
140
+	}
141
+
142
+
143
+	public function wp_loaded()
144
+	{
145
+		// when adding a new registration...
146
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
147
+			EE_System::do_not_cache();
148
+			if (! isset($this->_req_data['processing_registration'])
149
+				|| absint($this->_req_data['processing_registration']) !== 1
150
+			) {
151
+				// and it's NOT the attendee information reg step
152
+				// force cookie expiration by setting time to last week
153
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
154
+				// and update the global
155
+				$_COOKIE['ee_registration_added'] = 0;
156
+			}
157
+		}
158
+	}
159
+
160
+
161
+	protected function _init_page_props()
162
+	{
163
+		$this->page_slug = REG_PG_SLUG;
164
+		$this->_admin_base_url = REG_ADMIN_URL;
165
+		$this->_admin_base_path = REG_ADMIN;
166
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
167
+		$this->_cpt_routes = array(
168
+			'add_new_attendee' => 'espresso_attendees',
169
+			'edit_attendee'    => 'espresso_attendees',
170
+			'insert_attendee'  => 'espresso_attendees',
171
+			'update_attendee'  => 'espresso_attendees',
172
+		);
173
+		$this->_cpt_model_names = array(
174
+			'add_new_attendee' => 'EEM_Attendee',
175
+			'edit_attendee'    => 'EEM_Attendee',
176
+		);
177
+		$this->_cpt_edit_routes = array(
178
+			'espresso_attendees' => 'edit_attendee',
179
+		);
180
+		$this->_pagenow_map = array(
181
+			'add_new_attendee' => 'post-new.php',
182
+			'edit_attendee'    => 'post.php',
183
+			'trash'            => 'post.php',
184
+		);
185
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
186
+		// add filters so that the comment urls don't take users to a confusing 404 page
187
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
188
+	}
189
+
190
+
191
+	public function clear_comment_link($link, $comment, $args)
192
+	{
193
+		// gotta make sure this only happens on this route
194
+		$post_type = get_post_type($comment->comment_post_ID);
195
+		if ($post_type === 'espresso_attendees') {
196
+			return '#commentsdiv';
197
+		}
198
+		return $link;
199
+	}
200
+
201
+
202
+	protected function _ajax_hooks()
203
+	{
204
+		// todo: all hooks for registrations ajax goes in here
205
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
206
+	}
207
+
208
+
209
+	protected function _define_page_props()
210
+	{
211
+		$this->_admin_page_title = $this->page_label;
212
+		$this->_labels = array(
213
+			'buttons'                      => array(
214
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
215
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
216
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
217
+				'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
218
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
219
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
220
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
221
+				'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
222
+			),
223
+			'publishbox'                   => array(
224
+				'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
225
+				'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
226
+			),
227
+			'hide_add_button_on_cpt_route' => array(
228
+				'edit_attendee' => true,
229
+			),
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 *        grab url requests and route them
236
+	 *
237
+	 * @access private
238
+	 * @return void
239
+	 * @throws EE_Error
240
+	 */
241
+	public function _set_page_routes()
242
+	{
243
+		$this->_get_registration_status_array();
244
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
245
+			? $this->_req_data['_REG_ID'] : 0;
246
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
247
+			? $this->_req_data['reg_status_change_form']['REG_ID']
248
+			: $reg_id;
249
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
250
+			? $this->_req_data['ATT_ID'] : 0;
251
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
252
+			? $this->_req_data['post']
253
+			: $att_id;
254
+		$this->_page_routes = array(
255
+			'default'                             => array(
256
+				'func'       => '_registrations_overview_list_table',
257
+				'capability' => 'ee_read_registrations',
258
+			),
259
+			'view_registration'                   => array(
260
+				'func'       => '_registration_details',
261
+				'capability' => 'ee_read_registration',
262
+				'obj_id'     => $reg_id,
263
+			),
264
+			'edit_registration'                   => array(
265
+				'func'               => '_update_attendee_registration_form',
266
+				'noheader'           => true,
267
+				'headers_sent_route' => 'view_registration',
268
+				'capability'         => 'ee_edit_registration',
269
+				'obj_id'             => $reg_id,
270
+				'_REG_ID'            => $reg_id,
271
+			),
272
+			'trash_registrations'                 => array(
273
+				'func'       => '_trash_or_restore_registrations',
274
+				'args'       => array('trash' => true),
275
+				'noheader'   => true,
276
+				'capability' => 'ee_delete_registrations',
277
+			),
278
+			'restore_registrations'               => array(
279
+				'func'       => '_trash_or_restore_registrations',
280
+				'args'       => array('trash' => false),
281
+				'noheader'   => true,
282
+				'capability' => 'ee_delete_registrations',
283
+			),
284
+			'delete_registrations'                => array(
285
+				'func'       => '_delete_registrations',
286
+				'noheader'   => true,
287
+				'capability' => 'ee_delete_registrations',
288
+			),
289
+			'new_registration'                    => array(
290
+				'func'       => 'new_registration',
291
+				'capability' => 'ee_edit_registrations',
292
+			),
293
+			'process_reg_step'                    => array(
294
+				'func'       => 'process_reg_step',
295
+				'noheader'   => true,
296
+				'capability' => 'ee_edit_registrations',
297
+			),
298
+			'redirect_to_txn'                     => array(
299
+				'func'       => 'redirect_to_txn',
300
+				'noheader'   => true,
301
+				'capability' => 'ee_edit_registrations',
302
+			),
303
+			'change_reg_status'                   => array(
304
+				'func'       => '_change_reg_status',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'approve_registration'                => array(
310
+				'func'       => 'approve_registration',
311
+				'noheader'   => true,
312
+				'capability' => 'ee_edit_registration',
313
+				'obj_id'     => $reg_id,
314
+			),
315
+			'approve_and_notify_registration'     => array(
316
+				'func'       => 'approve_registration',
317
+				'noheader'   => true,
318
+				'args'       => array(true),
319
+				'capability' => 'ee_edit_registration',
320
+				'obj_id'     => $reg_id,
321
+			),
322
+			'approve_registrations'               => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('approve'),
327
+			),
328
+			'approve_and_notify_registrations'    => array(
329
+				'func'       => 'bulk_action_on_registrations',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registrations',
332
+				'args'       => array('approve', true),
333
+			),
334
+			'decline_registration'                => array(
335
+				'func'       => 'decline_registration',
336
+				'noheader'   => true,
337
+				'capability' => 'ee_edit_registration',
338
+				'obj_id'     => $reg_id,
339
+			),
340
+			'decline_and_notify_registration'     => array(
341
+				'func'       => 'decline_registration',
342
+				'noheader'   => true,
343
+				'args'       => array(true),
344
+				'capability' => 'ee_edit_registration',
345
+				'obj_id'     => $reg_id,
346
+			),
347
+			'decline_registrations'               => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('decline'),
352
+			),
353
+			'decline_and_notify_registrations'    => array(
354
+				'func'       => 'bulk_action_on_registrations',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registrations',
357
+				'args'       => array('decline', true),
358
+			),
359
+			'pending_registration'                => array(
360
+				'func'       => 'pending_registration',
361
+				'noheader'   => true,
362
+				'capability' => 'ee_edit_registration',
363
+				'obj_id'     => $reg_id,
364
+			),
365
+			'pending_and_notify_registration'     => array(
366
+				'func'       => 'pending_registration',
367
+				'noheader'   => true,
368
+				'args'       => array(true),
369
+				'capability' => 'ee_edit_registration',
370
+				'obj_id'     => $reg_id,
371
+			),
372
+			'pending_registrations'               => array(
373
+				'func'       => 'bulk_action_on_registrations',
374
+				'noheader'   => true,
375
+				'capability' => 'ee_edit_registrations',
376
+				'args'       => array('pending'),
377
+			),
378
+			'pending_and_notify_registrations'    => array(
379
+				'func'       => 'bulk_action_on_registrations',
380
+				'noheader'   => true,
381
+				'capability' => 'ee_edit_registrations',
382
+				'args'       => array('pending', true),
383
+			),
384
+			'no_approve_registration'             => array(
385
+				'func'       => 'not_approve_registration',
386
+				'noheader'   => true,
387
+				'capability' => 'ee_edit_registration',
388
+				'obj_id'     => $reg_id,
389
+			),
390
+			'no_approve_and_notify_registration'  => array(
391
+				'func'       => 'not_approve_registration',
392
+				'noheader'   => true,
393
+				'args'       => array(true),
394
+				'capability' => 'ee_edit_registration',
395
+				'obj_id'     => $reg_id,
396
+			),
397
+			'no_approve_registrations'            => array(
398
+				'func'       => 'bulk_action_on_registrations',
399
+				'noheader'   => true,
400
+				'capability' => 'ee_edit_registrations',
401
+				'args'       => array('not_approve'),
402
+			),
403
+			'no_approve_and_notify_registrations' => array(
404
+				'func'       => 'bulk_action_on_registrations',
405
+				'noheader'   => true,
406
+				'capability' => 'ee_edit_registrations',
407
+				'args'       => array('not_approve', true),
408
+			),
409
+			'cancel_registration'                 => array(
410
+				'func'       => 'cancel_registration',
411
+				'noheader'   => true,
412
+				'capability' => 'ee_edit_registration',
413
+				'obj_id'     => $reg_id,
414
+			),
415
+			'cancel_and_notify_registration'      => array(
416
+				'func'       => 'cancel_registration',
417
+				'noheader'   => true,
418
+				'args'       => array(true),
419
+				'capability' => 'ee_edit_registration',
420
+				'obj_id'     => $reg_id,
421
+			),
422
+			'cancel_registrations'                => array(
423
+				'func'       => 'bulk_action_on_registrations',
424
+				'noheader'   => true,
425
+				'capability' => 'ee_edit_registrations',
426
+				'args'       => array('cancel'),
427
+			),
428
+			'cancel_and_notify_registrations'     => array(
429
+				'func'       => 'bulk_action_on_registrations',
430
+				'noheader'   => true,
431
+				'capability' => 'ee_edit_registrations',
432
+				'args'       => array('cancel', true),
433
+			),
434
+			'wait_list_registration'              => array(
435
+				'func'       => 'wait_list_registration',
436
+				'noheader'   => true,
437
+				'capability' => 'ee_edit_registration',
438
+				'obj_id'     => $reg_id,
439
+			),
440
+			'wait_list_and_notify_registration'   => array(
441
+				'func'       => 'wait_list_registration',
442
+				'noheader'   => true,
443
+				'args'       => array(true),
444
+				'capability' => 'ee_edit_registration',
445
+				'obj_id'     => $reg_id,
446
+			),
447
+			'contact_list'                        => array(
448
+				'func'       => '_attendee_contact_list_table',
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+			'add_new_attendee'                    => array(
452
+				'func' => '_create_new_cpt_item',
453
+				'args' => array(
454
+					'new_attendee' => true,
455
+					'capability'   => 'ee_edit_contacts',
456
+				),
457
+			),
458
+			'edit_attendee'                       => array(
459
+				'func'       => '_edit_cpt_item',
460
+				'capability' => 'ee_edit_contacts',
461
+				'obj_id'     => $att_id,
462
+			),
463
+			'duplicate_attendee'                  => array(
464
+				'func'       => '_duplicate_attendee',
465
+				'noheader'   => true,
466
+				'capability' => 'ee_edit_contacts',
467
+				'obj_id'     => $att_id,
468
+			),
469
+			'insert_attendee'                     => array(
470
+				'func'       => '_insert_or_update_attendee',
471
+				'args'       => array(
472
+					'new_attendee' => true,
473
+				),
474
+				'noheader'   => true,
475
+				'capability' => 'ee_edit_contacts',
476
+			),
477
+			'update_attendee'                     => array(
478
+				'func'       => '_insert_or_update_attendee',
479
+				'args'       => array(
480
+					'new_attendee' => false,
481
+				),
482
+				'noheader'   => true,
483
+				'capability' => 'ee_edit_contacts',
484
+				'obj_id'     => $att_id,
485
+			),
486
+			'trash_attendees'                     => array(
487
+				'func'       => '_trash_or_restore_attendees',
488
+				'args'       => array(
489
+					'trash' => 'true',
490
+				),
491
+				'noheader'   => true,
492
+				'capability' => 'ee_delete_contacts',
493
+			),
494
+			'trash_attendee'                      => array(
495
+				'func'       => '_trash_or_restore_attendees',
496
+				'args'       => array(
497
+					'trash' => true,
498
+				),
499
+				'noheader'   => true,
500
+				'capability' => 'ee_delete_contacts',
501
+				'obj_id'     => $att_id,
502
+			),
503
+			'restore_attendees'                   => array(
504
+				'func'       => '_trash_or_restore_attendees',
505
+				'args'       => array(
506
+					'trash' => false,
507
+				),
508
+				'noheader'   => true,
509
+				'capability' => 'ee_delete_contacts',
510
+				'obj_id'     => $att_id,
511
+			),
512
+			'resend_registration'                 => array(
513
+				'func'       => '_resend_registration',
514
+				'noheader'   => true,
515
+				'capability' => 'ee_send_message',
516
+			),
517
+			'registrations_report'                => array(
518
+				'func'       => '_registrations_report',
519
+				'noheader'   => true,
520
+				'capability' => 'ee_read_registrations',
521
+			),
522
+			'contact_list_export'                 => array(
523
+				'func'       => '_contact_list_export',
524
+				'noheader'   => true,
525
+				'capability' => 'export',
526
+			),
527
+			'contact_list_report'                 => array(
528
+				'func'       => '_contact_list_report',
529
+				'noheader'   => true,
530
+				'capability' => 'ee_read_contacts',
531
+			),
532
+		);
533
+	}
534
+
535
+
536
+	protected function _set_page_config()
537
+	{
538
+		$this->_page_config = array(
539
+			'default'           => array(
540
+				'nav'           => array(
541
+					'label' => esc_html__('Overview', 'event_espresso'),
542
+					'order' => 5,
543
+				),
544
+				'help_tabs'     => array(
545
+					'registrations_overview_help_tab'                       => array(
546
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
547
+						'filename' => 'registrations_overview',
548
+					),
549
+					'registrations_overview_table_column_headings_help_tab' => array(
550
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
551
+						'filename' => 'registrations_overview_table_column_headings',
552
+					),
553
+					'registrations_overview_filters_help_tab'               => array(
554
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
555
+						'filename' => 'registrations_overview_filters',
556
+					),
557
+					'registrations_overview_views_help_tab'                 => array(
558
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
559
+						'filename' => 'registrations_overview_views',
560
+					),
561
+					'registrations_regoverview_other_help_tab'              => array(
562
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
563
+						'filename' => 'registrations_overview_other',
564
+					),
565
+				),
566
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
567
+				// 'help_tour'     => array('Registration_Overview_Help_Tour'),
568
+				'qtips'         => array('Registration_List_Table_Tips'),
569
+				'list_table'    => 'EE_Registrations_List_Table',
570
+				'require_nonce' => false,
571
+			),
572
+			'view_registration' => array(
573
+				'nav'           => array(
574
+					'label'      => esc_html__('REG Details', 'event_espresso'),
575
+					'order'      => 15,
576
+					'url'        => isset($this->_req_data['_REG_ID'])
577
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
578
+						: $this->_admin_base_url,
579
+					'persistent' => false,
580
+				),
581
+				'help_tabs'     => array(
582
+					'registrations_details_help_tab'                    => array(
583
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
584
+						'filename' => 'registrations_details',
585
+					),
586
+					'registrations_details_table_help_tab'              => array(
587
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
588
+						'filename' => 'registrations_details_table',
589
+					),
590
+					'registrations_details_form_answers_help_tab'       => array(
591
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
592
+						'filename' => 'registrations_details_form_answers',
593
+					),
594
+					'registrations_details_registrant_details_help_tab' => array(
595
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
596
+						'filename' => 'registrations_details_registrant_details',
597
+					),
598
+				),
599
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
600
+				// 'help_tour'     => array('Registration_Details_Help_Tour'),
601
+				'metaboxes'     => array_merge(
602
+					$this->_default_espresso_metaboxes,
603
+					array('_registration_details_metaboxes')
604
+				),
605
+				'require_nonce' => false,
606
+			),
607
+			'new_registration'  => array(
608
+				'nav'           => array(
609
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
610
+					'url'        => '#',
611
+					'order'      => 15,
612
+					'persistent' => false,
613
+				),
614
+				'metaboxes'     => $this->_default_espresso_metaboxes,
615
+				'labels'        => array(
616
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
617
+				),
618
+				'require_nonce' => false,
619
+			),
620
+			'add_new_attendee'  => array(
621
+				'nav'           => array(
622
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
623
+					'order'      => 15,
624
+					'persistent' => false,
625
+				),
626
+				'metaboxes'     => array_merge(
627
+					$this->_default_espresso_metaboxes,
628
+					array('_publish_post_box', 'attendee_editor_metaboxes')
629
+				),
630
+				'require_nonce' => false,
631
+			),
632
+			'edit_attendee'     => array(
633
+				'nav'           => array(
634
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
635
+					'order'      => 15,
636
+					'persistent' => false,
637
+					'url'        => isset($this->_req_data['ATT_ID'])
638
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
639
+						: $this->_admin_base_url,
640
+				),
641
+				'metaboxes'     => array('attendee_editor_metaboxes'),
642
+				'require_nonce' => false,
643
+			),
644
+			'contact_list'      => array(
645
+				'nav'           => array(
646
+					'label' => esc_html__('Contact List', 'event_espresso'),
647
+					'order' => 20,
648
+				),
649
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
650
+				'help_tabs'     => array(
651
+					'registrations_contact_list_help_tab'                       => array(
652
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
653
+						'filename' => 'registrations_contact_list',
654
+					),
655
+					'registrations_contact-list_table_column_headings_help_tab' => array(
656
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
657
+						'filename' => 'registrations_contact_list_table_column_headings',
658
+					),
659
+					'registrations_contact_list_views_help_tab'                 => array(
660
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
661
+						'filename' => 'registrations_contact_list_views',
662
+					),
663
+					'registrations_contact_list_other_help_tab'                 => array(
664
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
665
+						'filename' => 'registrations_contact_list_other',
666
+					),
667
+				),
668
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
669
+				// 'help_tour'     => array('Contact_List_Help_Tour'),
670
+				'metaboxes'     => array(),
671
+				'require_nonce' => false,
672
+			),
673
+			// override default cpt routes
674
+			'create_new'        => '',
675
+			'edit'              => '',
676
+		);
677
+	}
678
+
679
+
680
+	/**
681
+	 * The below methods aren't used by this class currently
682
+	 */
683
+	protected function _add_screen_options()
684
+	{
685
+	}
686
+
687
+
688
+	protected function _add_feature_pointers()
689
+	{
690
+	}
691
+
692
+
693
+	public function admin_init()
694
+	{
695
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
696
+			'click "Update Registration Questions" to save your changes',
697
+			'event_espresso'
698
+		);
699
+	}
700
+
701
+
702
+	public function admin_notices()
703
+	{
704
+	}
705
+
706
+
707
+	public function admin_footer_scripts()
708
+	{
709
+	}
710
+
711
+
712
+	/**
713
+	 *        get list of registration statuses
714
+	 *
715
+	 * @access private
716
+	 * @return void
717
+	 * @throws EE_Error
718
+	 */
719
+	private function _get_registration_status_array()
720
+	{
721
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
722
+	}
723
+
724
+
725
+	/**
726
+	 * @throws InvalidArgumentException
727
+	 * @throws InvalidDataTypeException
728
+	 * @throws InvalidInterfaceException
729
+	 * @since 4.10.2.p
730
+	 */
731
+	protected function _add_screen_options_default()
732
+	{
733
+		$this->_per_page_screen_option();
734
+	}
735
+
736
+
737
+	/**
738
+	 * @throws InvalidArgumentException
739
+	 * @throws InvalidDataTypeException
740
+	 * @throws InvalidInterfaceException
741
+	 * @since 4.10.2.p
742
+	 */
743
+	protected function _add_screen_options_contact_list()
744
+	{
745
+		$page_title = $this->_admin_page_title;
746
+		$this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
747
+		$this->_per_page_screen_option();
748
+		$this->_admin_page_title = $page_title;
749
+	}
750
+
751
+
752
+	public function load_scripts_styles()
753
+	{
754
+		// style
755
+		wp_register_style(
756
+			'espresso_reg',
757
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
758
+			array('ee-admin-css'),
759
+			EVENT_ESPRESSO_VERSION
760
+		);
761
+		wp_enqueue_style('espresso_reg');
762
+		// script
763
+		wp_register_script(
764
+			'espresso_reg',
765
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
766
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
767
+			EVENT_ESPRESSO_VERSION,
768
+			true
769
+		);
770
+		wp_enqueue_script('espresso_reg');
771
+	}
772
+
773
+
774
+	/**
775
+	 * @throws EE_Error
776
+	 * @throws InvalidArgumentException
777
+	 * @throws InvalidDataTypeException
778
+	 * @throws InvalidInterfaceException
779
+	 * @throws ReflectionException
780
+	 * @since 4.10.2.p
781
+	 */
782
+	public function load_scripts_styles_edit_attendee()
783
+	{
784
+		// stuff to only show up on our attendee edit details page.
785
+		$attendee_details_translations = array(
786
+			'att_publish_text' => sprintf(
787
+				/* translators: The date and time */
788
+				wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
789
+				'<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
790
+			),
791
+		);
792
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
793
+		wp_enqueue_script('jquery-validate');
794
+	}
795
+
796
+
797
+	/**
798
+	 * @throws EE_Error
799
+	 * @throws InvalidArgumentException
800
+	 * @throws InvalidDataTypeException
801
+	 * @throws InvalidInterfaceException
802
+	 * @throws ReflectionException
803
+	 * @since 4.10.2.p
804
+	 */
805
+	public function load_scripts_styles_view_registration()
806
+	{
807
+		// styles
808
+		wp_enqueue_style('espresso-ui-theme');
809
+		// scripts
810
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
811
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
812
+	}
813
+
814
+
815
+	public function load_scripts_styles_contact_list()
816
+	{
817
+		wp_dequeue_style('espresso_reg');
818
+		wp_register_style(
819
+			'espresso_att',
820
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
821
+			array('ee-admin-css'),
822
+			EVENT_ESPRESSO_VERSION
823
+		);
824
+		wp_enqueue_style('espresso_att');
825
+	}
826
+
827
+
828
+	public function load_scripts_styles_new_registration()
829
+	{
830
+		wp_register_script(
831
+			'ee-spco-for-admin',
832
+			REG_ASSETS_URL . 'spco_for_admin.js',
833
+			array('underscore', 'jquery'),
834
+			EVENT_ESPRESSO_VERSION,
835
+			true
836
+		);
837
+		wp_enqueue_script('ee-spco-for-admin');
838
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
839
+		EE_Form_Section_Proper::wp_enqueue_scripts();
840
+		EED_Ticket_Selector::load_tckt_slctr_assets();
841
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
842
+	}
843
+
844
+
845
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
846
+	{
847
+		add_filter('FHEE_load_EE_messages', '__return_true');
848
+	}
849
+
850
+
851
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
852
+	{
853
+		add_filter('FHEE_load_EE_messages', '__return_true');
854
+	}
855
+
856
+
857
+	/**
858
+	 * @throws EE_Error
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws InvalidInterfaceException
862
+	 * @throws ReflectionException
863
+	 * @since 4.10.2.p
864
+	 */
865
+	protected function _set_list_table_views_default()
866
+	{
867
+		// for notification related bulk actions we need to make sure only active messengers have an option.
868
+		EED_Messages::set_autoloaders();
869
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
870
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
871
+		$active_mts = $message_resource_manager->list_of_active_message_types();
872
+		// key= bulk_action_slug, value= message type.
873
+		$match_array = array(
874
+			'approve_registrations'    => 'registration',
875
+			'decline_registrations'    => 'declined_registration',
876
+			'pending_registrations'    => 'pending_approval',
877
+			'no_approve_registrations' => 'not_approved_registration',
878
+			'cancel_registrations'     => 'cancelled_registration',
879
+		);
880
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
881
+			'ee_send_message',
882
+			'batch_send_messages'
883
+		);
884
+		/** setup reg status bulk actions **/
885
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
886
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
887
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
888
+				'Approve and Notify Registrations',
889
+				'event_espresso'
890
+			);
891
+		}
892
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
893
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
894
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
895
+				'Decline and Notify Registrations',
896
+				'event_espresso'
897
+			);
898
+		}
899
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
900
+			'Set Registrations to Pending Payment',
901
+			'event_espresso'
902
+		);
903
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
904
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
905
+				'Set Registrations to Pending Payment and Notify',
906
+				'event_espresso'
907
+			);
908
+		}
909
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
910
+			'Set Registrations to Not Approved',
911
+			'event_espresso'
912
+		);
913
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
914
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
915
+				'Set Registrations to Not Approved and Notify',
916
+				'event_espresso'
917
+			);
918
+		}
919
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
920
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
921
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
922
+				'Cancel Registrations and Notify',
923
+				'event_espresso'
924
+			);
925
+		}
926
+		$def_reg_status_actions = apply_filters(
927
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
928
+			$def_reg_status_actions,
929
+			$active_mts,
930
+			$can_send
931
+		);
932
+
933
+		$this->_views = array(
934
+			'all'   => array(
935
+				'slug'        => 'all',
936
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
937
+				'count'       => 0,
938
+				'bulk_action' => array_merge(
939
+					$def_reg_status_actions,
940
+					array(
941
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
942
+					)
943
+				),
944
+			),
945
+			'month' => array(
946
+				'slug'        => 'month',
947
+				'label'       => esc_html__('This Month', 'event_espresso'),
948
+				'count'       => 0,
949
+				'bulk_action' => array_merge(
950
+					$def_reg_status_actions,
951
+					array(
952
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
953
+					)
954
+				),
955
+			),
956
+			'today' => array(
957
+				'slug'        => 'today',
958
+				'label'       => sprintf(
959
+					esc_html__('Today - %s', 'event_espresso'),
960
+					date('M d, Y', current_time('timestamp'))
961
+				),
962
+				'count'       => 0,
963
+				'bulk_action' => array_merge(
964
+					$def_reg_status_actions,
965
+					array(
966
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
967
+					)
968
+				),
969
+			),
970
+		);
971
+		if (EE_Registry::instance()->CAP->current_user_can(
972
+			'ee_delete_registrations',
973
+			'espresso_registrations_delete_registration'
974
+		)) {
975
+			$this->_views['incomplete'] = array(
976
+				'slug'        => 'incomplete',
977
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
978
+				'count'       => 0,
979
+				'bulk_action' => array(
980
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
981
+				),
982
+			);
983
+			$this->_views['trash'] = array(
984
+				'slug'        => 'trash',
985
+				'label'       => esc_html__('Trash', 'event_espresso'),
986
+				'count'       => 0,
987
+				'bulk_action' => array(
988
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
989
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
990
+				),
991
+			);
992
+		}
993
+	}
994
+
995
+
996
+	protected function _set_list_table_views_contact_list()
997
+	{
998
+		$this->_views = array(
999
+			'in_use' => array(
1000
+				'slug'        => 'in_use',
1001
+				'label'       => esc_html__('In Use', 'event_espresso'),
1002
+				'count'       => 0,
1003
+				'bulk_action' => array(
1004
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1005
+				),
1006
+			),
1007
+		);
1008
+		if (EE_Registry::instance()->CAP->current_user_can(
1009
+			'ee_delete_contacts',
1010
+			'espresso_registrations_trash_attendees'
1011
+		)
1012
+		) {
1013
+			$this->_views['trash'] = array(
1014
+				'slug'        => 'trash',
1015
+				'label'       => esc_html__('Trash', 'event_espresso'),
1016
+				'count'       => 0,
1017
+				'bulk_action' => array(
1018
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1019
+				),
1020
+			);
1021
+		}
1022
+	}
1023
+
1024
+
1025
+	protected function _registration_legend_items()
1026
+	{
1027
+		$fc_items = array(
1028
+			'star-icon'        => array(
1029
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1030
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1031
+			),
1032
+			'view_details'     => array(
1033
+				'class' => 'dashicons dashicons-clipboard',
1034
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1035
+			),
1036
+			'edit_attendee'    => array(
1037
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1038
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1039
+			),
1040
+			'view_transaction' => array(
1041
+				'class' => 'dashicons dashicons-cart',
1042
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1043
+			),
1044
+			'view_invoice'     => array(
1045
+				'class' => 'dashicons dashicons-media-spreadsheet',
1046
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1047
+			),
1048
+		);
1049
+		if (EE_Registry::instance()->CAP->current_user_can(
1050
+			'ee_send_message',
1051
+			'espresso_registrations_resend_registration'
1052
+		)) {
1053
+			$fc_items['resend_registration'] = array(
1054
+				'class' => 'dashicons dashicons-email-alt',
1055
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1056
+			);
1057
+		} else {
1058
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
1059
+		}
1060
+		if (EE_Registry::instance()->CAP->current_user_can(
1061
+			'ee_read_global_messages',
1062
+			'view_filtered_messages'
1063
+		)) {
1064
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1065
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1066
+				$fc_items['view_related_messages'] = array(
1067
+					'class' => $related_for_icon['css_class'],
1068
+					'desc'  => $related_for_icon['label'],
1069
+				);
1070
+			}
1071
+		}
1072
+		$sc_items = array(
1073
+			'approved_status'   => array(
1074
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1075
+				'desc'  => EEH_Template::pretty_status(
1076
+					EEM_Registration::status_id_approved,
1077
+					false,
1078
+					'sentence'
1079
+				),
1080
+			),
1081
+			'pending_status'    => array(
1082
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1083
+				'desc'  => EEH_Template::pretty_status(
1084
+					EEM_Registration::status_id_pending_payment,
1085
+					false,
1086
+					'sentence'
1087
+				),
1088
+			),
1089
+			'wait_list'         => array(
1090
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1091
+				'desc'  => EEH_Template::pretty_status(
1092
+					EEM_Registration::status_id_wait_list,
1093
+					false,
1094
+					'sentence'
1095
+				),
1096
+			),
1097
+			'incomplete_status' => array(
1098
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1099
+				'desc'  => EEH_Template::pretty_status(
1100
+					EEM_Registration::status_id_incomplete,
1101
+					false,
1102
+					'sentence'
1103
+				),
1104
+			),
1105
+			'not_approved'      => array(
1106
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1107
+				'desc'  => EEH_Template::pretty_status(
1108
+					EEM_Registration::status_id_not_approved,
1109
+					false,
1110
+					'sentence'
1111
+				),
1112
+			),
1113
+			'declined_status'   => array(
1114
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1115
+				'desc'  => EEH_Template::pretty_status(
1116
+					EEM_Registration::status_id_declined,
1117
+					false,
1118
+					'sentence'
1119
+				),
1120
+			),
1121
+			'cancelled_status'  => array(
1122
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1123
+				'desc'  => EEH_Template::pretty_status(
1124
+					EEM_Registration::status_id_cancelled,
1125
+					false,
1126
+					'sentence'
1127
+				),
1128
+			),
1129
+		);
1130
+		return array_merge($fc_items, $sc_items);
1131
+	}
1132
+
1133
+
1134
+
1135
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1136
+
1137
+
1138
+
1139
+	/**
1140
+	 * @throws DomainException
1141
+	 * @throws EE_Error
1142
+	 * @throws InvalidArgumentException
1143
+	 * @throws InvalidDataTypeException
1144
+	 * @throws InvalidInterfaceException
1145
+	 * @throws ReflectionException
1146
+	 */
1147
+	protected function _registrations_overview_list_table()
1148
+	{
1149
+		$this->appendAddNewRegistrationButtonToPageTitle();
1150
+		$header_text = '';
1151
+		$admin_page_header_decorators = [
1152
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1153
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1154
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1155
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1156
+		];
1157
+		foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1158
+			$filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1159
+			$header_text = $filter_header_decorator->getHeaderText($header_text);
1160
+		}
1161
+		$this->_template_args['admin_page_header'] = $header_text;
1162
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1163
+		$this->display_admin_list_table_page_with_no_sidebar();
1164
+	}
1165
+
1166
+
1167
+	/**
1168
+	 * @throws EE_Error
1169
+	 * @throws InvalidArgumentException
1170
+	 * @throws InvalidDataTypeException
1171
+	 * @throws InvalidInterfaceException
1172
+	 */
1173
+	private function appendAddNewRegistrationButtonToPageTitle()
1174
+	{
1175
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1176
+			? absint($this->_req_data['event_id'])
1177
+			: 0;
1178
+		if ($EVT_ID
1179
+			&& EE_Registry::instance()->CAP->current_user_can(
1180
+				'ee_edit_registrations',
1181
+				'espresso_registrations_new_registration',
1182
+				$EVT_ID
1183
+			)
1184
+		) {
1185
+			$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1186
+				'new_registration',
1187
+				'add-registrant',
1188
+				array('event_id' => $EVT_ID),
1189
+				'add-new-h2'
1190
+			);
1191
+		}
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * This sets the _registration property for the registration details screen
1197
+	 *
1198
+	 * @access private
1199
+	 * @return bool
1200
+	 * @throws EE_Error
1201
+	 * @throws InvalidArgumentException
1202
+	 * @throws InvalidDataTypeException
1203
+	 * @throws InvalidInterfaceException
1204
+	 */
1205
+	private function _set_registration_object()
1206
+	{
1207
+		// get out if we've already set the object
1208
+		if ($this->_registration instanceof EE_Registration) {
1209
+			return true;
1210
+		}
1211
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1212
+		if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1213
+			return true;
1214
+		}
1215
+		$error_msg = sprintf(
1216
+			esc_html__(
1217
+				'An error occurred and the details for Registration ID #%s could not be retrieved.',
1218
+				'event_espresso'
1219
+			),
1220
+			$REG_ID
1221
+		);
1222
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1223
+		$this->_registration = null;
1224
+		return false;
1225
+	}
1226
+
1227
+
1228
+	/**
1229
+	 * Used to retrieve registrations for the list table.
1230
+	 *
1231
+	 * @param int  $per_page
1232
+	 * @param bool $count
1233
+	 * @param bool $this_month
1234
+	 * @param bool $today
1235
+	 * @return EE_Registration[]|int
1236
+	 * @throws EE_Error
1237
+	 * @throws InvalidArgumentException
1238
+	 * @throws InvalidDataTypeException
1239
+	 * @throws InvalidInterfaceException
1240
+	 */
1241
+	public function get_registrations(
1242
+		$per_page = 10,
1243
+		$count = false,
1244
+		$this_month = false,
1245
+		$today = false
1246
+	) {
1247
+		if ($this_month) {
1248
+			$this->_req_data['status'] = 'month';
1249
+		}
1250
+		if ($today) {
1251
+			$this->_req_data['status'] = 'today';
1252
+		}
1253
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1254
+		/**
1255
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1256
+		 *
1257
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1258
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1259
+		 *                             or if you have the development copy of EE you can view this at the path:
1260
+		 *                             /docs/G--Model-System/model-query-params.md
1261
+		 */
1262
+		$query_params['group_by'] = '';
1263
+
1264
+		return $count
1265
+			? $this->getRegistrationModel()->count($query_params)
1266
+			/** @type EE_Registration[] */
1267
+			: $this->getRegistrationModel()->get_all($query_params);
1268
+	}
1269
+
1270
+
1271
+	/**
1272
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1273
+	 * Note: this listens to values on the request for some of the query parameters.
1274
+	 *
1275
+	 * @param array $request
1276
+	 * @param int   $per_page
1277
+	 * @param bool  $count
1278
+	 * @return array
1279
+	 * @throws EE_Error
1280
+	 * @throws InvalidArgumentException
1281
+	 * @throws InvalidDataTypeException
1282
+	 * @throws InvalidInterfaceException
1283
+	 */
1284
+	protected function _get_registration_query_parameters(
1285
+		$request = array(),
1286
+		$per_page = 10,
1287
+		$count = false
1288
+	) {
1289
+		/** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1290
+		$list_table_query_builder = $this->getLoader()->getNew(
1291
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1292
+			[ $request ]
1293
+		);
1294
+		return $list_table_query_builder->getQueryParams($per_page, $count);
1295
+	}
1296
+
1297
+
1298
+	public function get_registration_status_array()
1299
+	{
1300
+		return self::$_reg_status;
1301
+	}
1302
+
1303
+
1304
+
1305
+
1306
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1307
+	/**
1308
+	 *        generates HTML for the View Registration Details Admin page
1309
+	 *
1310
+	 * @access protected
1311
+	 * @return void
1312
+	 * @throws DomainException
1313
+	 * @throws EE_Error
1314
+	 * @throws InvalidArgumentException
1315
+	 * @throws InvalidDataTypeException
1316
+	 * @throws InvalidInterfaceException
1317
+	 * @throws EntityNotFoundException
1318
+	 * @throws ReflectionException
1319
+	 */
1320
+	protected function _registration_details()
1321
+	{
1322
+		$this->_template_args = array();
1323
+		$this->_set_registration_object();
1324
+		if (is_object($this->_registration)) {
1325
+			$transaction = $this->_registration->transaction()
1326
+				? $this->_registration->transaction()
1327
+				: EE_Transaction::new_instance();
1328
+			$this->_session = $transaction->session_data();
1329
+			$event_id = $this->_registration->event_ID();
1330
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1331
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1332
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1333
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1334
+			$this->_template_args['grand_total'] = $transaction->total();
1335
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1336
+			// link back to overview
1337
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1338
+			$this->_template_args['registration'] = $this->_registration;
1339
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1340
+				array(
1341
+					'action'   => 'default',
1342
+					'event_id' => $event_id,
1343
+				),
1344
+				REG_ADMIN_URL
1345
+			);
1346
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1347
+				array(
1348
+					'action' => 'default',
1349
+					'EVT_ID' => $event_id,
1350
+					'page'   => 'espresso_transactions',
1351
+				),
1352
+				admin_url('admin.php')
1353
+			);
1354
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1355
+				array(
1356
+					'page'   => 'espresso_events',
1357
+					'action' => 'edit',
1358
+					'post'   => $event_id,
1359
+				),
1360
+				admin_url('admin.php')
1361
+			);
1362
+			// next and previous links
1363
+			$next_reg = $this->_registration->next(
1364
+				null,
1365
+				array(),
1366
+				'REG_ID'
1367
+			);
1368
+			$this->_template_args['next_registration'] = $next_reg
1369
+				? $this->_next_link(
1370
+					EE_Admin_Page::add_query_args_and_nonce(
1371
+						array(
1372
+							'action'  => 'view_registration',
1373
+							'_REG_ID' => $next_reg['REG_ID'],
1374
+						),
1375
+						REG_ADMIN_URL
1376
+					),
1377
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1378
+				)
1379
+				: '';
1380
+			$previous_reg = $this->_registration->previous(
1381
+				null,
1382
+				array(),
1383
+				'REG_ID'
1384
+			);
1385
+			$this->_template_args['previous_registration'] = $previous_reg
1386
+				? $this->_previous_link(
1387
+					EE_Admin_Page::add_query_args_and_nonce(
1388
+						array(
1389
+							'action'  => 'view_registration',
1390
+							'_REG_ID' => $previous_reg['REG_ID'],
1391
+						),
1392
+						REG_ADMIN_URL
1393
+					),
1394
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1395
+				)
1396
+				: '';
1397
+			// grab header
1398
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1399
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1400
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1401
+				$template_path,
1402
+				$this->_template_args,
1403
+				true
1404
+			);
1405
+		} else {
1406
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1407
+		}
1408
+		// the details template wrapper
1409
+		$this->display_admin_page_with_sidebar();
1410
+	}
1411
+
1412
+
1413
+	/**
1414
+	 * @throws EE_Error
1415
+	 * @throws InvalidArgumentException
1416
+	 * @throws InvalidDataTypeException
1417
+	 * @throws InvalidInterfaceException
1418
+	 * @throws ReflectionException
1419
+	 * @since 4.10.2.p
1420
+	 */
1421
+	protected function _registration_details_metaboxes()
1422
+	{
1423
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1424
+		$this->_set_registration_object();
1425
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1426
+		add_meta_box(
1427
+			'edit-reg-status-mbox',
1428
+			esc_html__('Registration Status', 'event_espresso'),
1429
+			array($this, 'set_reg_status_buttons_metabox'),
1430
+			$this->wp_page_slug,
1431
+			'normal',
1432
+			'high'
1433
+		);
1434
+		add_meta_box(
1435
+			'edit-reg-details-mbox',
1436
+			esc_html__('Registration Details', 'event_espresso'),
1437
+			array($this, '_reg_details_meta_box'),
1438
+			$this->wp_page_slug,
1439
+			'normal',
1440
+			'high'
1441
+		);
1442
+		if ($attendee instanceof EE_Attendee
1443
+			&& EE_Registry::instance()->CAP->current_user_can(
1444
+				'ee_read_registration',
1445
+				'edit-reg-questions-mbox',
1446
+				$this->_registration->ID()
1447
+			)
1448
+		) {
1449
+			add_meta_box(
1450
+				'edit-reg-questions-mbox',
1451
+				esc_html__('Registration Form Answers', 'event_espresso'),
1452
+				array($this, '_reg_questions_meta_box'),
1453
+				$this->wp_page_slug,
1454
+				'normal',
1455
+				'high'
1456
+			);
1457
+		}
1458
+		add_meta_box(
1459
+			'edit-reg-registrant-mbox',
1460
+			esc_html__('Contact Details', 'event_espresso'),
1461
+			array($this, '_reg_registrant_side_meta_box'),
1462
+			$this->wp_page_slug,
1463
+			'side',
1464
+			'high'
1465
+		);
1466
+		if ($this->_registration->group_size() > 1) {
1467
+			add_meta_box(
1468
+				'edit-reg-attendees-mbox',
1469
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1470
+				array($this, '_reg_attendees_meta_box'),
1471
+				$this->wp_page_slug,
1472
+				'normal',
1473
+				'high'
1474
+			);
1475
+		}
1476
+	}
1477
+
1478
+
1479
+	/**
1480
+	 * set_reg_status_buttons_metabox
1481
+	 *
1482
+	 * @access protected
1483
+	 * @return string
1484
+	 * @throws EE_Error
1485
+	 * @throws EntityNotFoundException
1486
+	 * @throws InvalidArgumentException
1487
+	 * @throws InvalidDataTypeException
1488
+	 * @throws InvalidInterfaceException
1489
+	 * @throws ReflectionException
1490
+	 */
1491
+	public function set_reg_status_buttons_metabox()
1492
+	{
1493
+		$this->_set_registration_object();
1494
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1495
+		echo $change_reg_status_form->form_open(
1496
+			self::add_query_args_and_nonce(
1497
+				array(
1498
+					'action' => 'change_reg_status',
1499
+				),
1500
+				REG_ADMIN_URL
1501
+			)
1502
+		);
1503
+		echo $change_reg_status_form->get_html();
1504
+		echo $change_reg_status_form->form_close();
1505
+	}
1506
+
1507
+
1508
+	/**
1509
+	 * @return EE_Form_Section_Proper
1510
+	 * @throws EE_Error
1511
+	 * @throws InvalidArgumentException
1512
+	 * @throws InvalidDataTypeException
1513
+	 * @throws InvalidInterfaceException
1514
+	 * @throws EntityNotFoundException
1515
+	 * @throws ReflectionException
1516
+	 */
1517
+	protected function _generate_reg_status_change_form()
1518
+	{
1519
+		$reg_status_change_form_array = array(
1520
+			'name'            => 'reg_status_change_form',
1521
+			'html_id'         => 'reg-status-change-form',
1522
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1523
+			'subsections'     => array(
1524
+				'return'             => new EE_Hidden_Input(
1525
+					array(
1526
+						'name'    => 'return',
1527
+						'default' => 'view_registration',
1528
+					)
1529
+				),
1530
+				'REG_ID'             => new EE_Hidden_Input(
1531
+					array(
1532
+						'name'    => 'REG_ID',
1533
+						'default' => $this->_registration->ID(),
1534
+					)
1535
+				),
1536
+				'current_status'     => new EE_Form_Section_HTML(
1537
+					EEH_HTML::table(
1538
+						EEH_HTML::tr(
1539
+							EEH_HTML::th(
1540
+								EEH_HTML::label(
1541
+									EEH_HTML::strong(
1542
+										esc_html__('Current Registration Status', 'event_espresso')
1543
+									)
1544
+								)
1545
+							)
1546
+							. EEH_HTML::td(
1547
+								EEH_HTML::strong(
1548
+									$this->_registration->pretty_status(),
1549
+									'',
1550
+									'status-' . $this->_registration->status_ID(),
1551
+									'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1552
+								)
1553
+							)
1554
+						)
1555
+					)
1556
+				)
1557
+			)
1558
+		);
1559
+		if (EE_Registry::instance()->CAP->current_user_can(
1560
+			'ee_edit_registration',
1561
+			'toggle_registration_status',
1562
+			$this->_registration->ID()
1563
+		)) {
1564
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1565
+				$this->_get_reg_statuses(),
1566
+				array(
1567
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1568
+					'default'         => $this->_registration->status_ID(),
1569
+				)
1570
+			);
1571
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1572
+				array(
1573
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1574
+					'default'         => false,
1575
+					'html_help_text'  => esc_html__(
1576
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1577
+						'event_espresso'
1578
+					)
1579
+				)
1580
+			);
1581
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1582
+				array(
1583
+					'html_class'      => 'button-primary',
1584
+					'html_label_text' => '&nbsp;',
1585
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1586
+				)
1587
+			);
1588
+		}
1589
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1590
+	}
1591
+
1592
+
1593
+	/**
1594
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1595
+	 *
1596
+	 * @return array
1597
+	 * @throws EE_Error
1598
+	 * @throws InvalidArgumentException
1599
+	 * @throws InvalidDataTypeException
1600
+	 * @throws InvalidInterfaceException
1601
+	 * @throws EntityNotFoundException
1602
+	 */
1603
+	protected function _get_reg_statuses()
1604
+	{
1605
+		$reg_status_array = $this->getRegistrationModel()->reg_status_array();
1606
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1607
+		// get current reg status
1608
+		$current_status = $this->_registration->status_ID();
1609
+		// is registration for free event? This will determine whether to display the pending payment option
1610
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1611
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1612
+		) {
1613
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1614
+		}
1615
+		return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1616
+	}
1617
+
1618
+
1619
+	/**
1620
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1621
+	 *
1622
+	 * @param bool $status REG status given for changing registrations to.
1623
+	 * @param bool $notify Whether to send messages notifications or not.
1624
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1625
+	 * @throws DomainException
1626
+	 * @throws EE_Error
1627
+	 * @throws EntityNotFoundException
1628
+	 * @throws InvalidArgumentException
1629
+	 * @throws InvalidDataTypeException
1630
+	 * @throws InvalidInterfaceException
1631
+	 * @throws ReflectionException
1632
+	 * @throws RuntimeException
1633
+	 */
1634
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1635
+	{
1636
+		if (isset($this->_req_data['reg_status_change_form'])) {
1637
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1638
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1639
+				: array();
1640
+		} else {
1641
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1642
+				? (array) $this->_req_data['_REG_ID']
1643
+				: array();
1644
+		}
1645
+		// sanitize $REG_IDs
1646
+		$REG_IDs = array_map('absint', $REG_IDs);
1647
+		// and remove empty entries
1648
+		$REG_IDs = array_filter($REG_IDs);
1649
+
1650
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1651
+
1652
+		/**
1653
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1654
+		 * Currently this value is used downstream by the _process_resend_registration method.
1655
+		 *
1656
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1657
+		 * @param bool                     $status           The status registrations were changed to.
1658
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1659
+		 * @param Registrations_Admin_Page $admin_page_object
1660
+		 */
1661
+		$this->_req_data['_REG_ID'] = apply_filters(
1662
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1663
+			$result['REG_ID'],
1664
+			$status,
1665
+			$result['success'],
1666
+			$this
1667
+		);
1668
+
1669
+		// notify?
1670
+		if ($notify
1671
+			&& $result['success']
1672
+			&& ! empty($this->_req_data['_REG_ID'])
1673
+			&& EE_Registry::instance()->CAP->current_user_can(
1674
+				'ee_send_message',
1675
+				'espresso_registrations_resend_registration'
1676
+			)
1677
+		) {
1678
+			$this->_process_resend_registration();
1679
+		}
1680
+		return $result;
1681
+	}
1682
+
1683
+
1684
+	/**
1685
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1686
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1687
+	 *
1688
+	 * @param array  $REG_IDs
1689
+	 * @param string $status
1690
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1691
+	 *                        slug sent with setting the registration status.
1692
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1693
+	 * @throws EE_Error
1694
+	 * @throws InvalidArgumentException
1695
+	 * @throws InvalidDataTypeException
1696
+	 * @throws InvalidInterfaceException
1697
+	 * @throws ReflectionException
1698
+	 * @throws RuntimeException
1699
+	 * @throws EntityNotFoundException
1700
+	 * @throws DomainException
1701
+	 */
1702
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1703
+	{
1704
+		$success = false;
1705
+		// typecast $REG_IDs
1706
+		$REG_IDs = (array) $REG_IDs;
1707
+		if (! empty($REG_IDs)) {
1708
+			$success = true;
1709
+			// set default status if none is passed
1710
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1711
+			$status_context = $notify
1712
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1713
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1714
+			// loop through REG_ID's and change status
1715
+			foreach ($REG_IDs as $REG_ID) {
1716
+				$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1717
+				if ($registration instanceof EE_Registration) {
1718
+					$registration->set_status(
1719
+						$status,
1720
+						false,
1721
+						new Context(
1722
+							$status_context,
1723
+							esc_html__(
1724
+								'Manually triggered status change on a Registration Admin Page route.',
1725
+								'event_espresso'
1726
+							)
1727
+						)
1728
+					);
1729
+					$result = $registration->save();
1730
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1731
+					$success = $result !== false ? $success : false;
1732
+				}
1733
+			}
1734
+		}
1735
+
1736
+		// return $success and processed registrations
1737
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * Common logic for setting up success message and redirecting to appropriate route
1743
+	 *
1744
+	 * @param string $STS_ID status id for the registration changed to
1745
+	 * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1746
+	 * @return void
1747
+	 * @throws DomainException
1748
+	 * @throws EE_Error
1749
+	 * @throws EntityNotFoundException
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws ReflectionException
1754
+	 * @throws RuntimeException
1755
+	 */
1756
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1757
+	{
1758
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1759
+			: array('success' => false);
1760
+		$success = isset($result['success']) && $result['success'];
1761
+		// setup success message
1762
+		if ($success) {
1763
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1764
+				$msg = sprintf(
1765
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1766
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1767
+				);
1768
+			} else {
1769
+				$msg = sprintf(
1770
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1771
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1772
+				);
1773
+			}
1774
+			EE_Error::add_success($msg);
1775
+		} else {
1776
+			EE_Error::add_error(
1777
+				esc_html__(
1778
+					'Something went wrong, and the status was not changed',
1779
+					'event_espresso'
1780
+				),
1781
+				__FILE__,
1782
+				__LINE__,
1783
+				__FUNCTION__
1784
+			);
1785
+		}
1786
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] === 'view_registration') {
1787
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1788
+		} else {
1789
+			$route = array('action' => 'default');
1790
+		}
1791
+		$route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1792
+		$this->_redirect_after_action($success, '', '', $route, true);
1793
+	}
1794
+
1795
+
1796
+	/**
1797
+	 * incoming reg status change from reg details page.
1798
+	 *
1799
+	 * @return void
1800
+	 * @throws EE_Error
1801
+	 * @throws EntityNotFoundException
1802
+	 * @throws InvalidArgumentException
1803
+	 * @throws InvalidDataTypeException
1804
+	 * @throws InvalidInterfaceException
1805
+	 * @throws ReflectionException
1806
+	 * @throws RuntimeException
1807
+	 * @throws DomainException
1808
+	 */
1809
+	protected function _change_reg_status()
1810
+	{
1811
+		$this->_req_data['return'] = 'view_registration';
1812
+		// set notify based on whether the send notifications toggle is set or not
1813
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1814
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1815
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1816
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1817
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1818
+			case EEM_Registration::status_id_approved:
1819
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1820
+				$this->approve_registration($notify);
1821
+				break;
1822
+			case EEM_Registration::status_id_pending_payment:
1823
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1824
+				$this->pending_registration($notify);
1825
+				break;
1826
+			case EEM_Registration::status_id_not_approved:
1827
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1828
+				$this->not_approve_registration($notify);
1829
+				break;
1830
+			case EEM_Registration::status_id_declined:
1831
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1832
+				$this->decline_registration($notify);
1833
+				break;
1834
+			case EEM_Registration::status_id_cancelled:
1835
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1836
+				$this->cancel_registration($notify);
1837
+				break;
1838
+			case EEM_Registration::status_id_wait_list:
1839
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1840
+				$this->wait_list_registration($notify);
1841
+				break;
1842
+			case EEM_Registration::status_id_incomplete:
1843
+			default:
1844
+				$result['success'] = false;
1845
+				unset($this->_req_data['return']);
1846
+				$this->_reg_status_change_return('', false);
1847
+				break;
1848
+		}
1849
+	}
1850
+
1851
+
1852
+	/**
1853
+	 * Callback for bulk action routes.
1854
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1855
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
1856
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1857
+	 * when an action is happening on just a single registration).
1858
+	 *
1859
+	 * @param      $action
1860
+	 * @param bool $notify
1861
+	 */
1862
+	protected function bulk_action_on_registrations($action, $notify = false)
1863
+	{
1864
+		do_action(
1865
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1866
+			$this,
1867
+			$action,
1868
+			$notify
1869
+		);
1870
+		$method = $action . '_registration';
1871
+		if (method_exists($this, $method)) {
1872
+			$this->$method($notify);
1873
+		}
1874
+	}
1875
+
1876
+
1877
+	/**
1878
+	 * approve_registration
1879
+	 *
1880
+	 * @access protected
1881
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1882
+	 * @return void
1883
+	 * @throws EE_Error
1884
+	 * @throws EntityNotFoundException
1885
+	 * @throws InvalidArgumentException
1886
+	 * @throws InvalidDataTypeException
1887
+	 * @throws InvalidInterfaceException
1888
+	 * @throws ReflectionException
1889
+	 * @throws RuntimeException
1890
+	 * @throws DomainException
1891
+	 */
1892
+	protected function approve_registration($notify = false)
1893
+	{
1894
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1895
+	}
1896
+
1897
+
1898
+	/**
1899
+	 *        decline_registration
1900
+	 *
1901
+	 * @access protected
1902
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1903
+	 * @return void
1904
+	 * @throws EE_Error
1905
+	 * @throws EntityNotFoundException
1906
+	 * @throws InvalidArgumentException
1907
+	 * @throws InvalidDataTypeException
1908
+	 * @throws InvalidInterfaceException
1909
+	 * @throws ReflectionException
1910
+	 * @throws RuntimeException
1911
+	 * @throws DomainException
1912
+	 */
1913
+	protected function decline_registration($notify = false)
1914
+	{
1915
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 *        cancel_registration
1921
+	 *
1922
+	 * @access protected
1923
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1924
+	 * @return void
1925
+	 * @throws EE_Error
1926
+	 * @throws EntityNotFoundException
1927
+	 * @throws InvalidArgumentException
1928
+	 * @throws InvalidDataTypeException
1929
+	 * @throws InvalidInterfaceException
1930
+	 * @throws ReflectionException
1931
+	 * @throws RuntimeException
1932
+	 * @throws DomainException
1933
+	 */
1934
+	protected function cancel_registration($notify = false)
1935
+	{
1936
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1937
+	}
1938
+
1939
+
1940
+	/**
1941
+	 *        not_approve_registration
1942
+	 *
1943
+	 * @access protected
1944
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1945
+	 * @return void
1946
+	 * @throws EE_Error
1947
+	 * @throws EntityNotFoundException
1948
+	 * @throws InvalidArgumentException
1949
+	 * @throws InvalidDataTypeException
1950
+	 * @throws InvalidInterfaceException
1951
+	 * @throws ReflectionException
1952
+	 * @throws RuntimeException
1953
+	 * @throws DomainException
1954
+	 */
1955
+	protected function not_approve_registration($notify = false)
1956
+	{
1957
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1958
+	}
1959
+
1960
+
1961
+	/**
1962
+	 *        decline_registration
1963
+	 *
1964
+	 * @access protected
1965
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1966
+	 * @return void
1967
+	 * @throws EE_Error
1968
+	 * @throws EntityNotFoundException
1969
+	 * @throws InvalidArgumentException
1970
+	 * @throws InvalidDataTypeException
1971
+	 * @throws InvalidInterfaceException
1972
+	 * @throws ReflectionException
1973
+	 * @throws RuntimeException
1974
+	 * @throws DomainException
1975
+	 */
1976
+	protected function pending_registration($notify = false)
1977
+	{
1978
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1979
+	}
1980
+
1981
+
1982
+	/**
1983
+	 * waitlist_registration
1984
+	 *
1985
+	 * @access protected
1986
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1987
+	 * @return void
1988
+	 * @throws EE_Error
1989
+	 * @throws EntityNotFoundException
1990
+	 * @throws InvalidArgumentException
1991
+	 * @throws InvalidDataTypeException
1992
+	 * @throws InvalidInterfaceException
1993
+	 * @throws ReflectionException
1994
+	 * @throws RuntimeException
1995
+	 * @throws DomainException
1996
+	 */
1997
+	protected function wait_list_registration($notify = false)
1998
+	{
1999
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2000
+	}
2001
+
2002
+
2003
+	/**
2004
+	 *        generates HTML for the Registration main meta box
2005
+	 *
2006
+	 * @access public
2007
+	 * @return void
2008
+	 * @throws DomainException
2009
+	 * @throws EE_Error
2010
+	 * @throws InvalidArgumentException
2011
+	 * @throws InvalidDataTypeException
2012
+	 * @throws InvalidInterfaceException
2013
+	 * @throws ReflectionException
2014
+	 * @throws EntityNotFoundException
2015
+	 */
2016
+	public function _reg_details_meta_box()
2017
+	{
2018
+		EEH_Autoloader::register_line_item_display_autoloaders();
2019
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2020
+		EE_Registry::instance()->load_helper('Line_Item');
2021
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2022
+			: EE_Transaction::new_instance();
2023
+		$this->_session = $transaction->session_data();
2024
+		$filters = new EE_Line_Item_Filter_Collection();
2025
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2026
+		$filters->add(new EE_Non_Zero_Line_Item_Filter());
2027
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2028
+			$filters,
2029
+			$transaction->total_line_item()
2030
+		);
2031
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2032
+		$line_item_display = new EE_Line_Item_Display(
2033
+			'reg_admin_table',
2034
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2035
+		);
2036
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2037
+			$filtered_line_item_tree,
2038
+			array('EE_Registration' => $this->_registration)
2039
+		);
2040
+		$attendee = $this->_registration->attendee();
2041
+		if (EE_Registry::instance()->CAP->current_user_can(
2042
+			'ee_read_transaction',
2043
+			'espresso_transactions_view_transaction'
2044
+		)) {
2045
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2046
+				EE_Admin_Page::add_query_args_and_nonce(
2047
+					array(
2048
+						'action' => 'view_transaction',
2049
+						'TXN_ID' => $transaction->ID(),
2050
+					),
2051
+					TXN_ADMIN_URL
2052
+				),
2053
+				esc_html__(' View Transaction', 'event_espresso'),
2054
+				'button secondary-button right',
2055
+				'dashicons dashicons-cart'
2056
+			);
2057
+		} else {
2058
+			$this->_template_args['view_transaction_button'] = '';
2059
+		}
2060
+		if ($attendee instanceof EE_Attendee
2061
+			&& EE_Registry::instance()->CAP->current_user_can(
2062
+				'ee_send_message',
2063
+				'espresso_registrations_resend_registration'
2064
+			)
2065
+		) {
2066
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2067
+				EE_Admin_Page::add_query_args_and_nonce(
2068
+					array(
2069
+						'action'      => 'resend_registration',
2070
+						'_REG_ID'     => $this->_registration->ID(),
2071
+						'redirect_to' => 'view_registration',
2072
+					),
2073
+					REG_ADMIN_URL
2074
+				),
2075
+				esc_html__(' Resend Registration', 'event_espresso'),
2076
+				'button secondary-button right',
2077
+				'dashicons dashicons-email-alt'
2078
+			);
2079
+		} else {
2080
+			$this->_template_args['resend_registration_button'] = '';
2081
+		}
2082
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2083
+		$payment = $transaction->get_first_related('Payment');
2084
+		$payment = ! $payment instanceof EE_Payment
2085
+			? EE_Payment::new_instance()
2086
+			: $payment;
2087
+		$payment_method = $payment->get_first_related('Payment_Method');
2088
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2089
+			? EE_Payment_Method::new_instance()
2090
+			: $payment_method;
2091
+		$reg_details = array(
2092
+			'payment_method'       => $payment_method->name(),
2093
+			'response_msg'         => $payment->gateway_response(),
2094
+			'registration_id'      => $this->_registration->get('REG_code'),
2095
+			'registration_session' => $this->_registration->session_ID(),
2096
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2097
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2098
+		);
2099
+		if (isset($reg_details['registration_id'])) {
2100
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2101
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2102
+				'Registration ID',
2103
+				'event_espresso'
2104
+			);
2105
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2106
+		}
2107
+		if (isset($reg_details['payment_method'])) {
2108
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2109
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2110
+				'Most Recent Payment Method',
2111
+				'event_espresso'
2112
+			);
2113
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2114
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2115
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2116
+				'Payment method response',
2117
+				'event_espresso'
2118
+			);
2119
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2120
+		}
2121
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2122
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2123
+			'Registration Session',
2124
+			'event_espresso'
2125
+		);
2126
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2127
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2128
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2129
+			'Registration placed from IP',
2130
+			'event_espresso'
2131
+		);
2132
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2133
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2134
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2135
+			'Registrant User Agent',
2136
+			'event_espresso'
2137
+		);
2138
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2139
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2140
+			array(
2141
+				'action'   => 'default',
2142
+				'event_id' => $this->_registration->event_ID(),
2143
+			),
2144
+			REG_ADMIN_URL
2145
+		);
2146
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2147
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2148
+		$template_path =
2149
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2150
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2151
+	}
2152
+
2153
+
2154
+	/**
2155
+	 * generates HTML for the Registration Questions meta box.
2156
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2157
+	 * otherwise uses new forms system
2158
+	 *
2159
+	 * @access public
2160
+	 * @return void
2161
+	 * @throws DomainException
2162
+	 * @throws EE_Error
2163
+	 * @throws InvalidArgumentException
2164
+	 * @throws InvalidDataTypeException
2165
+	 * @throws InvalidInterfaceException
2166
+	 * @throws ReflectionException
2167
+	 */
2168
+	public function _reg_questions_meta_box()
2169
+	{
2170
+		// allow someone to override this method entirely
2171
+		if (apply_filters(
2172
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2173
+			true,
2174
+			$this,
2175
+			$this->_registration
2176
+		)) {
2177
+			$form = $this->_get_reg_custom_questions_form(
2178
+				$this->_registration->ID()
2179
+			);
2180
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2181
+				? $form->get_html_and_js()
2182
+				: '';
2183
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2184
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2185
+			$template_path =
2186
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2187
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2188
+		}
2189
+	}
2190
+
2191
+
2192
+	/**
2193
+	 * form_before_question_group
2194
+	 *
2195
+	 * @deprecated    as of 4.8.32.rc.000
2196
+	 * @access        public
2197
+	 * @param        string $output
2198
+	 * @return        string
2199
+	 */
2200
+	public function form_before_question_group($output)
2201
+	{
2202
+		EE_Error::doing_it_wrong(
2203
+			__CLASS__ . '::' . __FUNCTION__,
2204
+			esc_html__(
2205
+				'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.',
2206
+				'event_espresso'
2207
+			),
2208
+			'4.8.32.rc.000'
2209
+		);
2210
+		return '
2211 2211
 	<table class="form-table ee-width-100">
2212 2212
 		<tbody>
2213 2213
 			';
2214
-    }
2215
-
2216
-
2217
-    /**
2218
-     * form_after_question_group
2219
-     *
2220
-     * @deprecated    as of 4.8.32.rc.000
2221
-     * @access        public
2222
-     * @param        string $output
2223
-     * @return        string
2224
-     */
2225
-    public function form_after_question_group($output)
2226
-    {
2227
-        EE_Error::doing_it_wrong(
2228
-            __CLASS__ . '::' . __FUNCTION__,
2229
-            esc_html__(
2230
-                '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.',
2231
-                'event_espresso'
2232
-            ),
2233
-            '4.8.32.rc.000'
2234
-        );
2235
-        return '
2214
+	}
2215
+
2216
+
2217
+	/**
2218
+	 * form_after_question_group
2219
+	 *
2220
+	 * @deprecated    as of 4.8.32.rc.000
2221
+	 * @access        public
2222
+	 * @param        string $output
2223
+	 * @return        string
2224
+	 */
2225
+	public function form_after_question_group($output)
2226
+	{
2227
+		EE_Error::doing_it_wrong(
2228
+			__CLASS__ . '::' . __FUNCTION__,
2229
+			esc_html__(
2230
+				'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.',
2231
+				'event_espresso'
2232
+			),
2233
+			'4.8.32.rc.000'
2234
+		);
2235
+		return '
2236 2236
 			<tr class="hide-if-no-js">
2237 2237
 				<th> </th>
2238 2238
 				<td class="reg-admin-edit-attendee-question-td">
2239 2239
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2240
-               . esc_attr__('click to edit question', 'event_espresso')
2241
-               . '">
2240
+			   . esc_attr__('click to edit question', 'event_espresso')
2241
+			   . '">
2242 2242
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2243
-               . esc_html__('edit the above question group', 'event_espresso')
2244
-               . '</span>
2243
+			   . esc_html__('edit the above question group', 'event_espresso')
2244
+			   . '</span>
2245 2245
 						<div class="dashicons dashicons-edit"></div>
2246 2246
 					</a>
2247 2247
 				</td>
@@ -2249,642 +2249,642 @@  discard block
 block discarded – undo
2249 2249
 		</tbody>
2250 2250
 	</table>
2251 2251
 ';
2252
-    }
2253
-
2254
-
2255
-    /**
2256
-     * form_form_field_label_wrap
2257
-     *
2258
-     * @deprecated    as of 4.8.32.rc.000
2259
-     * @access        public
2260
-     * @param        string $label
2261
-     * @return        string
2262
-     */
2263
-    public function form_form_field_label_wrap($label)
2264
-    {
2265
-        EE_Error::doing_it_wrong(
2266
-            __CLASS__ . '::' . __FUNCTION__,
2267
-            esc_html__(
2268
-                '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.',
2269
-                'event_espresso'
2270
-            ),
2271
-            '4.8.32.rc.000'
2272
-        );
2273
-        return '
2252
+	}
2253
+
2254
+
2255
+	/**
2256
+	 * form_form_field_label_wrap
2257
+	 *
2258
+	 * @deprecated    as of 4.8.32.rc.000
2259
+	 * @access        public
2260
+	 * @param        string $label
2261
+	 * @return        string
2262
+	 */
2263
+	public function form_form_field_label_wrap($label)
2264
+	{
2265
+		EE_Error::doing_it_wrong(
2266
+			__CLASS__ . '::' . __FUNCTION__,
2267
+			esc_html__(
2268
+				'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.',
2269
+				'event_espresso'
2270
+			),
2271
+			'4.8.32.rc.000'
2272
+		);
2273
+		return '
2274 2274
 			<tr>
2275 2275
 				<th>
2276 2276
 					' . $label . '
2277 2277
 				</th>';
2278
-    }
2279
-
2280
-
2281
-    /**
2282
-     * form_form_field_input__wrap
2283
-     *
2284
-     * @deprecated    as of 4.8.32.rc.000
2285
-     * @access        public
2286
-     * @param        string $input
2287
-     * @return        string
2288
-     */
2289
-    public function form_form_field_input__wrap($input)
2290
-    {
2291
-        EE_Error::doing_it_wrong(
2292
-            __CLASS__ . '::' . __FUNCTION__,
2293
-            esc_html__(
2294
-                '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.',
2295
-                'event_espresso'
2296
-            ),
2297
-            '4.8.32.rc.000'
2298
-        );
2299
-        return '
2278
+	}
2279
+
2280
+
2281
+	/**
2282
+	 * form_form_field_input__wrap
2283
+	 *
2284
+	 * @deprecated    as of 4.8.32.rc.000
2285
+	 * @access        public
2286
+	 * @param        string $input
2287
+	 * @return        string
2288
+	 */
2289
+	public function form_form_field_input__wrap($input)
2290
+	{
2291
+		EE_Error::doing_it_wrong(
2292
+			__CLASS__ . '::' . __FUNCTION__,
2293
+			esc_html__(
2294
+				'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.',
2295
+				'event_espresso'
2296
+			),
2297
+			'4.8.32.rc.000'
2298
+		);
2299
+		return '
2300 2300
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2301 2301
 					' . $input . '
2302 2302
 				</td>
2303 2303
 			</tr>';
2304
-    }
2305
-
2306
-
2307
-    /**
2308
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2309
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2310
-     * to display the page
2311
-     *
2312
-     * @access protected
2313
-     * @return void
2314
-     * @throws EE_Error
2315
-     * @throws InvalidArgumentException
2316
-     * @throws InvalidDataTypeException
2317
-     * @throws InvalidInterfaceException
2318
-     * @throws ReflectionException
2319
-     */
2320
-    protected function _update_attendee_registration_form()
2321
-    {
2322
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2323
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2324
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2325
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2326
-            if ($success) {
2327
-                $what = esc_html__('Registration Form', 'event_espresso');
2328
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2329
-                    : array('action' => 'default');
2330
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2331
-            }
2332
-        }
2333
-    }
2334
-
2335
-
2336
-    /**
2337
-     * Gets the form for saving registrations custom questions (if done
2338
-     * previously retrieves the cached form object, which may have validation errors in it)
2339
-     *
2340
-     * @param int $REG_ID
2341
-     * @return EE_Registration_Custom_Questions_Form
2342
-     * @throws EE_Error
2343
-     * @throws InvalidArgumentException
2344
-     * @throws InvalidDataTypeException
2345
-     * @throws InvalidInterfaceException
2346
-     */
2347
-    protected function _get_reg_custom_questions_form($REG_ID)
2348
-    {
2349
-        if (! $this->_reg_custom_questions_form) {
2350
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2351
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2352
-                $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2353
-            );
2354
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2355
-        }
2356
-        return $this->_reg_custom_questions_form;
2357
-    }
2358
-
2359
-
2360
-    /**
2361
-     * Saves
2362
-     *
2363
-     * @access private
2364
-     * @param bool $REG_ID
2365
-     * @return bool
2366
-     * @throws EE_Error
2367
-     * @throws InvalidArgumentException
2368
-     * @throws InvalidDataTypeException
2369
-     * @throws InvalidInterfaceException
2370
-     * @throws ReflectionException
2371
-     */
2372
-    private function _save_reg_custom_questions_form($REG_ID = false)
2373
-    {
2374
-        if (! $REG_ID) {
2375
-            EE_Error::add_error(
2376
-                esc_html__(
2377
-                    'An error occurred. No registration ID was received.',
2378
-                    'event_espresso'
2379
-                ),
2380
-                __FILE__,
2381
-                __FUNCTION__,
2382
-                __LINE__
2383
-            );
2384
-        }
2385
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2386
-        $form->receive_form_submission($this->_req_data);
2387
-        $success = false;
2388
-        if ($form->is_valid()) {
2389
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2390
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2391
-                    $where_conditions = array(
2392
-                        'QST_ID' => $question_id,
2393
-                        'REG_ID' => $REG_ID,
2394
-                    );
2395
-                    $possibly_new_values = array(
2396
-                        'ANS_value' => $input->normalized_value(),
2397
-                    );
2398
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2399
-                    if ($answer instanceof EE_Answer) {
2400
-                        $success = $answer->save($possibly_new_values);
2401
-                    } else {
2402
-                        // insert it then
2403
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2404
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2405
-                        $success = $answer->save();
2406
-                    }
2407
-                }
2408
-            }
2409
-        } else {
2410
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2411
-        }
2412
-        return $success;
2413
-    }
2414
-
2415
-
2416
-    /**
2417
-     *        generates HTML for the Registration main meta box
2418
-     *
2419
-     * @access public
2420
-     * @return void
2421
-     * @throws DomainException
2422
-     * @throws EE_Error
2423
-     * @throws InvalidArgumentException
2424
-     * @throws InvalidDataTypeException
2425
-     * @throws InvalidInterfaceException
2426
-     * @throws ReflectionException
2427
-     */
2428
-    public function _reg_attendees_meta_box()
2429
-    {
2430
-        $REG = $this->getRegistrationModel();
2431
-        // get all other registrations on this transaction, and cache
2432
-        // the attendees for them so we don't have to run another query using force_join
2433
-        $registrations = $REG->get_all(
2434
-            array(
2435
-                array(
2436
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2437
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2438
-                ),
2439
-                'force_join' => array('Attendee'),
2440
-                'default_where_conditions' => 'other_models_only',
2441
-            )
2442
-        );
2443
-        $this->_template_args['attendees'] = array();
2444
-        $this->_template_args['attendee_notice'] = '';
2445
-        if (empty($registrations)
2446
-            || (is_array($registrations)
2447
-                && ! EEH_Array::get_one_item_from_array($registrations))
2448
-        ) {
2449
-            EE_Error::add_error(
2450
-                esc_html__(
2451
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2452
-                    'event_espresso'
2453
-                ),
2454
-                __FILE__,
2455
-                __FUNCTION__,
2456
-                __LINE__
2457
-            );
2458
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2459
-        } else {
2460
-            $att_nmbr = 1;
2461
-            foreach ($registrations as $registration) {
2462
-                /* @var $registration EE_Registration */
2463
-                $attendee = $registration->attendee()
2464
-                    ? $registration->attendee()
2465
-                    : $this->getAttendeeModel()->create_default_object();
2466
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2467
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2468
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2469
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2470
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2471
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2472
-                    ', ',
2473
-                    $attendee->full_address_as_array()
2474
-                );
2475
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2476
-                    array(
2477
-                        'action' => 'edit_attendee',
2478
-                        'post'   => $attendee->ID(),
2479
-                    ),
2480
-                    REG_ADMIN_URL
2481
-                );
2482
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2483
-                    ? $registration->event_obj()->name()
2484
-                    : '';
2485
-                $att_nmbr++;
2486
-            }
2487
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2488
-        }
2489
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2490
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2491
-    }
2492
-
2493
-
2494
-    /**
2495
-     *        generates HTML for the Edit Registration side meta box
2496
-     *
2497
-     * @access public
2498
-     * @return void
2499
-     * @throws DomainException
2500
-     * @throws EE_Error
2501
-     * @throws InvalidArgumentException
2502
-     * @throws InvalidDataTypeException
2503
-     * @throws InvalidInterfaceException
2504
-     * @throws ReflectionException
2505
-     */
2506
-    public function _reg_registrant_side_meta_box()
2507
-    {
2508
-        /*@var $attendee EE_Attendee */
2509
-        $att_check = $this->_registration->attendee();
2510
-        $attendee = $att_check instanceof EE_Attendee
2511
-            ? $att_check
2512
-            : $this->getAttendeeModel()->create_default_object();
2513
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2514
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2515
-        // primary registration object (that way we know if we need to show create button or not)
2516
-        if (! $this->_registration->is_primary_registrant()) {
2517
-            $primary_registration = $this->_registration->get_primary_registration();
2518
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2519
-                : null;
2520
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2521
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2522
-                // custom attendee object so let's not worry about the primary reg.
2523
-                $primary_registration = null;
2524
-            }
2525
-        } else {
2526
-            $primary_registration = null;
2527
-        }
2528
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2529
-        $this->_template_args['fname'] = $attendee->fname();
2530
-        $this->_template_args['lname'] = $attendee->lname();
2531
-        $this->_template_args['email'] = $attendee->email();
2532
-        $this->_template_args['phone'] = $attendee->phone();
2533
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2534
-        // edit link
2535
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2536
-            array(
2537
-                'action' => 'edit_attendee',
2538
-                'post'   => $attendee->ID(),
2539
-            ),
2540
-            REG_ADMIN_URL
2541
-        );
2542
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2543
-        // create link
2544
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2545
-            ? EE_Admin_Page::add_query_args_and_nonce(
2546
-                array(
2547
-                    'action'  => 'duplicate_attendee',
2548
-                    '_REG_ID' => $this->_registration->ID(),
2549
-                ),
2550
-                REG_ADMIN_URL
2551
-            ) : '';
2552
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2553
-        $this->_template_args['att_check'] = $att_check;
2554
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2555
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2556
-    }
2557
-
2558
-
2559
-    /**
2560
-     * trash or restore registrations
2561
-     *
2562
-     * @param  boolean $trash whether to archive or restore
2563
-     * @return void
2564
-     * @throws EE_Error
2565
-     * @throws InvalidArgumentException
2566
-     * @throws InvalidDataTypeException
2567
-     * @throws InvalidInterfaceException
2568
-     * @throws RuntimeException
2569
-     * @access protected
2570
-     */
2571
-    protected function _trash_or_restore_registrations($trash = true)
2572
-    {
2573
-        // if empty _REG_ID then get out because there's nothing to do
2574
-        if (empty($this->_req_data['_REG_ID'])) {
2575
-            EE_Error::add_error(
2576
-                sprintf(
2577
-                    esc_html__(
2578
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2579
-                        'event_espresso'
2580
-                    ),
2581
-                    $trash ? 'trash' : 'restore'
2582
-                ),
2583
-                __FILE__,
2584
-                __LINE__,
2585
-                __FUNCTION__
2586
-            );
2587
-            $this->_redirect_after_action(false, '', '', array(), true);
2588
-        }
2589
-        $success = 0;
2590
-        $overwrite_msgs = false;
2591
-        // Checkboxes
2592
-        if (! is_array($this->_req_data['_REG_ID'])) {
2593
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2594
-        }
2595
-        $reg_count = count($this->_req_data['_REG_ID']);
2596
-        // cycle thru checkboxes
2597
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2598
-            /** @var EE_Registration $REG */
2599
-            $REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2600
-            $payments = $REG->registration_payments();
2601
-            if (! empty($payments)) {
2602
-                $name = $REG->attendee() instanceof EE_Attendee
2603
-                    ? $REG->attendee()->full_name()
2604
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2605
-                $overwrite_msgs = true;
2606
-                EE_Error::add_error(
2607
-                    sprintf(
2608
-                        esc_html__(
2609
-                            '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.',
2610
-                            'event_espresso'
2611
-                        ),
2612
-                        $name
2613
-                    ),
2614
-                    __FILE__,
2615
-                    __FUNCTION__,
2616
-                    __LINE__
2617
-                );
2618
-                // can't trash this registration because it has payments.
2619
-                continue;
2620
-            }
2621
-            $updated = $trash ? $REG->delete() : $REG->restore();
2622
-            if ($updated) {
2623
-                $success++;
2624
-            }
2625
-        }
2626
-        $this->_redirect_after_action(
2627
-            $success === $reg_count, // were ALL registrations affected?
2628
-            $success > 1
2629
-                ? esc_html__('Registrations', 'event_espresso')
2630
-                : esc_html__('Registration', 'event_espresso'),
2631
-            $trash
2632
-                ? esc_html__('moved to the trash', 'event_espresso')
2633
-                : esc_html__('restored', 'event_espresso'),
2634
-            $this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2635
-            $overwrite_msgs
2636
-        );
2637
-    }
2638
-
2639
-
2640
-    /**
2641
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2642
-     * registration but also.
2643
-     * 1. Removing relations to EE_Attendee
2644
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2645
-     * ALSO trashed.
2646
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2647
-     * 4. Removing relationships between all tickets and the related registrations
2648
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2649
-     * 6. Deleting permanently any related Checkins.
2650
-     *
2651
-     * @return void
2652
-     * @throws EE_Error
2653
-     * @throws InvalidArgumentException
2654
-     * @throws InvalidDataTypeException
2655
-     * @throws InvalidInterfaceException
2656
-     * @throws ReflectionException
2657
-     */
2658
-    protected function _delete_registrations()
2659
-    {
2660
-        $REG_MDL = $this->getRegistrationModel();
2661
-        $success = 1;
2662
-        // Checkboxes
2663
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2664
-            // if array has more than one element than success message should be plural
2665
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2666
-            // cycle thru checkboxes
2667
-            foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2668
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2669
-                if (! $REG instanceof EE_Registration) {
2670
-                    continue;
2671
-                }
2672
-                $deleted = $this->_delete_registration($REG);
2673
-                if (! $deleted) {
2674
-                    $success = 0;
2675
-                }
2676
-            }
2677
-        } else {
2678
-            // grab single id and delete
2679
-            $REG_ID = $this->_req_data['_REG_ID'];
2680
-            /** @var EE_Registration $REG */
2681
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2682
-            $deleted = $this->_delete_registration($REG);
2683
-            if (! $deleted) {
2684
-                $success = 0;
2685
-            }
2686
-        }
2687
-        $what = $success > 1
2688
-            ? esc_html__('Registrations', 'event_espresso')
2689
-            : esc_html__('Registration', 'event_espresso');
2690
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2691
-        $this->_redirect_after_action(
2692
-            $success,
2693
-            $what,
2694
-            $action_desc,
2695
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2696
-            true
2697
-        );
2698
-    }
2699
-
2700
-
2701
-    /**
2702
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2703
-     * models get affected.
2704
-     *
2705
-     * @param EE_Registration $REG registration to be deleted permanently
2706
-     * @return bool true = successful deletion, false = fail.
2707
-     * @throws EE_Error
2708
-     * @throws InvalidArgumentException
2709
-     * @throws InvalidDataTypeException
2710
-     * @throws InvalidInterfaceException
2711
-     * @throws ReflectionException
2712
-     */
2713
-    protected function _delete_registration(EE_Registration $REG)
2714
-    {
2715
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2716
-        // registrations on the transaction that are NOT trashed.
2717
-        $TXN = $REG->get_first_related('Transaction');
2718
-        if (! $TXN instanceof EE_Transaction) {
2719
-            EE_Error::add_error(
2720
-                sprintf(
2721
-                    esc_html__(
2722
-                        'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2723
-                        'event_espresso'
2724
-                    ),
2725
-                    $REG->id()
2726
-                ),
2727
-                __FILE__,
2728
-                __FUNCTION__,
2729
-                __LINE__
2730
-            );
2731
-            return false;
2732
-        }
2733
-        $REGS = $TXN->get_many_related('Registration');
2734
-        $all_trashed = true;
2735
-        foreach ($REGS as $registration) {
2736
-            if (! $registration->get('REG_deleted')) {
2737
-                $all_trashed = false;
2738
-            }
2739
-        }
2740
-        if (! $all_trashed) {
2741
-            EE_Error::add_error(
2742
-                esc_html__(
2743
-                    '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.',
2744
-                    'event_espresso'
2745
-                ),
2746
-                __FILE__,
2747
-                __FUNCTION__,
2748
-                __LINE__
2749
-            );
2750
-            return false;
2751
-        }
2752
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2753
-        // separately from THIS one).
2754
-        foreach ($REGS as $registration) {
2755
-            // delete related answers
2756
-            $registration->delete_related_permanently('Answer');
2757
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2758
-            $attendee = $registration->get_first_related('Attendee');
2759
-            if ($attendee instanceof EE_Attendee) {
2760
-                $registration->_remove_relation_to($attendee, 'Attendee');
2761
-            }
2762
-            // now remove relationships to tickets on this registration.
2763
-            $registration->_remove_relations('Ticket');
2764
-            // now delete permanently the checkins related to this registration.
2765
-            $registration->delete_related_permanently('Checkin');
2766
-            if ($registration->ID() === $REG->ID()) {
2767
-                continue;
2768
-            } //we don't want to delete permanently the existing registration just yet.
2769
-            // remove relation to transaction for these registrations if NOT the existing registrations
2770
-            $registration->_remove_relations('Transaction');
2771
-            // delete permanently any related messages.
2772
-            $registration->delete_related_permanently('Message');
2773
-            // now delete this registration permanently
2774
-            $registration->delete_permanently();
2775
-        }
2776
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2777
-        // (the transaction and line items should be all that's left).
2778
-        // delete the line items related to the transaction for this registration.
2779
-        $TXN->delete_related_permanently('Line_Item');
2780
-        // we need to remove all the relationships on the transaction
2781
-        $TXN->delete_related_permanently('Payment');
2782
-        $TXN->delete_related_permanently('Extra_Meta');
2783
-        $TXN->delete_related_permanently('Message');
2784
-        // now we can delete this REG permanently (and the transaction of course)
2785
-        $REG->delete_related_permanently('Transaction');
2786
-        return $REG->delete_permanently();
2787
-    }
2788
-
2789
-
2790
-    /**
2791
-     *    generates HTML for the Register New Attendee Admin page
2792
-     *
2793
-     * @access private
2794
-     * @throws DomainException
2795
-     * @throws EE_Error
2796
-     * @throws InvalidArgumentException
2797
-     * @throws InvalidDataTypeException
2798
-     * @throws InvalidInterfaceException
2799
-     * @throws ReflectionException
2800
-     */
2801
-    public function new_registration()
2802
-    {
2803
-        if (! $this->_set_reg_event()) {
2804
-            throw new EE_Error(
2805
-                esc_html__(
2806
-                    'Unable to continue with registering because there is no Event ID in the request',
2807
-                    'event_espresso'
2808
-                )
2809
-            );
2810
-        }
2811
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2812
-        // gotta start with a clean slate if we're not coming here via ajax
2813
-        if (! defined('DOING_AJAX')
2814
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2815
-        ) {
2816
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2817
-        }
2818
-        $this->_template_args['event_name'] = '';
2819
-        // event name
2820
-        if ($this->_reg_event) {
2821
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2822
-            $edit_event_url = self::add_query_args_and_nonce(
2823
-                array(
2824
-                    'action' => 'edit',
2825
-                    'post'   => $this->_reg_event->ID(),
2826
-                ),
2827
-                EVENTS_ADMIN_URL
2828
-            );
2829
-            $edit_event_lnk = '<a href="'
2830
-                              . $edit_event_url
2831
-                              . '" title="'
2832
-                              . esc_attr__('Edit ', 'event_espresso')
2833
-                              . $this->_reg_event->name()
2834
-                              . '">'
2835
-                              . esc_html__('Edit Event', 'event_espresso')
2836
-                              . '</a>';
2837
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2838
-                                                   . $edit_event_lnk
2839
-                                                   . '</span>';
2840
-        }
2841
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2842
-        if (defined('DOING_AJAX')) {
2843
-            $this->_return_json();
2844
-        }
2845
-        // grab header
2846
-        $template_path =
2847
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2848
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2849
-            $template_path,
2850
-            $this->_template_args,
2851
-            true
2852
-        );
2853
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2854
-        // the details template wrapper
2855
-        $this->display_admin_page_with_sidebar();
2856
-    }
2857
-
2858
-
2859
-    /**
2860
-     * This returns the content for a registration step
2861
-     *
2862
-     * @access protected
2863
-     * @return string html
2864
-     * @throws DomainException
2865
-     * @throws EE_Error
2866
-     * @throws InvalidArgumentException
2867
-     * @throws InvalidDataTypeException
2868
-     * @throws InvalidInterfaceException
2869
-     */
2870
-    protected function _get_registration_step_content()
2871
-    {
2872
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2873
-            $warning_msg = sprintf(
2874
-                esc_html__(
2875
-                    '%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',
2876
-                    'event_espresso'
2877
-                ),
2878
-                '<br />',
2879
-                '<h3 class="important-notice">',
2880
-                '</h3>',
2881
-                '<div class="float-right">',
2882
-                '<span id="redirect_timer" class="important-notice">30</span>',
2883
-                '</div>',
2884
-                '<b>',
2885
-                '</b>'
2886
-            );
2887
-            return '
2304
+	}
2305
+
2306
+
2307
+	/**
2308
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2309
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2310
+	 * to display the page
2311
+	 *
2312
+	 * @access protected
2313
+	 * @return void
2314
+	 * @throws EE_Error
2315
+	 * @throws InvalidArgumentException
2316
+	 * @throws InvalidDataTypeException
2317
+	 * @throws InvalidInterfaceException
2318
+	 * @throws ReflectionException
2319
+	 */
2320
+	protected function _update_attendee_registration_form()
2321
+	{
2322
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2323
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2324
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2325
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2326
+			if ($success) {
2327
+				$what = esc_html__('Registration Form', 'event_espresso');
2328
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2329
+					: array('action' => 'default');
2330
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2331
+			}
2332
+		}
2333
+	}
2334
+
2335
+
2336
+	/**
2337
+	 * Gets the form for saving registrations custom questions (if done
2338
+	 * previously retrieves the cached form object, which may have validation errors in it)
2339
+	 *
2340
+	 * @param int $REG_ID
2341
+	 * @return EE_Registration_Custom_Questions_Form
2342
+	 * @throws EE_Error
2343
+	 * @throws InvalidArgumentException
2344
+	 * @throws InvalidDataTypeException
2345
+	 * @throws InvalidInterfaceException
2346
+	 */
2347
+	protected function _get_reg_custom_questions_form($REG_ID)
2348
+	{
2349
+		if (! $this->_reg_custom_questions_form) {
2350
+			require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2351
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2352
+				$this->getRegistrationModel()->get_one_by_ID($REG_ID)
2353
+			);
2354
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2355
+		}
2356
+		return $this->_reg_custom_questions_form;
2357
+	}
2358
+
2359
+
2360
+	/**
2361
+	 * Saves
2362
+	 *
2363
+	 * @access private
2364
+	 * @param bool $REG_ID
2365
+	 * @return bool
2366
+	 * @throws EE_Error
2367
+	 * @throws InvalidArgumentException
2368
+	 * @throws InvalidDataTypeException
2369
+	 * @throws InvalidInterfaceException
2370
+	 * @throws ReflectionException
2371
+	 */
2372
+	private function _save_reg_custom_questions_form($REG_ID = false)
2373
+	{
2374
+		if (! $REG_ID) {
2375
+			EE_Error::add_error(
2376
+				esc_html__(
2377
+					'An error occurred. No registration ID was received.',
2378
+					'event_espresso'
2379
+				),
2380
+				__FILE__,
2381
+				__FUNCTION__,
2382
+				__LINE__
2383
+			);
2384
+		}
2385
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2386
+		$form->receive_form_submission($this->_req_data);
2387
+		$success = false;
2388
+		if ($form->is_valid()) {
2389
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2390
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2391
+					$where_conditions = array(
2392
+						'QST_ID' => $question_id,
2393
+						'REG_ID' => $REG_ID,
2394
+					);
2395
+					$possibly_new_values = array(
2396
+						'ANS_value' => $input->normalized_value(),
2397
+					);
2398
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2399
+					if ($answer instanceof EE_Answer) {
2400
+						$success = $answer->save($possibly_new_values);
2401
+					} else {
2402
+						// insert it then
2403
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2404
+						$answer = EE_Answer::new_instance($cols_n_vals);
2405
+						$success = $answer->save();
2406
+					}
2407
+				}
2408
+			}
2409
+		} else {
2410
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2411
+		}
2412
+		return $success;
2413
+	}
2414
+
2415
+
2416
+	/**
2417
+	 *        generates HTML for the Registration main meta box
2418
+	 *
2419
+	 * @access public
2420
+	 * @return void
2421
+	 * @throws DomainException
2422
+	 * @throws EE_Error
2423
+	 * @throws InvalidArgumentException
2424
+	 * @throws InvalidDataTypeException
2425
+	 * @throws InvalidInterfaceException
2426
+	 * @throws ReflectionException
2427
+	 */
2428
+	public function _reg_attendees_meta_box()
2429
+	{
2430
+		$REG = $this->getRegistrationModel();
2431
+		// get all other registrations on this transaction, and cache
2432
+		// the attendees for them so we don't have to run another query using force_join
2433
+		$registrations = $REG->get_all(
2434
+			array(
2435
+				array(
2436
+					'TXN_ID' => $this->_registration->transaction_ID(),
2437
+					'REG_ID' => array('!=', $this->_registration->ID()),
2438
+				),
2439
+				'force_join' => array('Attendee'),
2440
+				'default_where_conditions' => 'other_models_only',
2441
+			)
2442
+		);
2443
+		$this->_template_args['attendees'] = array();
2444
+		$this->_template_args['attendee_notice'] = '';
2445
+		if (empty($registrations)
2446
+			|| (is_array($registrations)
2447
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2448
+		) {
2449
+			EE_Error::add_error(
2450
+				esc_html__(
2451
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2452
+					'event_espresso'
2453
+				),
2454
+				__FILE__,
2455
+				__FUNCTION__,
2456
+				__LINE__
2457
+			);
2458
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2459
+		} else {
2460
+			$att_nmbr = 1;
2461
+			foreach ($registrations as $registration) {
2462
+				/* @var $registration EE_Registration */
2463
+				$attendee = $registration->attendee()
2464
+					? $registration->attendee()
2465
+					: $this->getAttendeeModel()->create_default_object();
2466
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2467
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2468
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2469
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2470
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2471
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2472
+					', ',
2473
+					$attendee->full_address_as_array()
2474
+				);
2475
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2476
+					array(
2477
+						'action' => 'edit_attendee',
2478
+						'post'   => $attendee->ID(),
2479
+					),
2480
+					REG_ADMIN_URL
2481
+				);
2482
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2483
+					? $registration->event_obj()->name()
2484
+					: '';
2485
+				$att_nmbr++;
2486
+			}
2487
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2488
+		}
2489
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2490
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2491
+	}
2492
+
2493
+
2494
+	/**
2495
+	 *        generates HTML for the Edit Registration side meta box
2496
+	 *
2497
+	 * @access public
2498
+	 * @return void
2499
+	 * @throws DomainException
2500
+	 * @throws EE_Error
2501
+	 * @throws InvalidArgumentException
2502
+	 * @throws InvalidDataTypeException
2503
+	 * @throws InvalidInterfaceException
2504
+	 * @throws ReflectionException
2505
+	 */
2506
+	public function _reg_registrant_side_meta_box()
2507
+	{
2508
+		/*@var $attendee EE_Attendee */
2509
+		$att_check = $this->_registration->attendee();
2510
+		$attendee = $att_check instanceof EE_Attendee
2511
+			? $att_check
2512
+			: $this->getAttendeeModel()->create_default_object();
2513
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2514
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2515
+		// primary registration object (that way we know if we need to show create button or not)
2516
+		if (! $this->_registration->is_primary_registrant()) {
2517
+			$primary_registration = $this->_registration->get_primary_registration();
2518
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2519
+				: null;
2520
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2521
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2522
+				// custom attendee object so let's not worry about the primary reg.
2523
+				$primary_registration = null;
2524
+			}
2525
+		} else {
2526
+			$primary_registration = null;
2527
+		}
2528
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2529
+		$this->_template_args['fname'] = $attendee->fname();
2530
+		$this->_template_args['lname'] = $attendee->lname();
2531
+		$this->_template_args['email'] = $attendee->email();
2532
+		$this->_template_args['phone'] = $attendee->phone();
2533
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2534
+		// edit link
2535
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2536
+			array(
2537
+				'action' => 'edit_attendee',
2538
+				'post'   => $attendee->ID(),
2539
+			),
2540
+			REG_ADMIN_URL
2541
+		);
2542
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2543
+		// create link
2544
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2545
+			? EE_Admin_Page::add_query_args_and_nonce(
2546
+				array(
2547
+					'action'  => 'duplicate_attendee',
2548
+					'_REG_ID' => $this->_registration->ID(),
2549
+				),
2550
+				REG_ADMIN_URL
2551
+			) : '';
2552
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2553
+		$this->_template_args['att_check'] = $att_check;
2554
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2555
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2556
+	}
2557
+
2558
+
2559
+	/**
2560
+	 * trash or restore registrations
2561
+	 *
2562
+	 * @param  boolean $trash whether to archive or restore
2563
+	 * @return void
2564
+	 * @throws EE_Error
2565
+	 * @throws InvalidArgumentException
2566
+	 * @throws InvalidDataTypeException
2567
+	 * @throws InvalidInterfaceException
2568
+	 * @throws RuntimeException
2569
+	 * @access protected
2570
+	 */
2571
+	protected function _trash_or_restore_registrations($trash = true)
2572
+	{
2573
+		// if empty _REG_ID then get out because there's nothing to do
2574
+		if (empty($this->_req_data['_REG_ID'])) {
2575
+			EE_Error::add_error(
2576
+				sprintf(
2577
+					esc_html__(
2578
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2579
+						'event_espresso'
2580
+					),
2581
+					$trash ? 'trash' : 'restore'
2582
+				),
2583
+				__FILE__,
2584
+				__LINE__,
2585
+				__FUNCTION__
2586
+			);
2587
+			$this->_redirect_after_action(false, '', '', array(), true);
2588
+		}
2589
+		$success = 0;
2590
+		$overwrite_msgs = false;
2591
+		// Checkboxes
2592
+		if (! is_array($this->_req_data['_REG_ID'])) {
2593
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2594
+		}
2595
+		$reg_count = count($this->_req_data['_REG_ID']);
2596
+		// cycle thru checkboxes
2597
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2598
+			/** @var EE_Registration $REG */
2599
+			$REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2600
+			$payments = $REG->registration_payments();
2601
+			if (! empty($payments)) {
2602
+				$name = $REG->attendee() instanceof EE_Attendee
2603
+					? $REG->attendee()->full_name()
2604
+					: esc_html__('Unknown Attendee', 'event_espresso');
2605
+				$overwrite_msgs = true;
2606
+				EE_Error::add_error(
2607
+					sprintf(
2608
+						esc_html__(
2609
+							'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.',
2610
+							'event_espresso'
2611
+						),
2612
+						$name
2613
+					),
2614
+					__FILE__,
2615
+					__FUNCTION__,
2616
+					__LINE__
2617
+				);
2618
+				// can't trash this registration because it has payments.
2619
+				continue;
2620
+			}
2621
+			$updated = $trash ? $REG->delete() : $REG->restore();
2622
+			if ($updated) {
2623
+				$success++;
2624
+			}
2625
+		}
2626
+		$this->_redirect_after_action(
2627
+			$success === $reg_count, // were ALL registrations affected?
2628
+			$success > 1
2629
+				? esc_html__('Registrations', 'event_espresso')
2630
+				: esc_html__('Registration', 'event_espresso'),
2631
+			$trash
2632
+				? esc_html__('moved to the trash', 'event_espresso')
2633
+				: esc_html__('restored', 'event_espresso'),
2634
+			$this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2635
+			$overwrite_msgs
2636
+		);
2637
+	}
2638
+
2639
+
2640
+	/**
2641
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2642
+	 * registration but also.
2643
+	 * 1. Removing relations to EE_Attendee
2644
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2645
+	 * ALSO trashed.
2646
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2647
+	 * 4. Removing relationships between all tickets and the related registrations
2648
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2649
+	 * 6. Deleting permanently any related Checkins.
2650
+	 *
2651
+	 * @return void
2652
+	 * @throws EE_Error
2653
+	 * @throws InvalidArgumentException
2654
+	 * @throws InvalidDataTypeException
2655
+	 * @throws InvalidInterfaceException
2656
+	 * @throws ReflectionException
2657
+	 */
2658
+	protected function _delete_registrations()
2659
+	{
2660
+		$REG_MDL = $this->getRegistrationModel();
2661
+		$success = 1;
2662
+		// Checkboxes
2663
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2664
+			// if array has more than one element than success message should be plural
2665
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2666
+			// cycle thru checkboxes
2667
+			foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2668
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2669
+				if (! $REG instanceof EE_Registration) {
2670
+					continue;
2671
+				}
2672
+				$deleted = $this->_delete_registration($REG);
2673
+				if (! $deleted) {
2674
+					$success = 0;
2675
+				}
2676
+			}
2677
+		} else {
2678
+			// grab single id and delete
2679
+			$REG_ID = $this->_req_data['_REG_ID'];
2680
+			/** @var EE_Registration $REG */
2681
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2682
+			$deleted = $this->_delete_registration($REG);
2683
+			if (! $deleted) {
2684
+				$success = 0;
2685
+			}
2686
+		}
2687
+		$what = $success > 1
2688
+			? esc_html__('Registrations', 'event_espresso')
2689
+			: esc_html__('Registration', 'event_espresso');
2690
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2691
+		$this->_redirect_after_action(
2692
+			$success,
2693
+			$what,
2694
+			$action_desc,
2695
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2696
+			true
2697
+		);
2698
+	}
2699
+
2700
+
2701
+	/**
2702
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2703
+	 * models get affected.
2704
+	 *
2705
+	 * @param EE_Registration $REG registration to be deleted permanently
2706
+	 * @return bool true = successful deletion, false = fail.
2707
+	 * @throws EE_Error
2708
+	 * @throws InvalidArgumentException
2709
+	 * @throws InvalidDataTypeException
2710
+	 * @throws InvalidInterfaceException
2711
+	 * @throws ReflectionException
2712
+	 */
2713
+	protected function _delete_registration(EE_Registration $REG)
2714
+	{
2715
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2716
+		// registrations on the transaction that are NOT trashed.
2717
+		$TXN = $REG->get_first_related('Transaction');
2718
+		if (! $TXN instanceof EE_Transaction) {
2719
+			EE_Error::add_error(
2720
+				sprintf(
2721
+					esc_html__(
2722
+						'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2723
+						'event_espresso'
2724
+					),
2725
+					$REG->id()
2726
+				),
2727
+				__FILE__,
2728
+				__FUNCTION__,
2729
+				__LINE__
2730
+			);
2731
+			return false;
2732
+		}
2733
+		$REGS = $TXN->get_many_related('Registration');
2734
+		$all_trashed = true;
2735
+		foreach ($REGS as $registration) {
2736
+			if (! $registration->get('REG_deleted')) {
2737
+				$all_trashed = false;
2738
+			}
2739
+		}
2740
+		if (! $all_trashed) {
2741
+			EE_Error::add_error(
2742
+				esc_html__(
2743
+					'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.',
2744
+					'event_espresso'
2745
+				),
2746
+				__FILE__,
2747
+				__FUNCTION__,
2748
+				__LINE__
2749
+			);
2750
+			return false;
2751
+		}
2752
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2753
+		// separately from THIS one).
2754
+		foreach ($REGS as $registration) {
2755
+			// delete related answers
2756
+			$registration->delete_related_permanently('Answer');
2757
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2758
+			$attendee = $registration->get_first_related('Attendee');
2759
+			if ($attendee instanceof EE_Attendee) {
2760
+				$registration->_remove_relation_to($attendee, 'Attendee');
2761
+			}
2762
+			// now remove relationships to tickets on this registration.
2763
+			$registration->_remove_relations('Ticket');
2764
+			// now delete permanently the checkins related to this registration.
2765
+			$registration->delete_related_permanently('Checkin');
2766
+			if ($registration->ID() === $REG->ID()) {
2767
+				continue;
2768
+			} //we don't want to delete permanently the existing registration just yet.
2769
+			// remove relation to transaction for these registrations if NOT the existing registrations
2770
+			$registration->_remove_relations('Transaction');
2771
+			// delete permanently any related messages.
2772
+			$registration->delete_related_permanently('Message');
2773
+			// now delete this registration permanently
2774
+			$registration->delete_permanently();
2775
+		}
2776
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2777
+		// (the transaction and line items should be all that's left).
2778
+		// delete the line items related to the transaction for this registration.
2779
+		$TXN->delete_related_permanently('Line_Item');
2780
+		// we need to remove all the relationships on the transaction
2781
+		$TXN->delete_related_permanently('Payment');
2782
+		$TXN->delete_related_permanently('Extra_Meta');
2783
+		$TXN->delete_related_permanently('Message');
2784
+		// now we can delete this REG permanently (and the transaction of course)
2785
+		$REG->delete_related_permanently('Transaction');
2786
+		return $REG->delete_permanently();
2787
+	}
2788
+
2789
+
2790
+	/**
2791
+	 *    generates HTML for the Register New Attendee Admin page
2792
+	 *
2793
+	 * @access private
2794
+	 * @throws DomainException
2795
+	 * @throws EE_Error
2796
+	 * @throws InvalidArgumentException
2797
+	 * @throws InvalidDataTypeException
2798
+	 * @throws InvalidInterfaceException
2799
+	 * @throws ReflectionException
2800
+	 */
2801
+	public function new_registration()
2802
+	{
2803
+		if (! $this->_set_reg_event()) {
2804
+			throw new EE_Error(
2805
+				esc_html__(
2806
+					'Unable to continue with registering because there is no Event ID in the request',
2807
+					'event_espresso'
2808
+				)
2809
+			);
2810
+		}
2811
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2812
+		// gotta start with a clean slate if we're not coming here via ajax
2813
+		if (! defined('DOING_AJAX')
2814
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2815
+		) {
2816
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2817
+		}
2818
+		$this->_template_args['event_name'] = '';
2819
+		// event name
2820
+		if ($this->_reg_event) {
2821
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2822
+			$edit_event_url = self::add_query_args_and_nonce(
2823
+				array(
2824
+					'action' => 'edit',
2825
+					'post'   => $this->_reg_event->ID(),
2826
+				),
2827
+				EVENTS_ADMIN_URL
2828
+			);
2829
+			$edit_event_lnk = '<a href="'
2830
+							  . $edit_event_url
2831
+							  . '" title="'
2832
+							  . esc_attr__('Edit ', 'event_espresso')
2833
+							  . $this->_reg_event->name()
2834
+							  . '">'
2835
+							  . esc_html__('Edit Event', 'event_espresso')
2836
+							  . '</a>';
2837
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2838
+												   . $edit_event_lnk
2839
+												   . '</span>';
2840
+		}
2841
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2842
+		if (defined('DOING_AJAX')) {
2843
+			$this->_return_json();
2844
+		}
2845
+		// grab header
2846
+		$template_path =
2847
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2848
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2849
+			$template_path,
2850
+			$this->_template_args,
2851
+			true
2852
+		);
2853
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2854
+		// the details template wrapper
2855
+		$this->display_admin_page_with_sidebar();
2856
+	}
2857
+
2858
+
2859
+	/**
2860
+	 * This returns the content for a registration step
2861
+	 *
2862
+	 * @access protected
2863
+	 * @return string html
2864
+	 * @throws DomainException
2865
+	 * @throws EE_Error
2866
+	 * @throws InvalidArgumentException
2867
+	 * @throws InvalidDataTypeException
2868
+	 * @throws InvalidInterfaceException
2869
+	 */
2870
+	protected function _get_registration_step_content()
2871
+	{
2872
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2873
+			$warning_msg = sprintf(
2874
+				esc_html__(
2875
+					'%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',
2876
+					'event_espresso'
2877
+				),
2878
+				'<br />',
2879
+				'<h3 class="important-notice">',
2880
+				'</h3>',
2881
+				'<div class="float-right">',
2882
+				'<span id="redirect_timer" class="important-notice">30</span>',
2883
+				'</div>',
2884
+				'<b>',
2885
+				'</b>'
2886
+			);
2887
+			return '
2888 2888
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2889 2889
 	<script >
2890 2890
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2897,868 +2897,868 @@  discard block
 block discarded – undo
2897 2897
 	        }
2898 2898
 	    }, 800 );
2899 2899
 	</script >';
2900
-        }
2901
-        $template_args = array(
2902
-            'title'                    => '',
2903
-            'content'                  => '',
2904
-            'step_button_text'         => '',
2905
-            'show_notification_toggle' => false,
2906
-        );
2907
-        // to indicate we're processing a new registration
2908
-        $hidden_fields = array(
2909
-            'processing_registration' => array(
2910
-                'type'  => 'hidden',
2911
-                'value' => 0,
2912
-            ),
2913
-            'event_id'                => array(
2914
-                'type'  => 'hidden',
2915
-                'value' => $this->_reg_event->ID(),
2916
-            ),
2917
-        );
2918
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
2919
-        $cart = EE_Registry::instance()->SSN->cart();
2920
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2921
-        switch ($step) {
2922
-            case 'ticket':
2923
-                $hidden_fields['processing_registration']['value'] = 1;
2924
-                $template_args['title'] = esc_html__(
2925
-                    'Step One: Select the Ticket for this registration',
2926
-                    'event_espresso'
2927
-                );
2928
-                $template_args['content'] =
2929
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2930
-                $template_args['content'] .= '</div>';
2931
-                $template_args['step_button_text'] = esc_html__(
2932
-                    'Add Tickets and Continue to Registrant Details',
2933
-                    'event_espresso'
2934
-                );
2935
-                $template_args['show_notification_toggle'] = false;
2936
-                break;
2937
-            case 'questions':
2938
-                $hidden_fields['processing_registration']['value'] = 2;
2939
-                $template_args['title'] = esc_html__(
2940
-                    'Step Two: Add Registrant Details for this Registration',
2941
-                    'event_espresso'
2942
-                );
2943
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2944
-                // properly by the first process_reg_step run.
2945
-                $template_args['content'] =
2946
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
2947
-                $template_args['step_button_text'] = esc_html__(
2948
-                    'Save Registration and Continue to Details',
2949
-                    'event_espresso'
2950
-                );
2951
-                $template_args['show_notification_toggle'] = true;
2952
-                break;
2953
-        }
2954
-        // we come back to the process_registration_step route.
2955
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2956
-        return EEH_Template::display_template(
2957
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2958
-            $template_args,
2959
-            true
2960
-        );
2961
-    }
2962
-
2963
-
2964
-    /**
2965
-     *        set_reg_event
2966
-     *
2967
-     * @access private
2968
-     * @return bool
2969
-     * @throws EE_Error
2970
-     * @throws InvalidArgumentException
2971
-     * @throws InvalidDataTypeException
2972
-     * @throws InvalidInterfaceException
2973
-     */
2974
-    private function _set_reg_event()
2975
-    {
2976
-        if (is_object($this->_reg_event)) {
2977
-            return true;
2978
-        }
2979
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2980
-        if (! $EVT_ID) {
2981
-            return false;
2982
-        }
2983
-        $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2984
-        return true;
2985
-    }
2986
-
2987
-
2988
-    /**
2989
-     * process_reg_step
2990
-     *
2991
-     * @access        public
2992
-     * @return string
2993
-     * @throws DomainException
2994
-     * @throws EE_Error
2995
-     * @throws InvalidArgumentException
2996
-     * @throws InvalidDataTypeException
2997
-     * @throws InvalidInterfaceException
2998
-     * @throws ReflectionException
2999
-     * @throws RuntimeException
3000
-     */
3001
-    public function process_reg_step()
3002
-    {
3003
-        EE_System::do_not_cache();
3004
-        $this->_set_reg_event();
3005
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3006
-        EE_Registry::instance()->REQ->set('uts', time());
3007
-        // what step are we on?
3008
-        $cart = EE_Registry::instance()->SSN->cart();
3009
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3010
-        // if doing ajax then we need to verify the nonce
3011
-        if (defined('DOING_AJAX')) {
3012
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3013
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3014
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3015
-        }
3016
-        switch ($step) {
3017
-            case 'ticket':
3018
-                // process ticket selection
3019
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3020
-                if ($success) {
3021
-                    EE_Error::add_success(
3022
-                        esc_html__(
3023
-                            'Tickets Selected. Now complete the registration.',
3024
-                            'event_espresso'
3025
-                        )
3026
-                    );
3027
-                } else {
3028
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3029
-                }
3030
-                if (defined('DOING_AJAX')) {
3031
-                    $this->new_registration(); // display next step
3032
-                } else {
3033
-                    $query_args = array(
3034
-                        'action'                  => 'new_registration',
3035
-                        'processing_registration' => 1,
3036
-                        'event_id'                => $this->_reg_event->ID(),
3037
-                        'uts'                     => time(),
3038
-                    );
3039
-                    $this->_redirect_after_action(
3040
-                        false,
3041
-                        '',
3042
-                        '',
3043
-                        $query_args,
3044
-                        true
3045
-                    );
3046
-                }
3047
-                break;
3048
-            case 'questions':
3049
-                if (! isset(
3050
-                    $this->_req_data['txn_reg_status_change'],
3051
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3052
-                )
3053
-                ) {
3054
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3055
-                }
3056
-                // process registration
3057
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3058
-                if ($cart instanceof EE_Cart) {
3059
-                    $grand_total = $cart->get_cart_grand_total();
3060
-                    if ($grand_total instanceof EE_Line_Item) {
3061
-                        $grand_total->save_this_and_descendants_to_txn();
3062
-                    }
3063
-                }
3064
-                if (! $transaction instanceof EE_Transaction) {
3065
-                    $query_args = array(
3066
-                        'action'                  => 'new_registration',
3067
-                        'processing_registration' => 2,
3068
-                        'event_id'                => $this->_reg_event->ID(),
3069
-                        'uts'                     => time(),
3070
-                    );
3071
-                    if (defined('DOING_AJAX')) {
3072
-                        // display registration form again because there are errors (maybe validation?)
3073
-                        $this->new_registration();
3074
-                        return;
3075
-                    }
3076
-                    $this->_redirect_after_action(
3077
-                        false,
3078
-                        '',
3079
-                        '',
3080
-                        $query_args,
3081
-                        true
3082
-                    );
3083
-                    return;
3084
-                }
3085
-                // maybe update status, and make sure to save transaction if not done already
3086
-                if (! $transaction->update_status_based_on_total_paid()) {
3087
-                    $transaction->save();
3088
-                }
3089
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3090
-                $this->_req_data = array();
3091
-                $query_args = array(
3092
-                    'action'        => 'redirect_to_txn',
3093
-                    'TXN_ID'        => $transaction->ID(),
3094
-                    'EVT_ID'        => $this->_reg_event->ID(),
3095
-                    'event_name'    => urlencode($this->_reg_event->name()),
3096
-                    'redirect_from' => 'new_registration',
3097
-                );
3098
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3099
-                break;
3100
-        }
3101
-        // what are you looking here for?  Should be nothing to do at this point.
3102
-    }
3103
-
3104
-
3105
-    /**
3106
-     * redirect_to_txn
3107
-     *
3108
-     * @access public
3109
-     * @return void
3110
-     * @throws EE_Error
3111
-     * @throws InvalidArgumentException
3112
-     * @throws InvalidDataTypeException
3113
-     * @throws InvalidInterfaceException
3114
-     * @throws ReflectionException
3115
-     */
3116
-    public function redirect_to_txn()
3117
-    {
3118
-        EE_System::do_not_cache();
3119
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3120
-        $query_args = array(
3121
-            'action' => 'view_transaction',
3122
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3123
-            'page'   => 'espresso_transactions',
3124
-        );
3125
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3126
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3127
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3128
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3129
-        }
3130
-        EE_Error::add_success(
3131
-            esc_html__(
3132
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3133
-                'event_espresso'
3134
-            )
3135
-        );
3136
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3137
-    }
3138
-
3139
-
3140
-    /**
3141
-     *        generates HTML for the Attendee Contact List
3142
-     *
3143
-     * @access protected
3144
-     * @return void
3145
-     * @throws DomainException
3146
-     * @throws EE_Error
3147
-     */
3148
-    protected function _attendee_contact_list_table()
3149
-    {
3150
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3151
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3152
-        $this->display_admin_list_table_page_with_no_sidebar();
3153
-    }
3154
-
3155
-
3156
-    /**
3157
-     *        get_attendees
3158
-     *
3159
-     * @param      $per_page
3160
-     * @param bool $count whether to return count or data.
3161
-     * @param bool $trash
3162
-     * @return array
3163
-     * @throws EE_Error
3164
-     * @throws InvalidArgumentException
3165
-     * @throws InvalidDataTypeException
3166
-     * @throws InvalidInterfaceException
3167
-     * @access public
3168
-     */
3169
-    public function get_attendees($per_page, $count = false, $trash = false)
3170
-    {
3171
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3172
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3173
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3174
-        switch ($this->_req_data['orderby']) {
3175
-            case 'ATT_ID':
3176
-                $orderby = 'ATT_ID';
3177
-                break;
3178
-            case 'ATT_fname':
3179
-                $orderby = 'ATT_fname';
3180
-                break;
3181
-            case 'ATT_email':
3182
-                $orderby = 'ATT_email';
3183
-                break;
3184
-            case 'ATT_city':
3185
-                $orderby = 'ATT_city';
3186
-                break;
3187
-            case 'STA_ID':
3188
-                $orderby = 'STA_ID';
3189
-                break;
3190
-            case 'CNT_ID':
3191
-                $orderby = 'CNT_ID';
3192
-                break;
3193
-            case 'Registration_Count':
3194
-                $orderby = 'Registration_Count';
3195
-                break;
3196
-            default:
3197
-                $orderby = 'ATT_lname';
3198
-        }
3199
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3200
-            ? $this->_req_data['order']
3201
-            : 'ASC';
3202
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3203
-            ? $this->_req_data['paged']
3204
-            : 1;
3205
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3206
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3207
-            ? $this->_req_data['perpage']
3208
-            : $per_page;
3209
-        $_where = array();
3210
-        if (! empty($this->_req_data['s'])) {
3211
-            $sstr = '%' . $this->_req_data['s'] . '%';
3212
-            $_where['OR'] = array(
3213
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3214
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3215
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3216
-                'ATT_fname'                         => array('LIKE', $sstr),
3217
-                'ATT_lname'                         => array('LIKE', $sstr),
3218
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3219
-                'ATT_email'                         => array('LIKE', $sstr),
3220
-                'ATT_address'                       => array('LIKE', $sstr),
3221
-                'ATT_address2'                      => array('LIKE', $sstr),
3222
-                'ATT_city'                          => array('LIKE', $sstr),
3223
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3224
-                'State.STA_name'                    => array('LIKE', $sstr),
3225
-                'ATT_phone'                         => array('LIKE', $sstr),
3226
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3227
-                'Registration.REG_code'             => array('LIKE', $sstr),
3228
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3229
-            );
3230
-        }
3231
-        $offset = ($current_page - 1) * $per_page;
3232
-        $limit = $count ? null : array($offset, $per_page);
3233
-        $query_args = array(
3234
-            $_where,
3235
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3236
-            'limit'         => $limit,
3237
-        );
3238
-        if (! $count) {
3239
-            $query_args['order_by'] = array($orderby => $sort);
3240
-        }
3241
-        if ($trash) {
3242
-            $query_args[0]['status'] = array('!=', 'publish');
3243
-            $all_attendees = $count
3244
-                ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3245
-                : $this->getAttendeeModel()->get_all($query_args);
3246
-        } else {
3247
-            $query_args[0]['status'] = array('IN', array('publish'));
3248
-            $all_attendees = $count
3249
-                ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3250
-                : $this->getAttendeeModel()->get_all($query_args);
3251
-        }
3252
-        return $all_attendees;
3253
-    }
3254
-
3255
-
3256
-    /**
3257
-     * This is just taking care of resending the registration confirmation
3258
-     *
3259
-     * @access protected
3260
-     * @return void
3261
-     * @throws EE_Error
3262
-     * @throws InvalidArgumentException
3263
-     * @throws InvalidDataTypeException
3264
-     * @throws InvalidInterfaceException
3265
-     * @throws ReflectionException
3266
-     */
3267
-    protected function _resend_registration()
3268
-    {
3269
-        $this->_process_resend_registration();
3270
-        $query_args = isset($this->_req_data['redirect_to'])
3271
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3272
-            : array('action' => 'default');
3273
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3274
-    }
3275
-
3276
-    /**
3277
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3278
-     * to use when selecting registrations
3279
-     *
3280
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3281
-     *                                                     the query parameters from the request
3282
-     * @return void ends the request with a redirect or download
3283
-     */
3284
-    public function _registrations_report_base($method_name_for_getting_query_params)
3285
-    {
3286
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3287
-            wp_redirect(
3288
-                EE_Admin_Page::add_query_args_and_nonce(
3289
-                    array(
3290
-                        'page'        => 'espresso_batch',
3291
-                        'batch'       => 'file',
3292
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3293
-                        'filters'     => urlencode(
3294
-                            serialize(
3295
-                                $this->$method_name_for_getting_query_params(
3296
-                                    EEH_Array::is_set(
3297
-                                        $this->_req_data,
3298
-                                        'filters',
3299
-                                        array()
3300
-                                    )
3301
-                                )
3302
-                            )
3303
-                        ),
3304
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3305
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3306
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3307
-                    )
3308
-                )
3309
-            );
3310
-        } else {
3311
-            $new_request_args = array(
3312
-                'export' => 'report',
3313
-                'action' => 'registrations_report_for_event',
3314
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3315
-            );
3316
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3317
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3318
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3319
-                $EE_Export = EE_Export::instance($this->_req_data);
3320
-                $EE_Export->export();
3321
-            }
3322
-        }
3323
-    }
3324
-
3325
-
3326
-    /**
3327
-     * Creates a registration report using only query parameters in the request
3328
-     *
3329
-     * @return void
3330
-     */
3331
-    public function _registrations_report()
3332
-    {
3333
-        $this->_registrations_report_base('_get_registration_query_parameters');
3334
-    }
3335
-
3336
-
3337
-    public function _contact_list_export()
3338
-    {
3339
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3340
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3341
-            $EE_Export = EE_Export::instance($this->_req_data);
3342
-            $EE_Export->export_attendees();
3343
-        }
3344
-    }
3345
-
3346
-
3347
-    public function _contact_list_report()
3348
-    {
3349
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3350
-            wp_redirect(
3351
-                EE_Admin_Page::add_query_args_and_nonce(
3352
-                    array(
3353
-                        'page'        => 'espresso_batch',
3354
-                        'batch'       => 'file',
3355
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3356
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3357
-                    )
3358
-                )
3359
-            );
3360
-        } else {
3361
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3362
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3363
-                $EE_Export = EE_Export::instance($this->_req_data);
3364
-                $EE_Export->report_attendees();
3365
-            }
3366
-        }
3367
-    }
3368
-
3369
-
3370
-
3371
-
3372
-
3373
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3374
-    /**
3375
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3376
-     *
3377
-     * @return void
3378
-     * @throws EE_Error
3379
-     * @throws InvalidArgumentException
3380
-     * @throws InvalidDataTypeException
3381
-     * @throws InvalidInterfaceException
3382
-     * @throws ReflectionException
3383
-     */
3384
-    protected function _duplicate_attendee()
3385
-    {
3386
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3387
-        // verify we have necessary info
3388
-        if (empty($this->_req_data['_REG_ID'])) {
3389
-            EE_Error::add_error(
3390
-                esc_html__(
3391
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3392
-                    'event_espresso'
3393
-                ),
3394
-                __FILE__,
3395
-                __LINE__,
3396
-                __FUNCTION__
3397
-            );
3398
-            $query_args = array('action' => $action);
3399
-            $this->_redirect_after_action('', '', '', $query_args, true);
3400
-        }
3401
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3402
-        $registration = $this->getRegistrationModel()->get_one_by_ID($this->_req_data['_REG_ID']);
3403
-        $attendee = $registration->attendee();
3404
-        // remove relation of existing attendee on registration
3405
-        $registration->_remove_relation_to($attendee, 'Attendee');
3406
-        // new attendee
3407
-        $new_attendee = clone $attendee;
3408
-        $new_attendee->set('ATT_ID', 0);
3409
-        $new_attendee->save();
3410
-        // add new attendee to reg
3411
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3412
-        EE_Error::add_success(
3413
-            esc_html__(
3414
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3415
-                'event_espresso'
3416
-            )
3417
-        );
3418
-        // redirect to edit page for attendee
3419
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3420
-        $this->_redirect_after_action('', '', '', $query_args, true);
3421
-    }
3422
-
3423
-
3424
-    /**
3425
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3426
-     *
3427
-     * @param int     $post_id
3428
-     * @param WP_POST $post
3429
-     * @throws DomainException
3430
-     * @throws EE_Error
3431
-     * @throws InvalidArgumentException
3432
-     * @throws InvalidDataTypeException
3433
-     * @throws InvalidInterfaceException
3434
-     * @throws LogicException
3435
-     * @throws InvalidFormSubmissionException
3436
-     * @throws ReflectionException
3437
-     */
3438
-    protected function _insert_update_cpt_item($post_id, $post)
3439
-    {
3440
-        $success = true;
3441
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3442
-            ? $this->getAttendeeModel()->get_one_by_ID($post_id)
3443
-            : null;
3444
-        // for attendee updates
3445
-        if ($attendee instanceof EE_Attendee) {
3446
-            // note we should only be UPDATING attendees at this point.
3447
-            $updated_fields = array(
3448
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3449
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3450
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3451
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3452
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3453
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3454
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3455
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3456
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3457
-            );
3458
-            foreach ($updated_fields as $field => $value) {
3459
-                $attendee->set($field, $value);
3460
-            }
3461
-
3462
-            // process contact details metabox form handler (which will also save the attendee)
3463
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3464
-            $success = $contact_details_form->process($this->_req_data);
3465
-
3466
-            $attendee_update_callbacks = apply_filters(
3467
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3468
-                array()
3469
-            );
3470
-            foreach ($attendee_update_callbacks as $a_callback) {
3471
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3472
-                    throw new EE_Error(
3473
-                        sprintf(
3474
-                            esc_html__(
3475
-                                '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.',
3476
-                                'event_espresso'
3477
-                            ),
3478
-                            $a_callback
3479
-                        )
3480
-                    );
3481
-                }
3482
-            }
3483
-        }
3484
-
3485
-        if ($success === false) {
3486
-            EE_Error::add_error(
3487
-                esc_html__(
3488
-                    'Something went wrong with updating the meta table data for the registration.',
3489
-                    'event_espresso'
3490
-                ),
3491
-                __FILE__,
3492
-                __FUNCTION__,
3493
-                __LINE__
3494
-            );
3495
-        }
3496
-    }
3497
-
3498
-
3499
-    public function trash_cpt_item($post_id)
3500
-    {
3501
-    }
3502
-
3503
-
3504
-    public function delete_cpt_item($post_id)
3505
-    {
3506
-    }
3507
-
3508
-
3509
-    public function restore_cpt_item($post_id)
3510
-    {
3511
-    }
3512
-
3513
-
3514
-    protected function _restore_cpt_item($post_id, $revision_id)
3515
-    {
3516
-    }
3517
-
3518
-
3519
-    /**
3520
-     * @throws EE_Error
3521
-     * @since 4.10.2.p
3522
-     */
3523
-    public function attendee_editor_metaboxes()
3524
-    {
3525
-        $this->verify_cpt_object();
3526
-        remove_meta_box(
3527
-            'postexcerpt',
3528
-            $this->_cpt_routes[ $this->_req_action ],
3529
-            'normal'
3530
-        );
3531
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3532
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3533
-            add_meta_box(
3534
-                'postexcerpt',
3535
-                esc_html__('Short Biography', 'event_espresso'),
3536
-                'post_excerpt_meta_box',
3537
-                $this->_cpt_routes[ $this->_req_action ],
3538
-                'normal'
3539
-            );
3540
-        }
3541
-        if (post_type_supports('espresso_attendees', 'comments')) {
3542
-            add_meta_box(
3543
-                'commentsdiv',
3544
-                esc_html__('Notes on the Contact', 'event_espresso'),
3545
-                'post_comment_meta_box',
3546
-                $this->_cpt_routes[ $this->_req_action ],
3547
-                'normal',
3548
-                'core'
3549
-            );
3550
-        }
3551
-        add_meta_box(
3552
-            'attendee_contact_info',
3553
-            esc_html__('Contact Info', 'event_espresso'),
3554
-            array($this, 'attendee_contact_info'),
3555
-            $this->_cpt_routes[ $this->_req_action ],
3556
-            'side',
3557
-            'core'
3558
-        );
3559
-        add_meta_box(
3560
-            'attendee_details_address',
3561
-            esc_html__('Address Details', 'event_espresso'),
3562
-            array($this, 'attendee_address_details'),
3563
-            $this->_cpt_routes[ $this->_req_action ],
3564
-            'normal',
3565
-            'core'
3566
-        );
3567
-        add_meta_box(
3568
-            'attendee_registrations',
3569
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3570
-            array($this, 'attendee_registrations_meta_box'),
3571
-            $this->_cpt_routes[ $this->_req_action ],
3572
-            'normal',
3573
-            'high'
3574
-        );
3575
-    }
3576
-
3577
-
3578
-    /**
3579
-     * Metabox for attendee contact info
3580
-     *
3581
-     * @param  WP_Post $post wp post object
3582
-     * @return string attendee contact info ( and form )
3583
-     * @throws EE_Error
3584
-     * @throws InvalidArgumentException
3585
-     * @throws InvalidDataTypeException
3586
-     * @throws InvalidInterfaceException
3587
-     * @throws LogicException
3588
-     * @throws DomainException
3589
-     */
3590
-    public function attendee_contact_info($post)
3591
-    {
3592
-        // get attendee object ( should already have it )
3593
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3594
-        $form->enqueueStylesAndScripts();
3595
-        echo $form->display();
3596
-    }
3597
-
3598
-
3599
-    /**
3600
-     * Return form handler for the contact details metabox
3601
-     *
3602
-     * @param EE_Attendee $attendee
3603
-     * @return AttendeeContactDetailsMetaboxFormHandler
3604
-     * @throws DomainException
3605
-     * @throws InvalidArgumentException
3606
-     * @throws InvalidDataTypeException
3607
-     * @throws InvalidInterfaceException
3608
-     */
3609
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3610
-    {
3611
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3612
-    }
3613
-
3614
-
3615
-    /**
3616
-     * Metabox for attendee details
3617
-     *
3618
-     * @param  WP_Post $post wp post object
3619
-     * @throws DomainException
3620
-     */
3621
-    public function attendee_address_details($post)
3622
-    {
3623
-        // get attendee object (should already have it)
3624
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3625
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3626
-            new EE_Question_Form_Input(
3627
-                EE_Question::new_instance(
3628
-                    array(
3629
-                        'QST_ID'           => 0,
3630
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3631
-                        'QST_system'       => 'admin-state',
3632
-                    )
3633
-                ),
3634
-                EE_Answer::new_instance(
3635
-                    array(
3636
-                        'ANS_ID'    => 0,
3637
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3638
-                    )
3639
-                ),
3640
-                array(
3641
-                    'input_id'       => 'STA_ID',
3642
-                    'input_name'     => 'STA_ID',
3643
-                    'input_prefix'   => '',
3644
-                    'append_qstn_id' => false,
3645
-                )
3646
-            )
3647
-        );
3648
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3649
-            new EE_Question_Form_Input(
3650
-                EE_Question::new_instance(
3651
-                    array(
3652
-                        'QST_ID'           => 0,
3653
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3654
-                        'QST_system'       => 'admin-country',
3655
-                    )
3656
-                ),
3657
-                EE_Answer::new_instance(
3658
-                    array(
3659
-                        'ANS_ID'    => 0,
3660
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3661
-                    )
3662
-                ),
3663
-                array(
3664
-                    'input_id'       => 'CNT_ISO',
3665
-                    'input_name'     => 'CNT_ISO',
3666
-                    'input_prefix'   => '',
3667
-                    'append_qstn_id' => false,
3668
-                )
3669
-            )
3670
-        );
3671
-        $template =
3672
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3673
-        EEH_Template::display_template($template, $this->_template_args);
3674
-    }
3675
-
3676
-
3677
-    /**
3678
-     *        _attendee_details
3679
-     *
3680
-     * @access protected
3681
-     * @param $post
3682
-     * @return void
3683
-     * @throws DomainException
3684
-     * @throws EE_Error
3685
-     * @throws InvalidArgumentException
3686
-     * @throws InvalidDataTypeException
3687
-     * @throws InvalidInterfaceException
3688
-     * @throws ReflectionException
3689
-     */
3690
-    public function attendee_registrations_meta_box($post)
3691
-    {
3692
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3693
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3694
-        $template =
3695
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3696
-        EEH_Template::display_template($template, $this->_template_args);
3697
-    }
3698
-
3699
-
3700
-    /**
3701
-     * add in the form fields for the attendee edit
3702
-     *
3703
-     * @param  WP_Post $post wp post object
3704
-     * @return string html for new form.
3705
-     * @throws DomainException
3706
-     */
3707
-    public function after_title_form_fields($post)
3708
-    {
3709
-        if ($post->post_type === 'espresso_attendees') {
3710
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3711
-            $template_args['attendee'] = $this->_cpt_model_obj;
3712
-            EEH_Template::display_template($template, $template_args);
3713
-        }
3714
-    }
3715
-
3716
-
3717
-    /**
3718
-     *        _trash_or_restore_attendee
3719
-     *
3720
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3721
-     * @return void
3722
-     * @throws EE_Error
3723
-     * @throws InvalidArgumentException
3724
-     * @throws InvalidDataTypeException
3725
-     * @throws InvalidInterfaceException
3726
-     * @throws ReflectionException
3727
-     * @access protected
3728
-     */
3729
-    protected function _trash_or_restore_attendees($trash = true)
3730
-    {
3731
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3732
-        $success = 1;
3733
-        // Checkboxes
3734
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3735
-            // if array has more than one element than success message should be plural
3736
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3737
-            // cycle thru checkboxes
3738
-            foreach ($this->_req_data['checkbox'] as $ATT_ID) {
3739
-                $updated = $trash ? $this->getAttendeeModel()->update_by_ID(array('status' => 'trash'), $ATT_ID)
3740
-                    : $this->getAttendeeModel()->update_by_ID(array('status' => 'publish'), $ATT_ID);
3741
-                if (! $updated) {
3742
-                    $success = 0;
3743
-                }
3744
-            }
3745
-        } else {
3746
-            // grab single id and delete
3747
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3748
-            // get attendee
3749
-            $att = $this->getAttendeeModel()->get_one_by_ID($ATT_ID);
3750
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3751
-            $updated = $att->save() && $updated;
3752
-            if (! $updated) {
3753
-                $success = 0;
3754
-            }
3755
-        }
3756
-        $what = $success > 1
3757
-            ? esc_html__('Contacts', 'event_espresso')
3758
-            : esc_html__('Contact', 'event_espresso');
3759
-        $action_desc = $trash
3760
-            ? esc_html__('moved to the trash', 'event_espresso')
3761
-            : esc_html__('restored', 'event_espresso');
3762
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3763
-    }
2900
+		}
2901
+		$template_args = array(
2902
+			'title'                    => '',
2903
+			'content'                  => '',
2904
+			'step_button_text'         => '',
2905
+			'show_notification_toggle' => false,
2906
+		);
2907
+		// to indicate we're processing a new registration
2908
+		$hidden_fields = array(
2909
+			'processing_registration' => array(
2910
+				'type'  => 'hidden',
2911
+				'value' => 0,
2912
+			),
2913
+			'event_id'                => array(
2914
+				'type'  => 'hidden',
2915
+				'value' => $this->_reg_event->ID(),
2916
+			),
2917
+		);
2918
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
2919
+		$cart = EE_Registry::instance()->SSN->cart();
2920
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2921
+		switch ($step) {
2922
+			case 'ticket':
2923
+				$hidden_fields['processing_registration']['value'] = 1;
2924
+				$template_args['title'] = esc_html__(
2925
+					'Step One: Select the Ticket for this registration',
2926
+					'event_espresso'
2927
+				);
2928
+				$template_args['content'] =
2929
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2930
+				$template_args['content'] .= '</div>';
2931
+				$template_args['step_button_text'] = esc_html__(
2932
+					'Add Tickets and Continue to Registrant Details',
2933
+					'event_espresso'
2934
+				);
2935
+				$template_args['show_notification_toggle'] = false;
2936
+				break;
2937
+			case 'questions':
2938
+				$hidden_fields['processing_registration']['value'] = 2;
2939
+				$template_args['title'] = esc_html__(
2940
+					'Step Two: Add Registrant Details for this Registration',
2941
+					'event_espresso'
2942
+				);
2943
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2944
+				// properly by the first process_reg_step run.
2945
+				$template_args['content'] =
2946
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
2947
+				$template_args['step_button_text'] = esc_html__(
2948
+					'Save Registration and Continue to Details',
2949
+					'event_espresso'
2950
+				);
2951
+				$template_args['show_notification_toggle'] = true;
2952
+				break;
2953
+		}
2954
+		// we come back to the process_registration_step route.
2955
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2956
+		return EEH_Template::display_template(
2957
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2958
+			$template_args,
2959
+			true
2960
+		);
2961
+	}
2962
+
2963
+
2964
+	/**
2965
+	 *        set_reg_event
2966
+	 *
2967
+	 * @access private
2968
+	 * @return bool
2969
+	 * @throws EE_Error
2970
+	 * @throws InvalidArgumentException
2971
+	 * @throws InvalidDataTypeException
2972
+	 * @throws InvalidInterfaceException
2973
+	 */
2974
+	private function _set_reg_event()
2975
+	{
2976
+		if (is_object($this->_reg_event)) {
2977
+			return true;
2978
+		}
2979
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2980
+		if (! $EVT_ID) {
2981
+			return false;
2982
+		}
2983
+		$this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2984
+		return true;
2985
+	}
2986
+
2987
+
2988
+	/**
2989
+	 * process_reg_step
2990
+	 *
2991
+	 * @access        public
2992
+	 * @return string
2993
+	 * @throws DomainException
2994
+	 * @throws EE_Error
2995
+	 * @throws InvalidArgumentException
2996
+	 * @throws InvalidDataTypeException
2997
+	 * @throws InvalidInterfaceException
2998
+	 * @throws ReflectionException
2999
+	 * @throws RuntimeException
3000
+	 */
3001
+	public function process_reg_step()
3002
+	{
3003
+		EE_System::do_not_cache();
3004
+		$this->_set_reg_event();
3005
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3006
+		EE_Registry::instance()->REQ->set('uts', time());
3007
+		// what step are we on?
3008
+		$cart = EE_Registry::instance()->SSN->cart();
3009
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3010
+		// if doing ajax then we need to verify the nonce
3011
+		if (defined('DOING_AJAX')) {
3012
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3013
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3014
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3015
+		}
3016
+		switch ($step) {
3017
+			case 'ticket':
3018
+				// process ticket selection
3019
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3020
+				if ($success) {
3021
+					EE_Error::add_success(
3022
+						esc_html__(
3023
+							'Tickets Selected. Now complete the registration.',
3024
+							'event_espresso'
3025
+						)
3026
+					);
3027
+				} else {
3028
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3029
+				}
3030
+				if (defined('DOING_AJAX')) {
3031
+					$this->new_registration(); // display next step
3032
+				} else {
3033
+					$query_args = array(
3034
+						'action'                  => 'new_registration',
3035
+						'processing_registration' => 1,
3036
+						'event_id'                => $this->_reg_event->ID(),
3037
+						'uts'                     => time(),
3038
+					);
3039
+					$this->_redirect_after_action(
3040
+						false,
3041
+						'',
3042
+						'',
3043
+						$query_args,
3044
+						true
3045
+					);
3046
+				}
3047
+				break;
3048
+			case 'questions':
3049
+				if (! isset(
3050
+					$this->_req_data['txn_reg_status_change'],
3051
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3052
+				)
3053
+				) {
3054
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3055
+				}
3056
+				// process registration
3057
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3058
+				if ($cart instanceof EE_Cart) {
3059
+					$grand_total = $cart->get_cart_grand_total();
3060
+					if ($grand_total instanceof EE_Line_Item) {
3061
+						$grand_total->save_this_and_descendants_to_txn();
3062
+					}
3063
+				}
3064
+				if (! $transaction instanceof EE_Transaction) {
3065
+					$query_args = array(
3066
+						'action'                  => 'new_registration',
3067
+						'processing_registration' => 2,
3068
+						'event_id'                => $this->_reg_event->ID(),
3069
+						'uts'                     => time(),
3070
+					);
3071
+					if (defined('DOING_AJAX')) {
3072
+						// display registration form again because there are errors (maybe validation?)
3073
+						$this->new_registration();
3074
+						return;
3075
+					}
3076
+					$this->_redirect_after_action(
3077
+						false,
3078
+						'',
3079
+						'',
3080
+						$query_args,
3081
+						true
3082
+					);
3083
+					return;
3084
+				}
3085
+				// maybe update status, and make sure to save transaction if not done already
3086
+				if (! $transaction->update_status_based_on_total_paid()) {
3087
+					$transaction->save();
3088
+				}
3089
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3090
+				$this->_req_data = array();
3091
+				$query_args = array(
3092
+					'action'        => 'redirect_to_txn',
3093
+					'TXN_ID'        => $transaction->ID(),
3094
+					'EVT_ID'        => $this->_reg_event->ID(),
3095
+					'event_name'    => urlencode($this->_reg_event->name()),
3096
+					'redirect_from' => 'new_registration',
3097
+				);
3098
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3099
+				break;
3100
+		}
3101
+		// what are you looking here for?  Should be nothing to do at this point.
3102
+	}
3103
+
3104
+
3105
+	/**
3106
+	 * redirect_to_txn
3107
+	 *
3108
+	 * @access public
3109
+	 * @return void
3110
+	 * @throws EE_Error
3111
+	 * @throws InvalidArgumentException
3112
+	 * @throws InvalidDataTypeException
3113
+	 * @throws InvalidInterfaceException
3114
+	 * @throws ReflectionException
3115
+	 */
3116
+	public function redirect_to_txn()
3117
+	{
3118
+		EE_System::do_not_cache();
3119
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3120
+		$query_args = array(
3121
+			'action' => 'view_transaction',
3122
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3123
+			'page'   => 'espresso_transactions',
3124
+		);
3125
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3126
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3127
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3128
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3129
+		}
3130
+		EE_Error::add_success(
3131
+			esc_html__(
3132
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3133
+				'event_espresso'
3134
+			)
3135
+		);
3136
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3137
+	}
3138
+
3139
+
3140
+	/**
3141
+	 *        generates HTML for the Attendee Contact List
3142
+	 *
3143
+	 * @access protected
3144
+	 * @return void
3145
+	 * @throws DomainException
3146
+	 * @throws EE_Error
3147
+	 */
3148
+	protected function _attendee_contact_list_table()
3149
+	{
3150
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3151
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3152
+		$this->display_admin_list_table_page_with_no_sidebar();
3153
+	}
3154
+
3155
+
3156
+	/**
3157
+	 *        get_attendees
3158
+	 *
3159
+	 * @param      $per_page
3160
+	 * @param bool $count whether to return count or data.
3161
+	 * @param bool $trash
3162
+	 * @return array
3163
+	 * @throws EE_Error
3164
+	 * @throws InvalidArgumentException
3165
+	 * @throws InvalidDataTypeException
3166
+	 * @throws InvalidInterfaceException
3167
+	 * @access public
3168
+	 */
3169
+	public function get_attendees($per_page, $count = false, $trash = false)
3170
+	{
3171
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3172
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3173
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3174
+		switch ($this->_req_data['orderby']) {
3175
+			case 'ATT_ID':
3176
+				$orderby = 'ATT_ID';
3177
+				break;
3178
+			case 'ATT_fname':
3179
+				$orderby = 'ATT_fname';
3180
+				break;
3181
+			case 'ATT_email':
3182
+				$orderby = 'ATT_email';
3183
+				break;
3184
+			case 'ATT_city':
3185
+				$orderby = 'ATT_city';
3186
+				break;
3187
+			case 'STA_ID':
3188
+				$orderby = 'STA_ID';
3189
+				break;
3190
+			case 'CNT_ID':
3191
+				$orderby = 'CNT_ID';
3192
+				break;
3193
+			case 'Registration_Count':
3194
+				$orderby = 'Registration_Count';
3195
+				break;
3196
+			default:
3197
+				$orderby = 'ATT_lname';
3198
+		}
3199
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3200
+			? $this->_req_data['order']
3201
+			: 'ASC';
3202
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3203
+			? $this->_req_data['paged']
3204
+			: 1;
3205
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3206
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3207
+			? $this->_req_data['perpage']
3208
+			: $per_page;
3209
+		$_where = array();
3210
+		if (! empty($this->_req_data['s'])) {
3211
+			$sstr = '%' . $this->_req_data['s'] . '%';
3212
+			$_where['OR'] = array(
3213
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3214
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3215
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3216
+				'ATT_fname'                         => array('LIKE', $sstr),
3217
+				'ATT_lname'                         => array('LIKE', $sstr),
3218
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3219
+				'ATT_email'                         => array('LIKE', $sstr),
3220
+				'ATT_address'                       => array('LIKE', $sstr),
3221
+				'ATT_address2'                      => array('LIKE', $sstr),
3222
+				'ATT_city'                          => array('LIKE', $sstr),
3223
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3224
+				'State.STA_name'                    => array('LIKE', $sstr),
3225
+				'ATT_phone'                         => array('LIKE', $sstr),
3226
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3227
+				'Registration.REG_code'             => array('LIKE', $sstr),
3228
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3229
+			);
3230
+		}
3231
+		$offset = ($current_page - 1) * $per_page;
3232
+		$limit = $count ? null : array($offset, $per_page);
3233
+		$query_args = array(
3234
+			$_where,
3235
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3236
+			'limit'         => $limit,
3237
+		);
3238
+		if (! $count) {
3239
+			$query_args['order_by'] = array($orderby => $sort);
3240
+		}
3241
+		if ($trash) {
3242
+			$query_args[0]['status'] = array('!=', 'publish');
3243
+			$all_attendees = $count
3244
+				? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3245
+				: $this->getAttendeeModel()->get_all($query_args);
3246
+		} else {
3247
+			$query_args[0]['status'] = array('IN', array('publish'));
3248
+			$all_attendees = $count
3249
+				? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3250
+				: $this->getAttendeeModel()->get_all($query_args);
3251
+		}
3252
+		return $all_attendees;
3253
+	}
3254
+
3255
+
3256
+	/**
3257
+	 * This is just taking care of resending the registration confirmation
3258
+	 *
3259
+	 * @access protected
3260
+	 * @return void
3261
+	 * @throws EE_Error
3262
+	 * @throws InvalidArgumentException
3263
+	 * @throws InvalidDataTypeException
3264
+	 * @throws InvalidInterfaceException
3265
+	 * @throws ReflectionException
3266
+	 */
3267
+	protected function _resend_registration()
3268
+	{
3269
+		$this->_process_resend_registration();
3270
+		$query_args = isset($this->_req_data['redirect_to'])
3271
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3272
+			: array('action' => 'default');
3273
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3274
+	}
3275
+
3276
+	/**
3277
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3278
+	 * to use when selecting registrations
3279
+	 *
3280
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3281
+	 *                                                     the query parameters from the request
3282
+	 * @return void ends the request with a redirect or download
3283
+	 */
3284
+	public function _registrations_report_base($method_name_for_getting_query_params)
3285
+	{
3286
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3287
+			wp_redirect(
3288
+				EE_Admin_Page::add_query_args_and_nonce(
3289
+					array(
3290
+						'page'        => 'espresso_batch',
3291
+						'batch'       => 'file',
3292
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3293
+						'filters'     => urlencode(
3294
+							serialize(
3295
+								$this->$method_name_for_getting_query_params(
3296
+									EEH_Array::is_set(
3297
+										$this->_req_data,
3298
+										'filters',
3299
+										array()
3300
+									)
3301
+								)
3302
+							)
3303
+						),
3304
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3305
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3306
+						'return_url'  => urlencode($this->_req_data['return_url']),
3307
+					)
3308
+				)
3309
+			);
3310
+		} else {
3311
+			$new_request_args = array(
3312
+				'export' => 'report',
3313
+				'action' => 'registrations_report_for_event',
3314
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3315
+			);
3316
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3317
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3318
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3319
+				$EE_Export = EE_Export::instance($this->_req_data);
3320
+				$EE_Export->export();
3321
+			}
3322
+		}
3323
+	}
3324
+
3325
+
3326
+	/**
3327
+	 * Creates a registration report using only query parameters in the request
3328
+	 *
3329
+	 * @return void
3330
+	 */
3331
+	public function _registrations_report()
3332
+	{
3333
+		$this->_registrations_report_base('_get_registration_query_parameters');
3334
+	}
3335
+
3336
+
3337
+	public function _contact_list_export()
3338
+	{
3339
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3340
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3341
+			$EE_Export = EE_Export::instance($this->_req_data);
3342
+			$EE_Export->export_attendees();
3343
+		}
3344
+	}
3345
+
3346
+
3347
+	public function _contact_list_report()
3348
+	{
3349
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3350
+			wp_redirect(
3351
+				EE_Admin_Page::add_query_args_and_nonce(
3352
+					array(
3353
+						'page'        => 'espresso_batch',
3354
+						'batch'       => 'file',
3355
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3356
+						'return_url'  => urlencode($this->_req_data['return_url']),
3357
+					)
3358
+				)
3359
+			);
3360
+		} else {
3361
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3362
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3363
+				$EE_Export = EE_Export::instance($this->_req_data);
3364
+				$EE_Export->report_attendees();
3365
+			}
3366
+		}
3367
+	}
3368
+
3369
+
3370
+
3371
+
3372
+
3373
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3374
+	/**
3375
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3376
+	 *
3377
+	 * @return void
3378
+	 * @throws EE_Error
3379
+	 * @throws InvalidArgumentException
3380
+	 * @throws InvalidDataTypeException
3381
+	 * @throws InvalidInterfaceException
3382
+	 * @throws ReflectionException
3383
+	 */
3384
+	protected function _duplicate_attendee()
3385
+	{
3386
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3387
+		// verify we have necessary info
3388
+		if (empty($this->_req_data['_REG_ID'])) {
3389
+			EE_Error::add_error(
3390
+				esc_html__(
3391
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3392
+					'event_espresso'
3393
+				),
3394
+				__FILE__,
3395
+				__LINE__,
3396
+				__FUNCTION__
3397
+			);
3398
+			$query_args = array('action' => $action);
3399
+			$this->_redirect_after_action('', '', '', $query_args, true);
3400
+		}
3401
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3402
+		$registration = $this->getRegistrationModel()->get_one_by_ID($this->_req_data['_REG_ID']);
3403
+		$attendee = $registration->attendee();
3404
+		// remove relation of existing attendee on registration
3405
+		$registration->_remove_relation_to($attendee, 'Attendee');
3406
+		// new attendee
3407
+		$new_attendee = clone $attendee;
3408
+		$new_attendee->set('ATT_ID', 0);
3409
+		$new_attendee->save();
3410
+		// add new attendee to reg
3411
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3412
+		EE_Error::add_success(
3413
+			esc_html__(
3414
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3415
+				'event_espresso'
3416
+			)
3417
+		);
3418
+		// redirect to edit page for attendee
3419
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3420
+		$this->_redirect_after_action('', '', '', $query_args, true);
3421
+	}
3422
+
3423
+
3424
+	/**
3425
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3426
+	 *
3427
+	 * @param int     $post_id
3428
+	 * @param WP_POST $post
3429
+	 * @throws DomainException
3430
+	 * @throws EE_Error
3431
+	 * @throws InvalidArgumentException
3432
+	 * @throws InvalidDataTypeException
3433
+	 * @throws InvalidInterfaceException
3434
+	 * @throws LogicException
3435
+	 * @throws InvalidFormSubmissionException
3436
+	 * @throws ReflectionException
3437
+	 */
3438
+	protected function _insert_update_cpt_item($post_id, $post)
3439
+	{
3440
+		$success = true;
3441
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3442
+			? $this->getAttendeeModel()->get_one_by_ID($post_id)
3443
+			: null;
3444
+		// for attendee updates
3445
+		if ($attendee instanceof EE_Attendee) {
3446
+			// note we should only be UPDATING attendees at this point.
3447
+			$updated_fields = array(
3448
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3449
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3450
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3451
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3452
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3453
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3454
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3455
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3456
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3457
+			);
3458
+			foreach ($updated_fields as $field => $value) {
3459
+				$attendee->set($field, $value);
3460
+			}
3461
+
3462
+			// process contact details metabox form handler (which will also save the attendee)
3463
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3464
+			$success = $contact_details_form->process($this->_req_data);
3465
+
3466
+			$attendee_update_callbacks = apply_filters(
3467
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3468
+				array()
3469
+			);
3470
+			foreach ($attendee_update_callbacks as $a_callback) {
3471
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3472
+					throw new EE_Error(
3473
+						sprintf(
3474
+							esc_html__(
3475
+								'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.',
3476
+								'event_espresso'
3477
+							),
3478
+							$a_callback
3479
+						)
3480
+					);
3481
+				}
3482
+			}
3483
+		}
3484
+
3485
+		if ($success === false) {
3486
+			EE_Error::add_error(
3487
+				esc_html__(
3488
+					'Something went wrong with updating the meta table data for the registration.',
3489
+					'event_espresso'
3490
+				),
3491
+				__FILE__,
3492
+				__FUNCTION__,
3493
+				__LINE__
3494
+			);
3495
+		}
3496
+	}
3497
+
3498
+
3499
+	public function trash_cpt_item($post_id)
3500
+	{
3501
+	}
3502
+
3503
+
3504
+	public function delete_cpt_item($post_id)
3505
+	{
3506
+	}
3507
+
3508
+
3509
+	public function restore_cpt_item($post_id)
3510
+	{
3511
+	}
3512
+
3513
+
3514
+	protected function _restore_cpt_item($post_id, $revision_id)
3515
+	{
3516
+	}
3517
+
3518
+
3519
+	/**
3520
+	 * @throws EE_Error
3521
+	 * @since 4.10.2.p
3522
+	 */
3523
+	public function attendee_editor_metaboxes()
3524
+	{
3525
+		$this->verify_cpt_object();
3526
+		remove_meta_box(
3527
+			'postexcerpt',
3528
+			$this->_cpt_routes[ $this->_req_action ],
3529
+			'normal'
3530
+		);
3531
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3532
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3533
+			add_meta_box(
3534
+				'postexcerpt',
3535
+				esc_html__('Short Biography', 'event_espresso'),
3536
+				'post_excerpt_meta_box',
3537
+				$this->_cpt_routes[ $this->_req_action ],
3538
+				'normal'
3539
+			);
3540
+		}
3541
+		if (post_type_supports('espresso_attendees', 'comments')) {
3542
+			add_meta_box(
3543
+				'commentsdiv',
3544
+				esc_html__('Notes on the Contact', 'event_espresso'),
3545
+				'post_comment_meta_box',
3546
+				$this->_cpt_routes[ $this->_req_action ],
3547
+				'normal',
3548
+				'core'
3549
+			);
3550
+		}
3551
+		add_meta_box(
3552
+			'attendee_contact_info',
3553
+			esc_html__('Contact Info', 'event_espresso'),
3554
+			array($this, 'attendee_contact_info'),
3555
+			$this->_cpt_routes[ $this->_req_action ],
3556
+			'side',
3557
+			'core'
3558
+		);
3559
+		add_meta_box(
3560
+			'attendee_details_address',
3561
+			esc_html__('Address Details', 'event_espresso'),
3562
+			array($this, 'attendee_address_details'),
3563
+			$this->_cpt_routes[ $this->_req_action ],
3564
+			'normal',
3565
+			'core'
3566
+		);
3567
+		add_meta_box(
3568
+			'attendee_registrations',
3569
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3570
+			array($this, 'attendee_registrations_meta_box'),
3571
+			$this->_cpt_routes[ $this->_req_action ],
3572
+			'normal',
3573
+			'high'
3574
+		);
3575
+	}
3576
+
3577
+
3578
+	/**
3579
+	 * Metabox for attendee contact info
3580
+	 *
3581
+	 * @param  WP_Post $post wp post object
3582
+	 * @return string attendee contact info ( and form )
3583
+	 * @throws EE_Error
3584
+	 * @throws InvalidArgumentException
3585
+	 * @throws InvalidDataTypeException
3586
+	 * @throws InvalidInterfaceException
3587
+	 * @throws LogicException
3588
+	 * @throws DomainException
3589
+	 */
3590
+	public function attendee_contact_info($post)
3591
+	{
3592
+		// get attendee object ( should already have it )
3593
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3594
+		$form->enqueueStylesAndScripts();
3595
+		echo $form->display();
3596
+	}
3597
+
3598
+
3599
+	/**
3600
+	 * Return form handler for the contact details metabox
3601
+	 *
3602
+	 * @param EE_Attendee $attendee
3603
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3604
+	 * @throws DomainException
3605
+	 * @throws InvalidArgumentException
3606
+	 * @throws InvalidDataTypeException
3607
+	 * @throws InvalidInterfaceException
3608
+	 */
3609
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3610
+	{
3611
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3612
+	}
3613
+
3614
+
3615
+	/**
3616
+	 * Metabox for attendee details
3617
+	 *
3618
+	 * @param  WP_Post $post wp post object
3619
+	 * @throws DomainException
3620
+	 */
3621
+	public function attendee_address_details($post)
3622
+	{
3623
+		// get attendee object (should already have it)
3624
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3625
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3626
+			new EE_Question_Form_Input(
3627
+				EE_Question::new_instance(
3628
+					array(
3629
+						'QST_ID'           => 0,
3630
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3631
+						'QST_system'       => 'admin-state',
3632
+					)
3633
+				),
3634
+				EE_Answer::new_instance(
3635
+					array(
3636
+						'ANS_ID'    => 0,
3637
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3638
+					)
3639
+				),
3640
+				array(
3641
+					'input_id'       => 'STA_ID',
3642
+					'input_name'     => 'STA_ID',
3643
+					'input_prefix'   => '',
3644
+					'append_qstn_id' => false,
3645
+				)
3646
+			)
3647
+		);
3648
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3649
+			new EE_Question_Form_Input(
3650
+				EE_Question::new_instance(
3651
+					array(
3652
+						'QST_ID'           => 0,
3653
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3654
+						'QST_system'       => 'admin-country',
3655
+					)
3656
+				),
3657
+				EE_Answer::new_instance(
3658
+					array(
3659
+						'ANS_ID'    => 0,
3660
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3661
+					)
3662
+				),
3663
+				array(
3664
+					'input_id'       => 'CNT_ISO',
3665
+					'input_name'     => 'CNT_ISO',
3666
+					'input_prefix'   => '',
3667
+					'append_qstn_id' => false,
3668
+				)
3669
+			)
3670
+		);
3671
+		$template =
3672
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3673
+		EEH_Template::display_template($template, $this->_template_args);
3674
+	}
3675
+
3676
+
3677
+	/**
3678
+	 *        _attendee_details
3679
+	 *
3680
+	 * @access protected
3681
+	 * @param $post
3682
+	 * @return void
3683
+	 * @throws DomainException
3684
+	 * @throws EE_Error
3685
+	 * @throws InvalidArgumentException
3686
+	 * @throws InvalidDataTypeException
3687
+	 * @throws InvalidInterfaceException
3688
+	 * @throws ReflectionException
3689
+	 */
3690
+	public function attendee_registrations_meta_box($post)
3691
+	{
3692
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3693
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3694
+		$template =
3695
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3696
+		EEH_Template::display_template($template, $this->_template_args);
3697
+	}
3698
+
3699
+
3700
+	/**
3701
+	 * add in the form fields for the attendee edit
3702
+	 *
3703
+	 * @param  WP_Post $post wp post object
3704
+	 * @return string html for new form.
3705
+	 * @throws DomainException
3706
+	 */
3707
+	public function after_title_form_fields($post)
3708
+	{
3709
+		if ($post->post_type === 'espresso_attendees') {
3710
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3711
+			$template_args['attendee'] = $this->_cpt_model_obj;
3712
+			EEH_Template::display_template($template, $template_args);
3713
+		}
3714
+	}
3715
+
3716
+
3717
+	/**
3718
+	 *        _trash_or_restore_attendee
3719
+	 *
3720
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3721
+	 * @return void
3722
+	 * @throws EE_Error
3723
+	 * @throws InvalidArgumentException
3724
+	 * @throws InvalidDataTypeException
3725
+	 * @throws InvalidInterfaceException
3726
+	 * @throws ReflectionException
3727
+	 * @access protected
3728
+	 */
3729
+	protected function _trash_or_restore_attendees($trash = true)
3730
+	{
3731
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3732
+		$success = 1;
3733
+		// Checkboxes
3734
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3735
+			// if array has more than one element than success message should be plural
3736
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3737
+			// cycle thru checkboxes
3738
+			foreach ($this->_req_data['checkbox'] as $ATT_ID) {
3739
+				$updated = $trash ? $this->getAttendeeModel()->update_by_ID(array('status' => 'trash'), $ATT_ID)
3740
+					: $this->getAttendeeModel()->update_by_ID(array('status' => 'publish'), $ATT_ID);
3741
+				if (! $updated) {
3742
+					$success = 0;
3743
+				}
3744
+			}
3745
+		} else {
3746
+			// grab single id and delete
3747
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3748
+			// get attendee
3749
+			$att = $this->getAttendeeModel()->get_one_by_ID($ATT_ID);
3750
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3751
+			$updated = $att->save() && $updated;
3752
+			if (! $updated) {
3753
+				$success = 0;
3754
+			}
3755
+		}
3756
+		$what = $success > 1
3757
+			? esc_html__('Contacts', 'event_espresso')
3758
+			: esc_html__('Contact', 'event_espresso');
3759
+		$action_desc = $trash
3760
+			? esc_html__('moved to the trash', 'event_espresso')
3761
+			: esc_html__('restored', 'event_espresso');
3762
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3763
+	}
3764 3764
 }
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page.core.php 1 patch
Indentation   +1517 added lines, -1517 removed lines patch added patch discarded remove patch
@@ -17,1523 +17,1523 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * _venue
22
-     * This will hold the venue object for venue_details screen.
23
-     *
24
-     * @access protected
25
-     * @var object
26
-     */
27
-    protected $_venue;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var object
34
-     */
35
-    protected $_category;
36
-
37
-
38
-    /**
39
-     * This property will hold the venue model instance
40
-     *
41
-     * @var object
42
-     */
43
-    protected $_venue_model;
44
-
45
-
46
-    protected function _init_page_props()
47
-    {
48
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
49
-        $this->page_slug = EE_VENUES_PG_SLUG;
50
-        $this->_admin_base_url = EE_VENUES_ADMIN_URL;
51
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
52
-        $this->page_label = __('Event Venues', 'event_espresso');
53
-        $this->_cpt_model_names = array(
54
-            'create_new' => 'EEM_Venue',
55
-            'edit'       => 'EEM_Venue',
56
-        );
57
-        $this->_cpt_edit_routes = array(
58
-            'espresso_venues' => 'edit',
59
-        );
60
-        $this->_venue_model = EEM_Venue::instance();
61
-    }
62
-
63
-
64
-    protected function _ajax_hooks()
65
-    {
66
-        // todo: all hooks for ee_venues ajax goes in here.
67
-    }
68
-
69
-
70
-    protected function _define_page_props()
71
-    {
72
-        $this->_admin_page_title = $this->page_label;
73
-        $this->_labels = array(
74
-            'buttons'      => array(
75
-                'add'             => __('Add New Venue', 'event_espresso'),
76
-                'edit'            => __('Edit Venue', 'event_espresso'),
77
-                'delete'          => __('Delete Venue', 'event_espresso'),
78
-                'add_category'    => __('Add New Category', 'event_espresso'),
79
-                'edit_category'   => __('Edit Category', 'event_espresso'),
80
-                'delete_category' => __('Delete Category', 'event_espresso'),
81
-            ),
82
-            'editor_title' => array(
83
-                'espresso_venues' => __('Enter Venue name here', 'event_espresso'),
84
-            ),
85
-            'publishbox'   => array(
86
-                'create_new'          => __('Save New Venue', 'event_espresso'),
87
-                'edit'                => __('Update Venue', 'event_espresso'),
88
-                'add_category'        => __('Save New Category', 'event_espresso'),
89
-                'edit_category'       => __('Update Category', 'event_espresso'),
90
-                'google_map_settings' => __('Update Settings', 'event_espresso'),
91
-            ),
92
-        );
93
-    }
94
-
95
-
96
-    protected function _set_page_routes()
97
-    {
98
-
99
-        // load formatter helper
100
-        // load field generator helper
101
-
102
-        // is there a vnu_id in the request?
103
-        $vnu_id = ! empty($this->_req_data['VNU_ID']) && ! is_array($this->_req_data['VNU_ID'])
104
-            ? $this->_req_data['VNU_ID'] : 0;
105
-        $vnu_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $vnu_id;
106
-
107
-        $this->_page_routes = array(
108
-            'default'                    => array(
109
-                'func'       => '_overview_list_table',
110
-                'capability' => 'ee_read_venues',
111
-            ),
112
-            'create_new'                 => array(
113
-                'func'       => '_create_new_cpt_item',
114
-                'capability' => 'ee_edit_venues',
115
-            ),
116
-            'edit'                       => array(
117
-                'func'       => '_edit_cpt_item',
118
-                'capability' => 'ee_edit_venue',
119
-                'obj_id'     => $vnu_id,
120
-            ),
121
-            'trash_venue'                => array(
122
-                'func'       => '_trash_or_restore_venue',
123
-                'args'       => array('venue_status' => 'trash'),
124
-                'noheader'   => true,
125
-                'capability' => 'ee_delete_venue',
126
-                'obj_id'     => $vnu_id,
127
-            ),
128
-            'trash_venues'               => array(
129
-                'func'       => '_trash_or_restore_venues',
130
-                'args'       => array('venue_status' => 'trash'),
131
-                'noheader'   => true,
132
-                'capability' => 'ee_delete_venues',
133
-            ),
134
-            'restore_venue'              => array(
135
-                'func'       => '_trash_or_restore_venue',
136
-                'args'       => array('venue_status' => 'draft'),
137
-                'noheader'   => true,
138
-                'capability' => 'ee_delete_venue',
139
-                'obj_id'     => $vnu_id,
140
-            ),
141
-            'restore_venues'             => array(
142
-                'func'       => '_trash_or_restore_venues',
143
-                'args'       => array('venue_status' => 'draft'),
144
-                'noheader'   => true,
145
-                'capability' => 'ee_delete_venues',
146
-            ),
147
-            'delete_venues'              => array(
148
-                'func'       => '_delete_venues',
149
-                'noheader'   => true,
150
-                'capability' => 'ee_delete_venues',
151
-            ),
152
-            'delete_venue'               => array(
153
-                'func'       => '_delete_venue',
154
-                'noheader'   => true,
155
-                'capability' => 'ee_delete_venue',
156
-                'obj_id'     => $vnu_id,
157
-            ),
158
-            // settings related
159
-            'google_map_settings'        => array(
160
-                'func'       => '_google_map_settings',
161
-                'capability' => 'manage_options',
162
-            ),
163
-            'update_google_map_settings' => array(
164
-                'func'       => '_update_google_map_settings',
165
-                'capability' => 'manage_options',
166
-                'noheader'   => true,
167
-            ),
168
-            // venue category tab related
169
-            'add_category'               => array(
170
-                'func'       => '_category_details',
171
-                'args'       => array('add'),
172
-                'capability' => 'ee_edit_venue_category',
173
-            ),
174
-            'edit_category'              => array(
175
-                'func'       => '_category_details',
176
-                'args'       => array('edit'),
177
-                'capability' => 'ee_edit_venue_category',
178
-            ),
179
-            'delete_categories'          => array(
180
-                'func'       => '_delete_categories',
181
-                'noheader'   => true,
182
-                'capability' => 'ee_delete_venue_category',
183
-            ),
184
-
185
-            'delete_category' => array(
186
-                'func'       => '_delete_categories',
187
-                'noheader'   => true,
188
-                'capability' => 'ee_delete_venue_category',
189
-            ),
190
-
191
-            'insert_category' => array(
192
-                'func'       => '_insert_or_update_category',
193
-                'args'       => array('new_category' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_edit_venue_category',
196
-            ),
197
-
198
-            'update_category'   => array(
199
-                'func'       => '_insert_or_update_category',
200
-                'args'       => array('new_category' => false),
201
-                'noheader'   => true,
202
-                'capability' => 'ee_edit_venue_category',
203
-            ),
204
-            'export_categories' => array(
205
-                'func'       => '_categories_export',
206
-                'noheader'   => true,
207
-                'capability' => 'export',
208
-            ),
209
-            'import_categories' => array(
210
-                'func'       => '_import_categories',
211
-                'capability' => 'import',
212
-            ),
213
-            'category_list'     => array(
214
-                'func'       => '_category_list_table',
215
-                'capability' => 'ee_manage_venue_categories',
216
-            ),
217
-        );
218
-    }
219
-
220
-
221
-    protected function _set_page_config()
222
-    {
223
-        $this->_page_config = array(
224
-            'default'             => array(
225
-                'nav'           => array(
226
-                    'label' => __('Overview', 'event_espresso'),
227
-                    'order' => 10,
228
-                ),
229
-                'list_table'    => 'Venues_Admin_List_Table',
230
-                'help_tabs'     => array(
231
-                    'venues_overview_help_tab'                           => array(
232
-                        'title'    => __('Venues Overview', 'event_espresso'),
233
-                        'filename' => 'venues_overview',
234
-                    ),
235
-                    'venues_overview_table_column_headings_help_tab'     => array(
236
-                        'title'    => __('Venues Overview Table Column Headings', 'event_espresso'),
237
-                        'filename' => 'venues_overview_table_column_headings',
238
-                    ),
239
-                    'venues_overview_views_bulk_actions_search_help_tab' => array(
240
-                        'title'    => __('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
241
-                        'filename' => 'venues_overview_views_bulk_actions_search',
242
-                    ),
243
-                ),
244
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
245
-                // 'help_tour'     => array('Venues_Overview_Help_Tour'),
246
-                'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
247
-                'require_nonce' => false,
248
-            ),
249
-            'create_new'          => array(
250
-                'nav'           => array(
251
-                    'label'      => __('Add Venue', 'event_espresso'),
252
-                    'order'      => 5,
253
-                    'persistent' => false,
254
-                ),
255
-                'help_tabs'     => array(
256
-                    'venues_editor_help_tab'                                               => array(
257
-                        'title'    => __('Venue Editor', 'event_espresso'),
258
-                        'filename' => 'venues_editor',
259
-                    ),
260
-                    'venues_editor_title_richtexteditor_help_tab'                          => array(
261
-                        'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
262
-                        'filename' => 'venues_editor_title_richtexteditor',
263
-                    ),
264
-                    'venues_editor_tags_categories_help_tab'                               => array(
265
-                        'title'    => __('Venue Tags & Categories', 'event_espresso'),
266
-                        'filename' => 'venues_editor_tags_categories',
267
-                    ),
268
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
269
-                        'title'    => __(
270
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
271
-                            'event_espresso'
272
-                        ),
273
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
274
-                    ),
275
-                    'venues_editor_save_new_venue_help_tab'                                => array(
276
-                        'title'    => __('Save New Venue', 'event_espresso'),
277
-                        'filename' => 'venues_editor_save_new_venue',
278
-                    ),
279
-                    'venues_editor_other_help_tab'                                         => array(
280
-                        'title'    => __('Venue Editor Other', 'event_espresso'),
281
-                        'filename' => 'venues_editor_other',
282
-                    ),
283
-                ),
284
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
285
-                // 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
286
-                'metaboxes'     => array('_venue_editor_metaboxes'),
287
-                'require_nonce' => false,
288
-            ),
289
-            'edit'                => array(
290
-                'nav'           => array(
291
-                    'label'      => __('Edit Venue', 'event_espresso'),
292
-                    'order'      => 5,
293
-                    'persistent' => false,
294
-                    'url'        => isset($this->_req_data['post']) ? add_query_arg(
295
-                        array('post' => $this->_req_data['post']),
296
-                        $this->_current_page_view_url
297
-                    ) : $this->_admin_base_url,
298
-                ),
299
-                'help_tabs'     => array(
300
-                    'venues_editor_help_tab'                                               => array(
301
-                        'title'    => __('Venue Editor', 'event_espresso'),
302
-                        'filename' => 'venues_editor',
303
-                    ),
304
-                    'venues_editor_title_richtexteditor_help_tab'                          => array(
305
-                        'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
306
-                        'filename' => 'venues_editor_title_richtexteditor',
307
-                    ),
308
-                    'venues_editor_tags_categories_help_tab'                               => array(
309
-                        'title'    => __('Venue Tags & Categories', 'event_espresso'),
310
-                        'filename' => 'venues_editor_tags_categories',
311
-                    ),
312
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
313
-                        'title'    => __(
314
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
315
-                            'event_espresso'
316
-                        ),
317
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
318
-                    ),
319
-                    'venues_editor_save_new_venue_help_tab'                                => array(
320
-                        'title'    => __('Save New Venue', 'event_espresso'),
321
-                        'filename' => 'venues_editor_save_new_venue',
322
-                    ),
323
-                    'venues_editor_other_help_tab'                                         => array(
324
-                        'title'    => __('Venue Editor Other', 'event_espresso'),
325
-                        'filename' => 'venues_editor_other',
326
-                    ),
327
-                ),
328
-                /*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
329
-                'metaboxes'     => array('_venue_editor_metaboxes'),
330
-                'require_nonce' => false,
331
-            ),
332
-            'google_map_settings' => array(
333
-                'nav'           => array(
334
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
335
-                    'order' => 40,
336
-                ),
337
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
338
-                'help_tabs'     => array(
339
-                    'general_settings_google_maps_help_tab' => array(
340
-                        'title'    => __('Google Maps', 'event_espresso'),
341
-                        'filename' => 'general_settings_google_maps',
342
-                    ),
343
-                ),
344
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
345
-                // 'help_tour'     => array('Google_Maps_Help_Tour'),
346
-                'require_nonce' => false,
347
-            ),
348
-            // venue category stuff
349
-            'add_category'        => array(
350
-                'nav'           => array(
351
-                    'label'      => __('Add Category', 'event_espresso'),
352
-                    'order'      => 15,
353
-                    'persistent' => false,
354
-                ),
355
-                'metaboxes'     => array('_publish_post_box'),
356
-                'help_tabs'     => array(
357
-                    'venues_add_category_help_tab' => array(
358
-                        'title'    => __('Add New Venue Category', 'event_espresso'),
359
-                        'filename' => 'venues_add_category',
360
-                    ),
361
-                ),
362
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
363
-                // 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
364
-                'require_nonce' => false,
365
-            ),
366
-            'edit_category'       => array(
367
-                'nav'           => array(
368
-                    'label'      => __('Edit Category', 'event_espresso'),
369
-                    'order'      => 15,
370
-                    'persistent' => false,
371
-                    'url'        => isset($this->_req_data['EVT_CAT_ID']) ? add_query_arg(
372
-                        array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
373
-                        $this->_current_page_view_url
374
-                    ) : $this->_admin_base_url,
375
-                ),
376
-                'metaboxes'     => array('_publish_post_box'),
377
-                'help_tabs'     => array(
378
-                    'venues_edit_category_help_tab' => array(
379
-                        'title'    => __('Edit Venue Category', 'event_espresso'),
380
-                        'filename' => 'venues_edit_category',
381
-                    ),
382
-                ),
383
-                /*'help_tour' => array( 'Venues_Edit_Category_Help_Tour' ),*/
384
-                'require_nonce' => false,
385
-            ),
386
-            'category_list'       => array(
387
-                'nav'           => array(
388
-                    'label' => __('Categories', 'event_espresso'),
389
-                    'order' => 20,
390
-                ),
391
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
392
-                'help_tabs'     => array(
393
-                    'venues_categories_help_tab'                       => array(
394
-                        'title'    => __('Venue Categories', 'event_espresso'),
395
-                        'filename' => 'venues_categories',
396
-                    ),
397
-                    'venues_categories_table_column_headings_help_tab' => array(
398
-                        'title'    => __('Venue Categories Table Column Headings', 'event_espresso'),
399
-                        'filename' => 'venues_categories_table_column_headings',
400
-                    ),
401
-                    'venues_categories_views_help_tab'                 => array(
402
-                        'title'    => __('Venue Categories Views', 'event_espresso'),
403
-                        'filename' => 'venues_categories_views',
404
-                    ),
405
-                    'venues_categories_other_help_tab'                 => array(
406
-                        'title'    => __('Venue Categories Other', 'event_espresso'),
407
-                        'filename' => 'venues_categories_other',
408
-                    ),
409
-                ),
410
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
411
-                // 'help_tour'     => array('Venues_Categories_Help_Tour'),
412
-                'metaboxes'     => $this->_default_espresso_metaboxes,
413
-                'require_nonce' => false,
414
-            ),
415
-        );
416
-    }
417
-
418
-
419
-    protected function _add_screen_options()
420
-    {
421
-        // todo
422
-    }
423
-
424
-
425
-    protected function _add_screen_options_default()
426
-    {
427
-        $this->_per_page_screen_option();
428
-    }
429
-
430
-
431
-    protected function _add_screen_options_category_list()
432
-    {
433
-        $page_title = $this->_admin_page_title;
434
-        $this->_admin_page_title = __('Venue Categories', 'event_espresso');
435
-        $this->_per_page_screen_option();
436
-        $this->_admin_page_title = $page_title;
437
-    }
438
-
439
-
440
-    // none of the below group are currently used for Event Venues
441
-    protected function _add_feature_pointers()
442
-    {
443
-    }
444
-
445
-    public function admin_init()
446
-    {
447
-    }
448
-
449
-    public function admin_notices()
450
-    {
451
-    }
452
-
453
-    public function admin_footer_scripts()
454
-    {
455
-    }
456
-
457
-
458
-    public function load_scripts_styles_create_new()
459
-    {
460
-        $this->load_scripts_styles_edit();
461
-    }
462
-
463
-
464
-    public function load_scripts_styles()
465
-    {
466
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
467
-        wp_enqueue_style('ee-cat-admin');
468
-    }
469
-
470
-
471
-    public function load_scripts_styles_add_category()
472
-    {
473
-        $this->load_scripts_styles_edit_category();
474
-    }
475
-
476
-
477
-    public function load_scripts_styles_edit_category()
478
-    {
479
-    }
480
-
481
-
482
-    public function load_scripts_styles_edit()
483
-    {
484
-        // styles
485
-        wp_enqueue_style('espresso-ui-theme');
486
-        wp_register_style(
487
-            'espresso_venues',
488
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
489
-            array(),
490
-            EVENT_ESPRESSO_VERSION
491
-        );
492
-        wp_enqueue_style('espresso_venues');
493
-    }
494
-
495
-
496
-    protected function _set_list_table_views_default()
497
-    {
498
-        $this->_views = array(
499
-            'all' => array(
500
-                'slug'        => 'all',
501
-                'label'       => __('View All Venues', 'event_espresso'),
502
-                'count'       => 0,
503
-                'bulk_action' => array(),
504
-            ),
505
-        );
506
-
507
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
508
-            $this->_views['all']['bulk_action'] = array(
509
-                'trash_venues' => __('Move to Trash', 'event_espresso'),
510
-            );
511
-            $this->_views['trash'] = array(
512
-                'slug'        => 'trash',
513
-                'label'       => __('Trash', 'event_espresso'),
514
-                'count'       => 0,
515
-                'bulk_action' => array(
516
-                    'restore_venues' => __('Restore from Trash', 'event_espresso'),
517
-                    'delete_venues'  => __('Delete', 'event_espresso'),
518
-                ),
519
-            );
520
-        }
521
-    }
522
-
523
-
524
-    protected function _set_list_table_views_category_list()
525
-    {
526
-        $this->_views = array(
527
-            'all' => array(
528
-                'slug'        => 'all',
529
-                'label'       => __('All', 'event_espresso'),
530
-                'count'       => 0,
531
-                'bulk_action' => array(
532
-                    'delete_categories' => __('Delete Permanently', 'event_espresso'),
533
-                ),
534
-            ),
535
-        );
536
-    }
537
-
538
-
539
-    protected function _overview_list_table()
540
-    {
541
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
-            get_post_type_archive_link('espresso_venues'),
544
-            __("View Venue Archive Page", "event_espresso"),
545
-            'button'
546
-        );
547
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button('create_new', 'add', array(), 'add-new-h2');
548
-        $this->_search_btn_label = __('Venues', 'event_espresso');
549
-        $this->display_admin_list_table_page_with_sidebar();
550
-    }
551
-
552
-
553
-    public function extra_misc_actions_publish_box()
554
-    {
555
-        $extra_rows = array(
556
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
557
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
558
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
559
-        );
560
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
561
-        EEH_Template::display_template($template, $extra_rows);
562
-    }
563
-
564
-
565
-    /*************        Google Maps        *************/
566
-
567
-
568
-    protected function _google_map_settings()
569
-    {
570
-
571
-
572
-        $this->_template_args['values'] = $this->_yes_no_values;
573
-        $default_map_settings = new stdClass();
574
-        $default_map_settings->use_google_maps = true;
575
-        $default_map_settings->google_map_api_key = '';
576
-        // for event details pages (reg page)
577
-        $default_map_settings->event_details_map_width = 585;            // ee_map_width_single
578
-        $default_map_settings->event_details_map_height = 362;            // ee_map_height_single
579
-        $default_map_settings->event_details_map_zoom = 14;            // ee_map_zoom_single
580
-        $default_map_settings->event_details_display_nav = true;            // ee_map_nav_display_single
581
-        $default_map_settings->event_details_nav_size = false;            // ee_map_nav_size_single
582
-        $default_map_settings->event_details_control_type = 'default';        // ee_map_type_control_single
583
-        $default_map_settings->event_details_map_align = 'center';            // ee_map_align_single
584
-        // for event list pages
585
-        $default_map_settings->event_list_map_width = 300;            // ee_map_width
586
-        $default_map_settings->event_list_map_height = 185;        // ee_map_height
587
-        $default_map_settings->event_list_map_zoom = 12;            // ee_map_zoom
588
-        $default_map_settings->event_list_display_nav = false;        // ee_map_nav_display
589
-        $default_map_settings->event_list_nav_size = true;            // ee_map_nav_size
590
-        $default_map_settings->event_list_control_type = 'dropdown';        // ee_map_type_control
591
-        $default_map_settings->event_list_map_align = 'center';            // ee_map_align
592
-
593
-        $this->_template_args['map_settings'] =
594
-            isset(EE_Registry::instance()->CFG->map_settings)
595
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
596
-                ? (object) array_merge(
597
-                    (array) $default_map_settings,
598
-                    (array) EE_Registry::instance()->CFG->map_settings
599
-                )
600
-                : $default_map_settings;
601
-
602
-        $this->_set_add_edit_form_tags('update_google_map_settings');
603
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
604
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
605
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
606
-            $this->_template_args,
607
-            true
608
-        );
609
-        $this->display_admin_page_with_sidebar();
610
-    }
611
-
612
-    protected function _update_google_map_settings()
613
-    {
614
-
615
-        EE_Registry::instance()->CFG->map_settings->use_google_maps =
616
-            isset($this->_req_data['use_google_maps'])
617
-                ? absint($this->_req_data['use_google_maps'])
618
-                : EE_Registry::instance()->CFG->map_settings->use_google_maps;
619
-
620
-        EE_Registry::instance()->CFG->map_settings->google_map_api_key =
621
-            isset($this->_req_data['google_map_api_key'])
622
-                ? sanitize_text_field($this->_req_data['google_map_api_key'])
623
-                : EE_Registry::instance()->CFG->map_settings->google_map_api_key;
624
-
625
-        EE_Registry::instance()->CFG->map_settings->event_details_map_width =
626
-            isset($this->_req_data['event_details_map_width'])
627
-                ? absint($this->_req_data['event_details_map_width'])
628
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_width;
629
-
630
-        EE_Registry::instance()->CFG->map_settings->event_details_map_height =
631
-            isset($this->_req_data['event_details_map_height'])
632
-                ? absint($this->_req_data['event_details_map_height'])
633
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_height;
634
-
635
-        EE_Registry::instance()->CFG->map_settings->event_details_map_zoom =
636
-            isset($this->_req_data['event_details_map_zoom'])
637
-                ? absint($this->_req_data['event_details_map_zoom'])
638
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_zoom;
639
-
640
-        EE_Registry::instance()->CFG->map_settings->event_details_display_nav =
641
-            isset($this->_req_data['event_details_display_nav'])
642
-                ? absint($this->_req_data['event_details_display_nav'])
643
-                : EE_Registry::instance()->CFG->map_settings->event_details_display_nav;
644
-
645
-        EE_Registry::instance()->CFG->map_settings->event_details_nav_size =
646
-            isset($this->_req_data['event_details_nav_size'])
647
-                ? absint($this->_req_data['event_details_nav_size'])
648
-                : EE_Registry::instance()->CFG->map_settings->event_details_nav_size;
649
-
650
-        EE_Registry::instance()->CFG->map_settings->event_details_control_type =
651
-            isset($this->_req_data['event_details_control_type'])
652
-                ? sanitize_text_field($this->_req_data['event_details_control_type'])
653
-                : EE_Registry::instance()->CFG->map_settings->event_details_control_type;
654
-
655
-        EE_Registry::instance()->CFG->map_settings->event_details_map_align =
656
-            isset($this->_req_data['event_details_map_align'])
657
-                ? sanitize_text_field($this->_req_data['event_details_map_align'])
658
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_align;
659
-
660
-        EE_Registry::instance()->CFG->map_settings->event_list_map_width =
661
-            isset($this->_req_data['event_list_map_width'])
662
-                ? absint($this->_req_data['event_list_map_width'])
663
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_width;
664
-
665
-        EE_Registry::instance()->CFG->map_settings->event_list_map_height =
666
-            isset($this->_req_data['event_list_map_height'])
667
-                ? absint($this->_req_data['event_list_map_height'])
668
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_height;
669
-
670
-        EE_Registry::instance()->CFG->map_settings->event_list_map_zoom =
671
-            isset($this->_req_data['event_list_map_zoom'])
672
-                ? absint($this->_req_data['event_list_map_zoom'])
673
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_zoom;
674
-
675
-        EE_Registry::instance()->CFG->map_settings->event_list_display_nav =
676
-            isset($this->_req_data['event_list_display_nav'])
677
-                ? absint($this->_req_data['event_list_display_nav'])
678
-                : EE_Registry::instance()->CFG->map_settings->event_list_display_nav;
679
-
680
-        EE_Registry::instance()->CFG->map_settings->event_list_nav_size =
681
-            isset($this->_req_data['event_list_nav_size'])
682
-                ? absint($this->_req_data['event_list_nav_size'])
683
-                : EE_Registry::instance()->CFG->map_settings->event_list_nav_size;
684
-
685
-        EE_Registry::instance()->CFG->map_settings->event_list_control_type =
686
-            isset($this->_req_data['event_list_control_type'])
687
-                ? sanitize_text_field($this->_req_data['event_list_control_type'])
688
-                : EE_Registry::instance()->CFG->map_settings->event_list_control_type;
689
-
690
-        EE_Registry::instance()->CFG->map_settings->event_list_map_align =
691
-            isset($this->_req_data['event_list_map_align'])
692
-                ? sanitize_text_field($this->_req_data['event_list_map_align'])
693
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_align;
694
-
695
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
696
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
697
-            EE_Registry::instance()->CFG->map_settings
698
-        );
699
-
700
-        $what = 'Google Map Settings';
701
-        $success = $this->_update_espresso_configuration(
702
-            $what,
703
-            EE_Registry::instance()->CFG->map_settings,
704
-            __FILE__,
705
-            __FUNCTION__,
706
-            __LINE__
707
-        );
708
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'google_map_settings'));
709
-    }
710
-
711
-
712
-    protected function _venue_editor_metaboxes()
713
-    {
714
-        $this->verify_cpt_object();
715
-
716
-        add_meta_box(
717
-            'espresso_venue_address_options',
718
-            __('Physical Location', 'event_espresso'),
719
-            array($this, 'venue_address_metabox'),
720
-            $this->page_slug,
721
-            'side',
722
-            'default'
723
-        );
724
-        add_meta_box(
725
-            'espresso_venue_gmap_options',
726
-            __('Google Map', 'event_espresso'),
727
-            array($this, 'venue_gmap_metabox'),
728
-            $this->page_slug,
729
-            'side',
730
-            'default'
731
-        );
732
-        add_meta_box(
733
-            'espresso_venue_virtual_loc_options',
734
-            __('Virtual Location', 'event_espresso'),
735
-            array($this, 'venue_virtual_loc_metabox'),
736
-            $this->page_slug,
737
-            'side',
738
-            'default'
739
-        );
740
-    }
741
-
742
-
743
-    public function venue_gmap_metabox()
744
-    {
745
-        $template_args = array(
746
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
747
-                'vnu_enable_for_gmap',
748
-                $this->get_yes_no_values(),
749
-                $this->_cpt_model_obj->enable_for_gmap()
750
-            ),
751
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
752
-        );
753
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
754
-        EEH_Template::display_template($template, $template_args);
755
-    }
756
-
757
-
758
-    public function venue_address_metabox()
759
-    {
760
-
761
-        $template_args['_venue'] = $this->_cpt_model_obj;
762
-
763
-        $template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
764
-            $QFI = new EE_Question_Form_Input(
765
-                EE_Question::new_instance(
766
-                    array('QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state')
767
-                ),
768
-                EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->state_ID())),
769
-                array(
770
-                    'input_name'     => 'sta_id',
771
-                    'input_id'       => 'sta_id',
772
-                    'input_class'    => '',
773
-                    'input_prefix'   => '',
774
-                    'append_qstn_id' => false,
775
-                )
776
-            )
777
-        );
778
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
779
-            $QFI = new EE_Question_Form_Input(
780
-                EE_Question::new_instance(
781
-                    array('QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country')
782
-                ),
783
-                EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->country_ID())),
784
-                array(
785
-                    'input_name'     => 'cnt_iso',
786
-                    'input_id'       => 'cnt_iso',
787
-                    'input_class'    => '',
788
-                    'input_prefix'   => '',
789
-                    'append_qstn_id' => false,
790
-                )
791
-            )
792
-        );
793
-
794
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
795
-        EEH_Template::display_template($template, $template_args);
796
-    }
797
-
798
-
799
-    public function venue_virtual_loc_metabox()
800
-    {
801
-        $template_args = array(
802
-            '_venue' => $this->_cpt_model_obj,
803
-        );
804
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
805
-        EEH_Template::display_template($template, $template_args);
806
-    }
807
-
808
-
809
-    protected function _restore_cpt_item($post_id, $revision_id)
810
-    {
811
-        $venue_obj = $this->_venue_model->get_one_by_ID($post_id);
812
-
813
-        // meta revision restore
814
-        $venue_obj->restore_revision($revision_id);
815
-    }
816
-
817
-
818
-    /**
819
-     * Handles updates for venue cpts
820
-     *
821
-     * @param  int    $post_id ID of Venue CPT
822
-     * @param  object $post    Post object (with "blessed" WP properties)
823
-     * @return void
824
-     */
825
-    protected function _insert_update_cpt_item($post_id, $post)
826
-    {
827
-
828
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
829
-            return;// get out we're not processing the saving of venues.
830
-        }
831
-
832
-        $wheres = array($this->_venue_model->primary_key_name() => $post_id);
833
-
834
-        $venue_values = array(
835
-            'VNU_address'         => ! empty($this->_req_data['vnu_address']) ? $this->_req_data['vnu_address'] : null,
836
-            'VNU_address2'        => ! empty($this->_req_data['vnu_address2']) ? $this->_req_data['vnu_address2']
837
-                : null,
838
-            'VNU_city'            => ! empty($this->_req_data['vnu_city']) ? $this->_req_data['vnu_city'] : null,
839
-            'STA_ID'              => ! empty($this->_req_data['sta_id']) ? $this->_req_data['sta_id'] : null,
840
-            'CNT_ISO'             => ! empty($this->_req_data['cnt_iso']) ? $this->_req_data['cnt_iso'] : null,
841
-            'VNU_zip'             => ! empty($this->_req_data['vnu_zip']) ? $this->_req_data['vnu_zip'] : null,
842
-            'VNU_phone'           => ! empty($this->_req_data['vnu_phone']) ? $this->_req_data['vnu_phone'] : null,
843
-            'VNU_capacity'        => ! empty($this->_req_data['vnu_capacity']) ? str_replace(
844
-                ',',
845
-                '',
846
-                $this->_req_data['vnu_capacity']
847
-            ) : EE_INF,
848
-            'VNU_url'             => ! empty($this->_req_data['vnu_url']) ? $this->_req_data['vnu_url'] : null,
849
-            'VNU_virtual_phone'   => ! empty($this->_req_data['vnu_virtual_phone'])
850
-                ? $this->_req_data['vnu_virtual_phone'] : null,
851
-            'VNU_virtual_url'     => ! empty($this->_req_data['vnu_virtual_url']) ? $this->_req_data['vnu_virtual_url']
852
-                : null,
853
-            'VNU_enable_for_gmap' => ! empty($this->_req_data['vnu_enable_for_gmap']) ? true : false,
854
-            'VNU_google_map_link' => ! empty($this->_req_data['vnu_google_map_link'])
855
-                ? $this->_req_data['vnu_google_map_link'] : null,
856
-        );
857
-
858
-        // update venue
859
-        $success = $this->_venue_model->update($venue_values, array($wheres));
860
-
861
-        // get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
862
-        $get_one_where = array($this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status);
863
-        $venue = $this->_venue_model->get_one(array($get_one_where));
864
-
865
-        // notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
866
-        $venue_update_callbacks = apply_filters(
867
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
868
-            array()
869
-        );
870
-
871
-        $att_success = true;
872
-
873
-        foreach ($venue_update_callbacks as $v_callback) {
874
-            $_succ = call_user_func_array($v_callback, array($venue, $this->_req_data));
875
-            $att_success = ! $att_success ? $att_success
876
-                : $_succ; // if ANY of these updates fail then we want the appropriate global error message
877
-        }
878
-
879
-        // any errors?
880
-        if ($success && ! $att_success) {
881
-            EE_Error::add_error(
882
-                __(
883
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
884
-                    'event_espresso'
885
-                ),
886
-                __FILE__,
887
-                __FUNCTION__,
888
-                __LINE__
889
-            );
890
-        } elseif ($success === false) {
891
-            EE_Error::add_error(
892
-                __('Venue Details did not save successfully.', 'event_espresso'),
893
-                __FILE__,
894
-                __FUNCTION__,
895
-                __LINE__
896
-            );
897
-        }
898
-    }
899
-
900
-
901
-    public function trash_cpt_item($post_id)
902
-    {
903
-        $this->_req_data['VNU_ID'] = $post_id;
904
-        $this->_trash_or_restore_venue('trash', false);
905
-    }
906
-
907
-
908
-    public function restore_cpt_item($post_id)
909
-    {
910
-        $this->_req_data['VNU_ID'] = $post_id;
911
-        $this->_trash_or_restore_venue('draft', false);
912
-    }
913
-
914
-
915
-    public function delete_cpt_item($post_id)
916
-    {
917
-        $this->_req_data['VNU_ID'] = $post_id;
918
-        $this->_delete_venue(false);
919
-    }
920
-
921
-
922
-    public function get_venue_object()
923
-    {
924
-        return $this->_cpt_model_obj;
925
-    }
926
-
927
-
928
-    protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
929
-    {
930
-        $VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : false;
931
-
932
-        // loop thru venues
933
-        if ($VNU_ID) {
934
-            // clean status
935
-            $venue_status = sanitize_key($venue_status);
936
-            // grab status
937
-            if (! empty($venue_status)) {
938
-                $success = $this->_change_venue_status($VNU_ID, $venue_status);
939
-            } else {
940
-                $success = false;
941
-                $msg = __(
942
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
943
-                    'event_espresso'
944
-                );
945
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
946
-            }
947
-        } else {
948
-            $success = false;
949
-            $msg = __(
950
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
951
-                'event_espresso'
952
-            );
953
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
954
-        }
955
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
956
-
957
-        if ($redirect_after) {
958
-            $this->_redirect_after_action($success, 'Venue', $action, array('action' => 'default'));
959
-        }
960
-    }
961
-
962
-
963
-    protected function _trash_or_restore_venues($venue_status = 'trash')
964
-    {
965
-        // clean status
966
-        $venue_status = sanitize_key($venue_status);
967
-        // grab status
968
-        if (! empty($venue_status)) {
969
-            $success = true;
970
-            // determine the event id and set to array.
971
-            $VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
972
-            // loop thru events
973
-            foreach ($VNU_IDs as $VNU_ID) {
974
-                if ($VNU_ID = absint($VNU_ID)) {
975
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
976
-                    $success = $results !== false ? $success : false;
977
-                } else {
978
-                    $msg = sprintf(
979
-                        __(
980
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
981
-                            'event_espresso'
982
-                        ),
983
-                        $VNU_ID
984
-                    );
985
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
986
-                    $success = false;
987
-                }
988
-            }
989
-        } else {
990
-            $success = false;
991
-            $msg = __(
992
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
993
-                'event_espresso'
994
-            );
995
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
996
-        }
997
-        // in order to force a pluralized result message we need to send back a success status greater than 1
998
-        $success = $success ? 2 : false;
999
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1000
-        $this->_redirect_after_action($success, 'Venues', $action, array('action' => 'default'));
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * _trash_or_restore_venues
1006
-     *
1007
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1008
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1009
-     * accepting a certain number of params.
1010
-     *
1011
-     * @access  private
1012
-     * @param  int    $VNU_ID
1013
-     * @param  string $venue_status
1014
-     * @return void
1015
-     */
1016
-    private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1017
-    {
1018
-        // grab venue id
1019
-        if (! $VNU_ID) {
1020
-            $msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1021
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1022
-            return false;
1023
-        }
1024
-
1025
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1026
-
1027
-        // clean status
1028
-        $venue_status = sanitize_key($venue_status);
1029
-        // grab status
1030
-        if (! $venue_status) {
1031
-            $msg = __('An error occurred. No Venue Status or an invalid Venue Status was received.', 'event_espresso');
1032
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
-            return false;
1034
-        }
1035
-
1036
-        // was event trashed or restored ?
1037
-        switch ($venue_status) {
1038
-            case 'draft':
1039
-                $action = 'restored from the trash';
1040
-                $hook = 'AHEE_venue_restored_from_trash';
1041
-                break;
1042
-            case 'trash':
1043
-                $action = 'moved to the trash';
1044
-                $hook = 'AHEE_venue_moved_to_trash';
1045
-                break;
1046
-            default:
1047
-                $action = 'updated';
1048
-                $hook = false;
1049
-        }
1050
-        // use class to change status
1051
-        $this->_cpt_model_obj->set_status($venue_status);
1052
-        $success = $this->_cpt_model_obj->save();
1053
-
1054
-        if ($success === false) {
1055
-            $msg = sprintf(__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1056
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1057
-            return false;
1058
-        }
1059
-        if ($hook) {
1060
-            do_action($hook);
1061
-        }
1062
-        return true;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * @param  bool $redirect_after
1068
-     * @return void
1069
-     */
1070
-    protected function _delete_venue($redirect_after = true)
1071
-    {
1072
-        // determine the venue id and set to array.
1073
-        $VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : null;
1074
-        $VNU_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $VNU_ID;
1075
-
1076
-
1077
-        // loop thru venues
1078
-        if ($VNU_ID) {
1079
-            $success = $this->_delete_or_trash_venue($VNU_ID);
1080
-        } else {
1081
-            $success = false;
1082
-            $msg = __(
1083
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1084
-                'event_espresso'
1085
-            );
1086
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1087
-        }
1088
-        if ($redirect_after) {
1089
-            $this->_redirect_after_action($success, 'Venue', 'deleted', array('action' => 'default'));
1090
-        }
1091
-    }
1092
-
1093
-
1094
-    protected function _delete_venues()
1095
-    {
1096
-        $success = true;
1097
-        // determine the event id and set to array.
1098
-        $VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
1099
-        // loop thru events
1100
-        foreach ($VNU_IDs as $VNU_ID) {
1101
-            if ($VNU_ID = absint($VNU_ID)) {
1102
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1103
-                $success = $results !== false ? $success : false;
1104
-            } else {
1105
-                $success = false;
1106
-                $msg = __(
1107
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
-                    'event_espresso'
1109
-                );
1110
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
-            }
1112
-        }
1113
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1114
-        $success = $success ? 2 : false;
1115
-        $this->_redirect_after_action(
1116
-            $success,
1117
-            __('Venues', 'event_espresso'),
1118
-            __('deleted', 'event_espresso'),
1119
-            array('action' => 'default')
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    // todo: put in parent
1125
-    private function _delete_or_trash_venue($VNU_ID = false)
1126
-    {
1127
-        // grab event id
1128
-        if (! $VNU_ID = absint($VNU_ID)) {
1129
-            $msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1130
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            return false;
1132
-        }
1133
-
1134
-
1135
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1136
-        // first need to remove all term relationships
1137
-        $venue->_remove_relations('Term_Taxonomy');
1138
-        $success = $venue->delete_permanently();
1139
-        // did it all go as planned ?
1140
-        if ($success) {
1141
-            $msg = sprintf(__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1142
-            EE_Error::add_success($msg);
1143
-        } else {
1144
-            $msg = sprintf(__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'), $VNU_ID);
1145
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1146
-            return false;
1147
-        }
1148
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1149
-        return true;
1150
-    }
1151
-
1152
-
1153
-
1154
-
1155
-    /***********/
1156
-    /* QUERIES */
1157
-
1158
-
1159
-    public function get_venues($per_page = 10, $count = false)
1160
-    {
1161
-
1162
-        $_orderby = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1163
-
1164
-        switch ($_orderby) {
1165
-            case 'id':
1166
-                $orderby = 'VNU_ID';
1167
-                break;
1168
-
1169
-            case 'capacity':
1170
-                $orderby = 'VNU_capacity';
1171
-                break;
1172
-
1173
-            case 'city':
1174
-                $orderby = 'VNU_city';
1175
-                break;
1176
-
1177
-            default:
1178
-                $orderby = 'VNU_name';
1179
-        }
1180
-
1181
-
1182
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1183
-            : 'ASC';
1184
-
1185
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1186
-            ? $this->_req_data['paged'] : 1;
1187
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
1188
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1189
-            ? $this->_req_data['perpage'] : $per_page;
1190
-
1191
-
1192
-        $offset = ($current_page - 1) * $per_page;
1193
-        $limit = array($offset, $per_page);
1194
-
1195
-        $category = isset($this->_req_data['category']) && $this->_req_data['category'] > 0
1196
-            ? $this->_req_data['category'] : null;
1197
-        $where = array();
1198
-
1199
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1200
-        if (isset($this->_req_data['status']) && $this->_req_data['status'] != 'all') {
1201
-            $where['status'] = $this->_req_data['status'];
1202
-        }
1203
-
1204
-        if (isset($this->_req_data['venue_status'])) {
1205
-            $where['status'] = $this->_req_data['venue_status'];
1206
-        }
1207
-
1208
-
1209
-        if ($category) {
1210
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1211
-            $where['Term_Taxonomy.term_id'] = $category;
1212
-        }
1213
-
1214
-
1215
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1216
-            $where['VNU_wp_user'] = get_current_user_id();
1217
-        } else {
1218
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1219
-                $where['OR'] = array(
1220
-                    'status*restrict_private' => array('!=', 'private'),
1221
-                    'AND'                     => array(
1222
-                        'status*inclusive' => array('=', 'private'),
1223
-                        'VNU_wp_user'      => get_current_user_id(),
1224
-                    ),
1225
-                );
1226
-            }
1227
-        }
1228
-
1229
-
1230
-        if (isset($this->_req_data['s'])) {
1231
-            $sstr = '%' . $this->_req_data['s'] . '%';
1232
-            $where['OR'] = array(
1233
-                'VNU_name'               => array('LIKE', $sstr),
1234
-                'VNU_desc'               => array('LIKE', $sstr),
1235
-                'VNU_short_desc'         => array('LIKE', $sstr),
1236
-                'VNU_address'            => array('LIKE', $sstr),
1237
-                'VNU_address2'           => array('LIKE', $sstr),
1238
-                'VNU_city'               => array('LIKE', $sstr),
1239
-                'VNU_zip'                => array('LIKE', $sstr),
1240
-                'VNU_phone'              => array('LIKE', $sstr),
1241
-                'VNU_url'                => array('LIKE', $sstr),
1242
-                'VNU_virtual_phone'      => array('LIKE', $sstr),
1243
-                'VNU_virtual_url'        => array('LIKE', $sstr),
1244
-                'VNU_google_map_link'    => array('LIKE', $sstr),
1245
-                'Event.EVT_name'         => array('LIKE', $sstr),
1246
-                'Event.EVT_desc'         => array('LIKE', $sstr),
1247
-                'Event.EVT_phone'        => array('LIKE', $sstr),
1248
-                'Event.EVT_external_URL' => array('LIKE', $sstr),
1249
-            );
1250
-        }
20
+	/**
21
+	 * _venue
22
+	 * This will hold the venue object for venue_details screen.
23
+	 *
24
+	 * @access protected
25
+	 * @var object
26
+	 */
27
+	protected $_venue;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var object
34
+	 */
35
+	protected $_category;
36
+
37
+
38
+	/**
39
+	 * This property will hold the venue model instance
40
+	 *
41
+	 * @var object
42
+	 */
43
+	protected $_venue_model;
44
+
45
+
46
+	protected function _init_page_props()
47
+	{
48
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
49
+		$this->page_slug = EE_VENUES_PG_SLUG;
50
+		$this->_admin_base_url = EE_VENUES_ADMIN_URL;
51
+		$this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
52
+		$this->page_label = __('Event Venues', 'event_espresso');
53
+		$this->_cpt_model_names = array(
54
+			'create_new' => 'EEM_Venue',
55
+			'edit'       => 'EEM_Venue',
56
+		);
57
+		$this->_cpt_edit_routes = array(
58
+			'espresso_venues' => 'edit',
59
+		);
60
+		$this->_venue_model = EEM_Venue::instance();
61
+	}
62
+
63
+
64
+	protected function _ajax_hooks()
65
+	{
66
+		// todo: all hooks for ee_venues ajax goes in here.
67
+	}
68
+
69
+
70
+	protected function _define_page_props()
71
+	{
72
+		$this->_admin_page_title = $this->page_label;
73
+		$this->_labels = array(
74
+			'buttons'      => array(
75
+				'add'             => __('Add New Venue', 'event_espresso'),
76
+				'edit'            => __('Edit Venue', 'event_espresso'),
77
+				'delete'          => __('Delete Venue', 'event_espresso'),
78
+				'add_category'    => __('Add New Category', 'event_espresso'),
79
+				'edit_category'   => __('Edit Category', 'event_espresso'),
80
+				'delete_category' => __('Delete Category', 'event_espresso'),
81
+			),
82
+			'editor_title' => array(
83
+				'espresso_venues' => __('Enter Venue name here', 'event_espresso'),
84
+			),
85
+			'publishbox'   => array(
86
+				'create_new'          => __('Save New Venue', 'event_espresso'),
87
+				'edit'                => __('Update Venue', 'event_espresso'),
88
+				'add_category'        => __('Save New Category', 'event_espresso'),
89
+				'edit_category'       => __('Update Category', 'event_espresso'),
90
+				'google_map_settings' => __('Update Settings', 'event_espresso'),
91
+			),
92
+		);
93
+	}
94
+
95
+
96
+	protected function _set_page_routes()
97
+	{
98
+
99
+		// load formatter helper
100
+		// load field generator helper
101
+
102
+		// is there a vnu_id in the request?
103
+		$vnu_id = ! empty($this->_req_data['VNU_ID']) && ! is_array($this->_req_data['VNU_ID'])
104
+			? $this->_req_data['VNU_ID'] : 0;
105
+		$vnu_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $vnu_id;
106
+
107
+		$this->_page_routes = array(
108
+			'default'                    => array(
109
+				'func'       => '_overview_list_table',
110
+				'capability' => 'ee_read_venues',
111
+			),
112
+			'create_new'                 => array(
113
+				'func'       => '_create_new_cpt_item',
114
+				'capability' => 'ee_edit_venues',
115
+			),
116
+			'edit'                       => array(
117
+				'func'       => '_edit_cpt_item',
118
+				'capability' => 'ee_edit_venue',
119
+				'obj_id'     => $vnu_id,
120
+			),
121
+			'trash_venue'                => array(
122
+				'func'       => '_trash_or_restore_venue',
123
+				'args'       => array('venue_status' => 'trash'),
124
+				'noheader'   => true,
125
+				'capability' => 'ee_delete_venue',
126
+				'obj_id'     => $vnu_id,
127
+			),
128
+			'trash_venues'               => array(
129
+				'func'       => '_trash_or_restore_venues',
130
+				'args'       => array('venue_status' => 'trash'),
131
+				'noheader'   => true,
132
+				'capability' => 'ee_delete_venues',
133
+			),
134
+			'restore_venue'              => array(
135
+				'func'       => '_trash_or_restore_venue',
136
+				'args'       => array('venue_status' => 'draft'),
137
+				'noheader'   => true,
138
+				'capability' => 'ee_delete_venue',
139
+				'obj_id'     => $vnu_id,
140
+			),
141
+			'restore_venues'             => array(
142
+				'func'       => '_trash_or_restore_venues',
143
+				'args'       => array('venue_status' => 'draft'),
144
+				'noheader'   => true,
145
+				'capability' => 'ee_delete_venues',
146
+			),
147
+			'delete_venues'              => array(
148
+				'func'       => '_delete_venues',
149
+				'noheader'   => true,
150
+				'capability' => 'ee_delete_venues',
151
+			),
152
+			'delete_venue'               => array(
153
+				'func'       => '_delete_venue',
154
+				'noheader'   => true,
155
+				'capability' => 'ee_delete_venue',
156
+				'obj_id'     => $vnu_id,
157
+			),
158
+			// settings related
159
+			'google_map_settings'        => array(
160
+				'func'       => '_google_map_settings',
161
+				'capability' => 'manage_options',
162
+			),
163
+			'update_google_map_settings' => array(
164
+				'func'       => '_update_google_map_settings',
165
+				'capability' => 'manage_options',
166
+				'noheader'   => true,
167
+			),
168
+			// venue category tab related
169
+			'add_category'               => array(
170
+				'func'       => '_category_details',
171
+				'args'       => array('add'),
172
+				'capability' => 'ee_edit_venue_category',
173
+			),
174
+			'edit_category'              => array(
175
+				'func'       => '_category_details',
176
+				'args'       => array('edit'),
177
+				'capability' => 'ee_edit_venue_category',
178
+			),
179
+			'delete_categories'          => array(
180
+				'func'       => '_delete_categories',
181
+				'noheader'   => true,
182
+				'capability' => 'ee_delete_venue_category',
183
+			),
184
+
185
+			'delete_category' => array(
186
+				'func'       => '_delete_categories',
187
+				'noheader'   => true,
188
+				'capability' => 'ee_delete_venue_category',
189
+			),
190
+
191
+			'insert_category' => array(
192
+				'func'       => '_insert_or_update_category',
193
+				'args'       => array('new_category' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_edit_venue_category',
196
+			),
197
+
198
+			'update_category'   => array(
199
+				'func'       => '_insert_or_update_category',
200
+				'args'       => array('new_category' => false),
201
+				'noheader'   => true,
202
+				'capability' => 'ee_edit_venue_category',
203
+			),
204
+			'export_categories' => array(
205
+				'func'       => '_categories_export',
206
+				'noheader'   => true,
207
+				'capability' => 'export',
208
+			),
209
+			'import_categories' => array(
210
+				'func'       => '_import_categories',
211
+				'capability' => 'import',
212
+			),
213
+			'category_list'     => array(
214
+				'func'       => '_category_list_table',
215
+				'capability' => 'ee_manage_venue_categories',
216
+			),
217
+		);
218
+	}
219
+
220
+
221
+	protected function _set_page_config()
222
+	{
223
+		$this->_page_config = array(
224
+			'default'             => array(
225
+				'nav'           => array(
226
+					'label' => __('Overview', 'event_espresso'),
227
+					'order' => 10,
228
+				),
229
+				'list_table'    => 'Venues_Admin_List_Table',
230
+				'help_tabs'     => array(
231
+					'venues_overview_help_tab'                           => array(
232
+						'title'    => __('Venues Overview', 'event_espresso'),
233
+						'filename' => 'venues_overview',
234
+					),
235
+					'venues_overview_table_column_headings_help_tab'     => array(
236
+						'title'    => __('Venues Overview Table Column Headings', 'event_espresso'),
237
+						'filename' => 'venues_overview_table_column_headings',
238
+					),
239
+					'venues_overview_views_bulk_actions_search_help_tab' => array(
240
+						'title'    => __('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
241
+						'filename' => 'venues_overview_views_bulk_actions_search',
242
+					),
243
+				),
244
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
245
+				// 'help_tour'     => array('Venues_Overview_Help_Tour'),
246
+				'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
247
+				'require_nonce' => false,
248
+			),
249
+			'create_new'          => array(
250
+				'nav'           => array(
251
+					'label'      => __('Add Venue', 'event_espresso'),
252
+					'order'      => 5,
253
+					'persistent' => false,
254
+				),
255
+				'help_tabs'     => array(
256
+					'venues_editor_help_tab'                                               => array(
257
+						'title'    => __('Venue Editor', 'event_espresso'),
258
+						'filename' => 'venues_editor',
259
+					),
260
+					'venues_editor_title_richtexteditor_help_tab'                          => array(
261
+						'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
262
+						'filename' => 'venues_editor_title_richtexteditor',
263
+					),
264
+					'venues_editor_tags_categories_help_tab'                               => array(
265
+						'title'    => __('Venue Tags & Categories', 'event_espresso'),
266
+						'filename' => 'venues_editor_tags_categories',
267
+					),
268
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
269
+						'title'    => __(
270
+							'Venue Editor Physical Location & Google Map & Virtual Location',
271
+							'event_espresso'
272
+						),
273
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
274
+					),
275
+					'venues_editor_save_new_venue_help_tab'                                => array(
276
+						'title'    => __('Save New Venue', 'event_espresso'),
277
+						'filename' => 'venues_editor_save_new_venue',
278
+					),
279
+					'venues_editor_other_help_tab'                                         => array(
280
+						'title'    => __('Venue Editor Other', 'event_espresso'),
281
+						'filename' => 'venues_editor_other',
282
+					),
283
+				),
284
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
285
+				// 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
286
+				'metaboxes'     => array('_venue_editor_metaboxes'),
287
+				'require_nonce' => false,
288
+			),
289
+			'edit'                => array(
290
+				'nav'           => array(
291
+					'label'      => __('Edit Venue', 'event_espresso'),
292
+					'order'      => 5,
293
+					'persistent' => false,
294
+					'url'        => isset($this->_req_data['post']) ? add_query_arg(
295
+						array('post' => $this->_req_data['post']),
296
+						$this->_current_page_view_url
297
+					) : $this->_admin_base_url,
298
+				),
299
+				'help_tabs'     => array(
300
+					'venues_editor_help_tab'                                               => array(
301
+						'title'    => __('Venue Editor', 'event_espresso'),
302
+						'filename' => 'venues_editor',
303
+					),
304
+					'venues_editor_title_richtexteditor_help_tab'                          => array(
305
+						'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
306
+						'filename' => 'venues_editor_title_richtexteditor',
307
+					),
308
+					'venues_editor_tags_categories_help_tab'                               => array(
309
+						'title'    => __('Venue Tags & Categories', 'event_espresso'),
310
+						'filename' => 'venues_editor_tags_categories',
311
+					),
312
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
313
+						'title'    => __(
314
+							'Venue Editor Physical Location & Google Map & Virtual Location',
315
+							'event_espresso'
316
+						),
317
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
318
+					),
319
+					'venues_editor_save_new_venue_help_tab'                                => array(
320
+						'title'    => __('Save New Venue', 'event_espresso'),
321
+						'filename' => 'venues_editor_save_new_venue',
322
+					),
323
+					'venues_editor_other_help_tab'                                         => array(
324
+						'title'    => __('Venue Editor Other', 'event_espresso'),
325
+						'filename' => 'venues_editor_other',
326
+					),
327
+				),
328
+				/*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
329
+				'metaboxes'     => array('_venue_editor_metaboxes'),
330
+				'require_nonce' => false,
331
+			),
332
+			'google_map_settings' => array(
333
+				'nav'           => array(
334
+					'label' => esc_html__('Google Maps', 'event_espresso'),
335
+					'order' => 40,
336
+				),
337
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
338
+				'help_tabs'     => array(
339
+					'general_settings_google_maps_help_tab' => array(
340
+						'title'    => __('Google Maps', 'event_espresso'),
341
+						'filename' => 'general_settings_google_maps',
342
+					),
343
+				),
344
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
345
+				// 'help_tour'     => array('Google_Maps_Help_Tour'),
346
+				'require_nonce' => false,
347
+			),
348
+			// venue category stuff
349
+			'add_category'        => array(
350
+				'nav'           => array(
351
+					'label'      => __('Add Category', 'event_espresso'),
352
+					'order'      => 15,
353
+					'persistent' => false,
354
+				),
355
+				'metaboxes'     => array('_publish_post_box'),
356
+				'help_tabs'     => array(
357
+					'venues_add_category_help_tab' => array(
358
+						'title'    => __('Add New Venue Category', 'event_espresso'),
359
+						'filename' => 'venues_add_category',
360
+					),
361
+				),
362
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
363
+				// 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
364
+				'require_nonce' => false,
365
+			),
366
+			'edit_category'       => array(
367
+				'nav'           => array(
368
+					'label'      => __('Edit Category', 'event_espresso'),
369
+					'order'      => 15,
370
+					'persistent' => false,
371
+					'url'        => isset($this->_req_data['EVT_CAT_ID']) ? add_query_arg(
372
+						array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
373
+						$this->_current_page_view_url
374
+					) : $this->_admin_base_url,
375
+				),
376
+				'metaboxes'     => array('_publish_post_box'),
377
+				'help_tabs'     => array(
378
+					'venues_edit_category_help_tab' => array(
379
+						'title'    => __('Edit Venue Category', 'event_espresso'),
380
+						'filename' => 'venues_edit_category',
381
+					),
382
+				),
383
+				/*'help_tour' => array( 'Venues_Edit_Category_Help_Tour' ),*/
384
+				'require_nonce' => false,
385
+			),
386
+			'category_list'       => array(
387
+				'nav'           => array(
388
+					'label' => __('Categories', 'event_espresso'),
389
+					'order' => 20,
390
+				),
391
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
392
+				'help_tabs'     => array(
393
+					'venues_categories_help_tab'                       => array(
394
+						'title'    => __('Venue Categories', 'event_espresso'),
395
+						'filename' => 'venues_categories',
396
+					),
397
+					'venues_categories_table_column_headings_help_tab' => array(
398
+						'title'    => __('Venue Categories Table Column Headings', 'event_espresso'),
399
+						'filename' => 'venues_categories_table_column_headings',
400
+					),
401
+					'venues_categories_views_help_tab'                 => array(
402
+						'title'    => __('Venue Categories Views', 'event_espresso'),
403
+						'filename' => 'venues_categories_views',
404
+					),
405
+					'venues_categories_other_help_tab'                 => array(
406
+						'title'    => __('Venue Categories Other', 'event_espresso'),
407
+						'filename' => 'venues_categories_other',
408
+					),
409
+				),
410
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
411
+				// 'help_tour'     => array('Venues_Categories_Help_Tour'),
412
+				'metaboxes'     => $this->_default_espresso_metaboxes,
413
+				'require_nonce' => false,
414
+			),
415
+		);
416
+	}
417
+
418
+
419
+	protected function _add_screen_options()
420
+	{
421
+		// todo
422
+	}
423
+
424
+
425
+	protected function _add_screen_options_default()
426
+	{
427
+		$this->_per_page_screen_option();
428
+	}
429
+
430
+
431
+	protected function _add_screen_options_category_list()
432
+	{
433
+		$page_title = $this->_admin_page_title;
434
+		$this->_admin_page_title = __('Venue Categories', 'event_espresso');
435
+		$this->_per_page_screen_option();
436
+		$this->_admin_page_title = $page_title;
437
+	}
438
+
439
+
440
+	// none of the below group are currently used for Event Venues
441
+	protected function _add_feature_pointers()
442
+	{
443
+	}
444
+
445
+	public function admin_init()
446
+	{
447
+	}
448
+
449
+	public function admin_notices()
450
+	{
451
+	}
452
+
453
+	public function admin_footer_scripts()
454
+	{
455
+	}
456
+
457
+
458
+	public function load_scripts_styles_create_new()
459
+	{
460
+		$this->load_scripts_styles_edit();
461
+	}
462
+
463
+
464
+	public function load_scripts_styles()
465
+	{
466
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
467
+		wp_enqueue_style('ee-cat-admin');
468
+	}
469
+
470
+
471
+	public function load_scripts_styles_add_category()
472
+	{
473
+		$this->load_scripts_styles_edit_category();
474
+	}
475
+
476
+
477
+	public function load_scripts_styles_edit_category()
478
+	{
479
+	}
480
+
481
+
482
+	public function load_scripts_styles_edit()
483
+	{
484
+		// styles
485
+		wp_enqueue_style('espresso-ui-theme');
486
+		wp_register_style(
487
+			'espresso_venues',
488
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
489
+			array(),
490
+			EVENT_ESPRESSO_VERSION
491
+		);
492
+		wp_enqueue_style('espresso_venues');
493
+	}
494
+
495
+
496
+	protected function _set_list_table_views_default()
497
+	{
498
+		$this->_views = array(
499
+			'all' => array(
500
+				'slug'        => 'all',
501
+				'label'       => __('View All Venues', 'event_espresso'),
502
+				'count'       => 0,
503
+				'bulk_action' => array(),
504
+			),
505
+		);
506
+
507
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
508
+			$this->_views['all']['bulk_action'] = array(
509
+				'trash_venues' => __('Move to Trash', 'event_espresso'),
510
+			);
511
+			$this->_views['trash'] = array(
512
+				'slug'        => 'trash',
513
+				'label'       => __('Trash', 'event_espresso'),
514
+				'count'       => 0,
515
+				'bulk_action' => array(
516
+					'restore_venues' => __('Restore from Trash', 'event_espresso'),
517
+					'delete_venues'  => __('Delete', 'event_espresso'),
518
+				),
519
+			);
520
+		}
521
+	}
522
+
523
+
524
+	protected function _set_list_table_views_category_list()
525
+	{
526
+		$this->_views = array(
527
+			'all' => array(
528
+				'slug'        => 'all',
529
+				'label'       => __('All', 'event_espresso'),
530
+				'count'       => 0,
531
+				'bulk_action' => array(
532
+					'delete_categories' => __('Delete Permanently', 'event_espresso'),
533
+				),
534
+			),
535
+		);
536
+	}
537
+
538
+
539
+	protected function _overview_list_table()
540
+	{
541
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
+			get_post_type_archive_link('espresso_venues'),
544
+			__("View Venue Archive Page", "event_espresso"),
545
+			'button'
546
+		);
547
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button('create_new', 'add', array(), 'add-new-h2');
548
+		$this->_search_btn_label = __('Venues', 'event_espresso');
549
+		$this->display_admin_list_table_page_with_sidebar();
550
+	}
551
+
552
+
553
+	public function extra_misc_actions_publish_box()
554
+	{
555
+		$extra_rows = array(
556
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
557
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
558
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
559
+		);
560
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
561
+		EEH_Template::display_template($template, $extra_rows);
562
+	}
563
+
564
+
565
+	/*************        Google Maps        *************/
566
+
567
+
568
+	protected function _google_map_settings()
569
+	{
570
+
571
+
572
+		$this->_template_args['values'] = $this->_yes_no_values;
573
+		$default_map_settings = new stdClass();
574
+		$default_map_settings->use_google_maps = true;
575
+		$default_map_settings->google_map_api_key = '';
576
+		// for event details pages (reg page)
577
+		$default_map_settings->event_details_map_width = 585;            // ee_map_width_single
578
+		$default_map_settings->event_details_map_height = 362;            // ee_map_height_single
579
+		$default_map_settings->event_details_map_zoom = 14;            // ee_map_zoom_single
580
+		$default_map_settings->event_details_display_nav = true;            // ee_map_nav_display_single
581
+		$default_map_settings->event_details_nav_size = false;            // ee_map_nav_size_single
582
+		$default_map_settings->event_details_control_type = 'default';        // ee_map_type_control_single
583
+		$default_map_settings->event_details_map_align = 'center';            // ee_map_align_single
584
+		// for event list pages
585
+		$default_map_settings->event_list_map_width = 300;            // ee_map_width
586
+		$default_map_settings->event_list_map_height = 185;        // ee_map_height
587
+		$default_map_settings->event_list_map_zoom = 12;            // ee_map_zoom
588
+		$default_map_settings->event_list_display_nav = false;        // ee_map_nav_display
589
+		$default_map_settings->event_list_nav_size = true;            // ee_map_nav_size
590
+		$default_map_settings->event_list_control_type = 'dropdown';        // ee_map_type_control
591
+		$default_map_settings->event_list_map_align = 'center';            // ee_map_align
592
+
593
+		$this->_template_args['map_settings'] =
594
+			isset(EE_Registry::instance()->CFG->map_settings)
595
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
596
+				? (object) array_merge(
597
+					(array) $default_map_settings,
598
+					(array) EE_Registry::instance()->CFG->map_settings
599
+				)
600
+				: $default_map_settings;
601
+
602
+		$this->_set_add_edit_form_tags('update_google_map_settings');
603
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
604
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
605
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
606
+			$this->_template_args,
607
+			true
608
+		);
609
+		$this->display_admin_page_with_sidebar();
610
+	}
611
+
612
+	protected function _update_google_map_settings()
613
+	{
614
+
615
+		EE_Registry::instance()->CFG->map_settings->use_google_maps =
616
+			isset($this->_req_data['use_google_maps'])
617
+				? absint($this->_req_data['use_google_maps'])
618
+				: EE_Registry::instance()->CFG->map_settings->use_google_maps;
619
+
620
+		EE_Registry::instance()->CFG->map_settings->google_map_api_key =
621
+			isset($this->_req_data['google_map_api_key'])
622
+				? sanitize_text_field($this->_req_data['google_map_api_key'])
623
+				: EE_Registry::instance()->CFG->map_settings->google_map_api_key;
624
+
625
+		EE_Registry::instance()->CFG->map_settings->event_details_map_width =
626
+			isset($this->_req_data['event_details_map_width'])
627
+				? absint($this->_req_data['event_details_map_width'])
628
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_width;
629
+
630
+		EE_Registry::instance()->CFG->map_settings->event_details_map_height =
631
+			isset($this->_req_data['event_details_map_height'])
632
+				? absint($this->_req_data['event_details_map_height'])
633
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_height;
634
+
635
+		EE_Registry::instance()->CFG->map_settings->event_details_map_zoom =
636
+			isset($this->_req_data['event_details_map_zoom'])
637
+				? absint($this->_req_data['event_details_map_zoom'])
638
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_zoom;
639
+
640
+		EE_Registry::instance()->CFG->map_settings->event_details_display_nav =
641
+			isset($this->_req_data['event_details_display_nav'])
642
+				? absint($this->_req_data['event_details_display_nav'])
643
+				: EE_Registry::instance()->CFG->map_settings->event_details_display_nav;
644
+
645
+		EE_Registry::instance()->CFG->map_settings->event_details_nav_size =
646
+			isset($this->_req_data['event_details_nav_size'])
647
+				? absint($this->_req_data['event_details_nav_size'])
648
+				: EE_Registry::instance()->CFG->map_settings->event_details_nav_size;
649
+
650
+		EE_Registry::instance()->CFG->map_settings->event_details_control_type =
651
+			isset($this->_req_data['event_details_control_type'])
652
+				? sanitize_text_field($this->_req_data['event_details_control_type'])
653
+				: EE_Registry::instance()->CFG->map_settings->event_details_control_type;
654
+
655
+		EE_Registry::instance()->CFG->map_settings->event_details_map_align =
656
+			isset($this->_req_data['event_details_map_align'])
657
+				? sanitize_text_field($this->_req_data['event_details_map_align'])
658
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_align;
659
+
660
+		EE_Registry::instance()->CFG->map_settings->event_list_map_width =
661
+			isset($this->_req_data['event_list_map_width'])
662
+				? absint($this->_req_data['event_list_map_width'])
663
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_width;
664
+
665
+		EE_Registry::instance()->CFG->map_settings->event_list_map_height =
666
+			isset($this->_req_data['event_list_map_height'])
667
+				? absint($this->_req_data['event_list_map_height'])
668
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_height;
669
+
670
+		EE_Registry::instance()->CFG->map_settings->event_list_map_zoom =
671
+			isset($this->_req_data['event_list_map_zoom'])
672
+				? absint($this->_req_data['event_list_map_zoom'])
673
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_zoom;
674
+
675
+		EE_Registry::instance()->CFG->map_settings->event_list_display_nav =
676
+			isset($this->_req_data['event_list_display_nav'])
677
+				? absint($this->_req_data['event_list_display_nav'])
678
+				: EE_Registry::instance()->CFG->map_settings->event_list_display_nav;
679
+
680
+		EE_Registry::instance()->CFG->map_settings->event_list_nav_size =
681
+			isset($this->_req_data['event_list_nav_size'])
682
+				? absint($this->_req_data['event_list_nav_size'])
683
+				: EE_Registry::instance()->CFG->map_settings->event_list_nav_size;
684
+
685
+		EE_Registry::instance()->CFG->map_settings->event_list_control_type =
686
+			isset($this->_req_data['event_list_control_type'])
687
+				? sanitize_text_field($this->_req_data['event_list_control_type'])
688
+				: EE_Registry::instance()->CFG->map_settings->event_list_control_type;
689
+
690
+		EE_Registry::instance()->CFG->map_settings->event_list_map_align =
691
+			isset($this->_req_data['event_list_map_align'])
692
+				? sanitize_text_field($this->_req_data['event_list_map_align'])
693
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_align;
694
+
695
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
696
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
697
+			EE_Registry::instance()->CFG->map_settings
698
+		);
699
+
700
+		$what = 'Google Map Settings';
701
+		$success = $this->_update_espresso_configuration(
702
+			$what,
703
+			EE_Registry::instance()->CFG->map_settings,
704
+			__FILE__,
705
+			__FUNCTION__,
706
+			__LINE__
707
+		);
708
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'google_map_settings'));
709
+	}
710
+
711
+
712
+	protected function _venue_editor_metaboxes()
713
+	{
714
+		$this->verify_cpt_object();
715
+
716
+		add_meta_box(
717
+			'espresso_venue_address_options',
718
+			__('Physical Location', 'event_espresso'),
719
+			array($this, 'venue_address_metabox'),
720
+			$this->page_slug,
721
+			'side',
722
+			'default'
723
+		);
724
+		add_meta_box(
725
+			'espresso_venue_gmap_options',
726
+			__('Google Map', 'event_espresso'),
727
+			array($this, 'venue_gmap_metabox'),
728
+			$this->page_slug,
729
+			'side',
730
+			'default'
731
+		);
732
+		add_meta_box(
733
+			'espresso_venue_virtual_loc_options',
734
+			__('Virtual Location', 'event_espresso'),
735
+			array($this, 'venue_virtual_loc_metabox'),
736
+			$this->page_slug,
737
+			'side',
738
+			'default'
739
+		);
740
+	}
741
+
742
+
743
+	public function venue_gmap_metabox()
744
+	{
745
+		$template_args = array(
746
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
747
+				'vnu_enable_for_gmap',
748
+				$this->get_yes_no_values(),
749
+				$this->_cpt_model_obj->enable_for_gmap()
750
+			),
751
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
752
+		);
753
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
754
+		EEH_Template::display_template($template, $template_args);
755
+	}
756
+
757
+
758
+	public function venue_address_metabox()
759
+	{
760
+
761
+		$template_args['_venue'] = $this->_cpt_model_obj;
762
+
763
+		$template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
764
+			$QFI = new EE_Question_Form_Input(
765
+				EE_Question::new_instance(
766
+					array('QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state')
767
+				),
768
+				EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->state_ID())),
769
+				array(
770
+					'input_name'     => 'sta_id',
771
+					'input_id'       => 'sta_id',
772
+					'input_class'    => '',
773
+					'input_prefix'   => '',
774
+					'append_qstn_id' => false,
775
+				)
776
+			)
777
+		);
778
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
779
+			$QFI = new EE_Question_Form_Input(
780
+				EE_Question::new_instance(
781
+					array('QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country')
782
+				),
783
+				EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->country_ID())),
784
+				array(
785
+					'input_name'     => 'cnt_iso',
786
+					'input_id'       => 'cnt_iso',
787
+					'input_class'    => '',
788
+					'input_prefix'   => '',
789
+					'append_qstn_id' => false,
790
+				)
791
+			)
792
+		);
793
+
794
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
795
+		EEH_Template::display_template($template, $template_args);
796
+	}
797
+
798
+
799
+	public function venue_virtual_loc_metabox()
800
+	{
801
+		$template_args = array(
802
+			'_venue' => $this->_cpt_model_obj,
803
+		);
804
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
805
+		EEH_Template::display_template($template, $template_args);
806
+	}
807
+
808
+
809
+	protected function _restore_cpt_item($post_id, $revision_id)
810
+	{
811
+		$venue_obj = $this->_venue_model->get_one_by_ID($post_id);
812
+
813
+		// meta revision restore
814
+		$venue_obj->restore_revision($revision_id);
815
+	}
816
+
817
+
818
+	/**
819
+	 * Handles updates for venue cpts
820
+	 *
821
+	 * @param  int    $post_id ID of Venue CPT
822
+	 * @param  object $post    Post object (with "blessed" WP properties)
823
+	 * @return void
824
+	 */
825
+	protected function _insert_update_cpt_item($post_id, $post)
826
+	{
827
+
828
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
829
+			return;// get out we're not processing the saving of venues.
830
+		}
831
+
832
+		$wheres = array($this->_venue_model->primary_key_name() => $post_id);
833
+
834
+		$venue_values = array(
835
+			'VNU_address'         => ! empty($this->_req_data['vnu_address']) ? $this->_req_data['vnu_address'] : null,
836
+			'VNU_address2'        => ! empty($this->_req_data['vnu_address2']) ? $this->_req_data['vnu_address2']
837
+				: null,
838
+			'VNU_city'            => ! empty($this->_req_data['vnu_city']) ? $this->_req_data['vnu_city'] : null,
839
+			'STA_ID'              => ! empty($this->_req_data['sta_id']) ? $this->_req_data['sta_id'] : null,
840
+			'CNT_ISO'             => ! empty($this->_req_data['cnt_iso']) ? $this->_req_data['cnt_iso'] : null,
841
+			'VNU_zip'             => ! empty($this->_req_data['vnu_zip']) ? $this->_req_data['vnu_zip'] : null,
842
+			'VNU_phone'           => ! empty($this->_req_data['vnu_phone']) ? $this->_req_data['vnu_phone'] : null,
843
+			'VNU_capacity'        => ! empty($this->_req_data['vnu_capacity']) ? str_replace(
844
+				',',
845
+				'',
846
+				$this->_req_data['vnu_capacity']
847
+			) : EE_INF,
848
+			'VNU_url'             => ! empty($this->_req_data['vnu_url']) ? $this->_req_data['vnu_url'] : null,
849
+			'VNU_virtual_phone'   => ! empty($this->_req_data['vnu_virtual_phone'])
850
+				? $this->_req_data['vnu_virtual_phone'] : null,
851
+			'VNU_virtual_url'     => ! empty($this->_req_data['vnu_virtual_url']) ? $this->_req_data['vnu_virtual_url']
852
+				: null,
853
+			'VNU_enable_for_gmap' => ! empty($this->_req_data['vnu_enable_for_gmap']) ? true : false,
854
+			'VNU_google_map_link' => ! empty($this->_req_data['vnu_google_map_link'])
855
+				? $this->_req_data['vnu_google_map_link'] : null,
856
+		);
857
+
858
+		// update venue
859
+		$success = $this->_venue_model->update($venue_values, array($wheres));
860
+
861
+		// get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
862
+		$get_one_where = array($this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status);
863
+		$venue = $this->_venue_model->get_one(array($get_one_where));
864
+
865
+		// notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
866
+		$venue_update_callbacks = apply_filters(
867
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
868
+			array()
869
+		);
870
+
871
+		$att_success = true;
872
+
873
+		foreach ($venue_update_callbacks as $v_callback) {
874
+			$_succ = call_user_func_array($v_callback, array($venue, $this->_req_data));
875
+			$att_success = ! $att_success ? $att_success
876
+				: $_succ; // if ANY of these updates fail then we want the appropriate global error message
877
+		}
878
+
879
+		// any errors?
880
+		if ($success && ! $att_success) {
881
+			EE_Error::add_error(
882
+				__(
883
+					'Venue Details saved successfully but something went wrong with saving attachments.',
884
+					'event_espresso'
885
+				),
886
+				__FILE__,
887
+				__FUNCTION__,
888
+				__LINE__
889
+			);
890
+		} elseif ($success === false) {
891
+			EE_Error::add_error(
892
+				__('Venue Details did not save successfully.', 'event_espresso'),
893
+				__FILE__,
894
+				__FUNCTION__,
895
+				__LINE__
896
+			);
897
+		}
898
+	}
899
+
900
+
901
+	public function trash_cpt_item($post_id)
902
+	{
903
+		$this->_req_data['VNU_ID'] = $post_id;
904
+		$this->_trash_or_restore_venue('trash', false);
905
+	}
906
+
907
+
908
+	public function restore_cpt_item($post_id)
909
+	{
910
+		$this->_req_data['VNU_ID'] = $post_id;
911
+		$this->_trash_or_restore_venue('draft', false);
912
+	}
913
+
914
+
915
+	public function delete_cpt_item($post_id)
916
+	{
917
+		$this->_req_data['VNU_ID'] = $post_id;
918
+		$this->_delete_venue(false);
919
+	}
920
+
921
+
922
+	public function get_venue_object()
923
+	{
924
+		return $this->_cpt_model_obj;
925
+	}
926
+
927
+
928
+	protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
929
+	{
930
+		$VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : false;
931
+
932
+		// loop thru venues
933
+		if ($VNU_ID) {
934
+			// clean status
935
+			$venue_status = sanitize_key($venue_status);
936
+			// grab status
937
+			if (! empty($venue_status)) {
938
+				$success = $this->_change_venue_status($VNU_ID, $venue_status);
939
+			} else {
940
+				$success = false;
941
+				$msg = __(
942
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
943
+					'event_espresso'
944
+				);
945
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
946
+			}
947
+		} else {
948
+			$success = false;
949
+			$msg = __(
950
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
951
+				'event_espresso'
952
+			);
953
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
954
+		}
955
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
956
+
957
+		if ($redirect_after) {
958
+			$this->_redirect_after_action($success, 'Venue', $action, array('action' => 'default'));
959
+		}
960
+	}
961
+
962
+
963
+	protected function _trash_or_restore_venues($venue_status = 'trash')
964
+	{
965
+		// clean status
966
+		$venue_status = sanitize_key($venue_status);
967
+		// grab status
968
+		if (! empty($venue_status)) {
969
+			$success = true;
970
+			// determine the event id and set to array.
971
+			$VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
972
+			// loop thru events
973
+			foreach ($VNU_IDs as $VNU_ID) {
974
+				if ($VNU_ID = absint($VNU_ID)) {
975
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
976
+					$success = $results !== false ? $success : false;
977
+				} else {
978
+					$msg = sprintf(
979
+						__(
980
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
981
+							'event_espresso'
982
+						),
983
+						$VNU_ID
984
+					);
985
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
986
+					$success = false;
987
+				}
988
+			}
989
+		} else {
990
+			$success = false;
991
+			$msg = __(
992
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
993
+				'event_espresso'
994
+			);
995
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
996
+		}
997
+		// in order to force a pluralized result message we need to send back a success status greater than 1
998
+		$success = $success ? 2 : false;
999
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1000
+		$this->_redirect_after_action($success, 'Venues', $action, array('action' => 'default'));
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * _trash_or_restore_venues
1006
+	 *
1007
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1008
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1009
+	 * accepting a certain number of params.
1010
+	 *
1011
+	 * @access  private
1012
+	 * @param  int    $VNU_ID
1013
+	 * @param  string $venue_status
1014
+	 * @return void
1015
+	 */
1016
+	private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1017
+	{
1018
+		// grab venue id
1019
+		if (! $VNU_ID) {
1020
+			$msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1021
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1022
+			return false;
1023
+		}
1024
+
1025
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1026
+
1027
+		// clean status
1028
+		$venue_status = sanitize_key($venue_status);
1029
+		// grab status
1030
+		if (! $venue_status) {
1031
+			$msg = __('An error occurred. No Venue Status or an invalid Venue Status was received.', 'event_espresso');
1032
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
+			return false;
1034
+		}
1035
+
1036
+		// was event trashed or restored ?
1037
+		switch ($venue_status) {
1038
+			case 'draft':
1039
+				$action = 'restored from the trash';
1040
+				$hook = 'AHEE_venue_restored_from_trash';
1041
+				break;
1042
+			case 'trash':
1043
+				$action = 'moved to the trash';
1044
+				$hook = 'AHEE_venue_moved_to_trash';
1045
+				break;
1046
+			default:
1047
+				$action = 'updated';
1048
+				$hook = false;
1049
+		}
1050
+		// use class to change status
1051
+		$this->_cpt_model_obj->set_status($venue_status);
1052
+		$success = $this->_cpt_model_obj->save();
1053
+
1054
+		if ($success === false) {
1055
+			$msg = sprintf(__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1056
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1057
+			return false;
1058
+		}
1059
+		if ($hook) {
1060
+			do_action($hook);
1061
+		}
1062
+		return true;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * @param  bool $redirect_after
1068
+	 * @return void
1069
+	 */
1070
+	protected function _delete_venue($redirect_after = true)
1071
+	{
1072
+		// determine the venue id and set to array.
1073
+		$VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : null;
1074
+		$VNU_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $VNU_ID;
1075
+
1076
+
1077
+		// loop thru venues
1078
+		if ($VNU_ID) {
1079
+			$success = $this->_delete_or_trash_venue($VNU_ID);
1080
+		} else {
1081
+			$success = false;
1082
+			$msg = __(
1083
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1084
+				'event_espresso'
1085
+			);
1086
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1087
+		}
1088
+		if ($redirect_after) {
1089
+			$this->_redirect_after_action($success, 'Venue', 'deleted', array('action' => 'default'));
1090
+		}
1091
+	}
1092
+
1093
+
1094
+	protected function _delete_venues()
1095
+	{
1096
+		$success = true;
1097
+		// determine the event id and set to array.
1098
+		$VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
1099
+		// loop thru events
1100
+		foreach ($VNU_IDs as $VNU_ID) {
1101
+			if ($VNU_ID = absint($VNU_ID)) {
1102
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1103
+				$success = $results !== false ? $success : false;
1104
+			} else {
1105
+				$success = false;
1106
+				$msg = __(
1107
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
+					'event_espresso'
1109
+				);
1110
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
+			}
1112
+		}
1113
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1114
+		$success = $success ? 2 : false;
1115
+		$this->_redirect_after_action(
1116
+			$success,
1117
+			__('Venues', 'event_espresso'),
1118
+			__('deleted', 'event_espresso'),
1119
+			array('action' => 'default')
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	// todo: put in parent
1125
+	private function _delete_or_trash_venue($VNU_ID = false)
1126
+	{
1127
+		// grab event id
1128
+		if (! $VNU_ID = absint($VNU_ID)) {
1129
+			$msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1130
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			return false;
1132
+		}
1133
+
1134
+
1135
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1136
+		// first need to remove all term relationships
1137
+		$venue->_remove_relations('Term_Taxonomy');
1138
+		$success = $venue->delete_permanently();
1139
+		// did it all go as planned ?
1140
+		if ($success) {
1141
+			$msg = sprintf(__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1142
+			EE_Error::add_success($msg);
1143
+		} else {
1144
+			$msg = sprintf(__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'), $VNU_ID);
1145
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1146
+			return false;
1147
+		}
1148
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1149
+		return true;
1150
+	}
1151
+
1152
+
1153
+
1154
+
1155
+	/***********/
1156
+	/* QUERIES */
1157
+
1158
+
1159
+	public function get_venues($per_page = 10, $count = false)
1160
+	{
1161
+
1162
+		$_orderby = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1163
+
1164
+		switch ($_orderby) {
1165
+			case 'id':
1166
+				$orderby = 'VNU_ID';
1167
+				break;
1168
+
1169
+			case 'capacity':
1170
+				$orderby = 'VNU_capacity';
1171
+				break;
1172
+
1173
+			case 'city':
1174
+				$orderby = 'VNU_city';
1175
+				break;
1176
+
1177
+			default:
1178
+				$orderby = 'VNU_name';
1179
+		}
1180
+
1181
+
1182
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1183
+			: 'ASC';
1184
+
1185
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1186
+			? $this->_req_data['paged'] : 1;
1187
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
1188
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1189
+			? $this->_req_data['perpage'] : $per_page;
1190
+
1191
+
1192
+		$offset = ($current_page - 1) * $per_page;
1193
+		$limit = array($offset, $per_page);
1194
+
1195
+		$category = isset($this->_req_data['category']) && $this->_req_data['category'] > 0
1196
+			? $this->_req_data['category'] : null;
1197
+		$where = array();
1198
+
1199
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1200
+		if (isset($this->_req_data['status']) && $this->_req_data['status'] != 'all') {
1201
+			$where['status'] = $this->_req_data['status'];
1202
+		}
1203
+
1204
+		if (isset($this->_req_data['venue_status'])) {
1205
+			$where['status'] = $this->_req_data['venue_status'];
1206
+		}
1207
+
1208
+
1209
+		if ($category) {
1210
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1211
+			$where['Term_Taxonomy.term_id'] = $category;
1212
+		}
1213
+
1214
+
1215
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1216
+			$where['VNU_wp_user'] = get_current_user_id();
1217
+		} else {
1218
+			if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1219
+				$where['OR'] = array(
1220
+					'status*restrict_private' => array('!=', 'private'),
1221
+					'AND'                     => array(
1222
+						'status*inclusive' => array('=', 'private'),
1223
+						'VNU_wp_user'      => get_current_user_id(),
1224
+					),
1225
+				);
1226
+			}
1227
+		}
1228
+
1229
+
1230
+		if (isset($this->_req_data['s'])) {
1231
+			$sstr = '%' . $this->_req_data['s'] . '%';
1232
+			$where['OR'] = array(
1233
+				'VNU_name'               => array('LIKE', $sstr),
1234
+				'VNU_desc'               => array('LIKE', $sstr),
1235
+				'VNU_short_desc'         => array('LIKE', $sstr),
1236
+				'VNU_address'            => array('LIKE', $sstr),
1237
+				'VNU_address2'           => array('LIKE', $sstr),
1238
+				'VNU_city'               => array('LIKE', $sstr),
1239
+				'VNU_zip'                => array('LIKE', $sstr),
1240
+				'VNU_phone'              => array('LIKE', $sstr),
1241
+				'VNU_url'                => array('LIKE', $sstr),
1242
+				'VNU_virtual_phone'      => array('LIKE', $sstr),
1243
+				'VNU_virtual_url'        => array('LIKE', $sstr),
1244
+				'VNU_google_map_link'    => array('LIKE', $sstr),
1245
+				'Event.EVT_name'         => array('LIKE', $sstr),
1246
+				'Event.EVT_desc'         => array('LIKE', $sstr),
1247
+				'Event.EVT_phone'        => array('LIKE', $sstr),
1248
+				'Event.EVT_external_URL' => array('LIKE', $sstr),
1249
+			);
1250
+		}
1251 1251
 
1252 1252
 
1253
-        $venues = $count
1254
-            ? $this->_venue_model->count(array($where), 'VNU_ID')
1255
-            : $this->_venue_model->get_all(
1256
-                array($where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort)
1257
-            );
1258
-
1259
-        return $venues;
1260
-    }
1261
-
1262
-
1263
-
1264
-
1265
-    /** Venue Category Stuff **/
1266
-
1267
-    /**
1268
-     * set the _category property with the category object for the loaded page.
1269
-     *
1270
-     * @access private
1271
-     * @return void
1272
-     */
1273
-    private function _set_category_object()
1274
-    {
1275
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1276
-            return;
1277
-        } // already have the category object so get out.
1278
-
1279
-        // set default category object
1280
-        $this->_set_empty_category_object();
1281
-
1282
-        // only set if we've got an id
1283
-        if (! isset($this->_req_data['VEN_CAT_ID'])) {
1284
-            return;
1285
-        }
1286
-
1287
-        $category_id = absint($this->_req_data['VEN_CAT_ID']);
1288
-        $term = get_term($category_id, 'espresso_venue_categories');
1289
-
1290
-
1291
-        if (! empty($term)) {
1292
-            $this->_category->category_name = $term->name;
1293
-            $this->_category->category_identifier = $term->slug;
1294
-            $this->_category->category_desc = $term->description;
1295
-            $this->_category->id = $term->term_id;
1296
-            $this->_category->parent = $term->parent;
1297
-        }
1298
-    }
1299
-
1300
-
1301
-    private function _set_empty_category_object()
1302
-    {
1303
-        $this->_category = new stdClass();
1304
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1305
-        $this->_category->id = $this->_category->parent = 0;
1306
-    }
1307
-
1308
-
1309
-    protected function _category_list_table()
1310
-    {
1311
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1312
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1313
-            'add_category',
1314
-            'add_category',
1315
-            array(),
1316
-            'add-new-h2'
1317
-        );
1318
-        $this->_search_btn_label = __('Venue Categories', 'event_espresso');
1319
-        $this->display_admin_list_table_page_with_sidebar();
1320
-    }
1321
-
1322
-
1323
-    protected function _category_details($view)
1324
-    {
1325
-
1326
-        // load formatter helper
1327
-        // load field generator helper
1328
-
1329
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1330
-        $this->_set_add_edit_form_tags($route);
1331
-
1332
-        $this->_set_category_object();
1333
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1334
-
1335
-        $delete_action = 'delete_category';
1336
-
1337
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'category_list'), $this->_admin_base_url);
1338
-
1339
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1340
-
1341
-        // take care of contents
1342
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1343
-        $this->display_admin_page_with_sidebar();
1344
-    }
1345
-
1346
-
1347
-    protected function _category_details_content()
1348
-    {
1349
-        $editor_args['category_desc'] = array(
1350
-            'type'          => 'wp_editor',
1351
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1352
-            'class'         => 'my_editor_custom',
1353
-            'wpeditor_args' => array('media_buttons' => false),
1354
-        );
1355
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1356
-
1357
-        $all_terms = get_terms(
1358
-            array('espresso_venue_categories'),
1359
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
1360
-        );
1361
-
1362
-        // setup category select for term parents.
1363
-        $category_select_values[] = array(
1364
-            'text' => __('No Parent', 'event_espresso'),
1365
-            'id'   => 0,
1366
-        );
1367
-        foreach ($all_terms as $term) {
1368
-            $category_select_values[] = array(
1369
-                'text' => $term->name,
1370
-                'id'   => $term->term_id,
1371
-            );
1372
-        }
1373
-
1374
-        $category_select = EEH_Form_Fields::select_input(
1375
-            'category_parent',
1376
-            $category_select_values,
1377
-            $this->_category->parent
1378
-        );
1379
-        $template_args = array(
1380
-            'category'                 => $this->_category,
1381
-            'category_select'          => $category_select,
1382
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1383
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1384
-            'disable'                  => '',
1385
-            'disabled_message'         => false,
1386
-        );
1387
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1388
-        return EEH_Template::display_template($template, $template_args, true);
1389
-    }
1390
-
1391
-
1392
-    protected function _delete_categories()
1393
-    {
1394
-        $cat_ids = isset($this->_req_data['VEN_CAT_ID']) ? (array) $this->_req_data['VEN_CAT_ID']
1395
-            : (array) $this->_req_data['category_id'];
1396
-
1397
-        foreach ($cat_ids as $cat_id) {
1398
-            $this->_delete_category($cat_id);
1399
-        }
1400
-
1401
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1402
-        $query_args = array(
1403
-            'action' => 'category_list',
1404
-        );
1405
-        $this->_redirect_after_action(0, '', '', $query_args);
1406
-    }
1407
-
1408
-
1409
-    protected function _delete_category($cat_id)
1410
-    {
1411
-        $cat_id = absint($cat_id);
1412
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1413
-    }
1414
-
1415
-
1416
-    protected function _insert_or_update_category($new_category)
1417
-    {
1418
-
1419
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1420
-        $success = 0; // we already have a success message so lets not send another.
1421
-        if ($cat_id) {
1422
-            $query_args = array(
1423
-                'action'     => 'edit_category',
1424
-                'VEN_CAT_ID' => $cat_id,
1425
-            );
1426
-        } else {
1427
-            $query_args = array('action' => 'add_category');
1428
-        }
1429
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1430
-    }
1431
-
1432
-
1433
-    private function _insert_category($update = false)
1434
-    {
1435
-        $cat_id = $update ? $this->_req_data['VEN_CAT_ID'] : '';
1436
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
1437
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
1438
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
1439
-
1440
-        if (empty($category_name)) {
1441
-            $msg = __('You must add a name for the category.', 'event_espresso');
1442
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1443
-            return false;
1444
-        }
1445
-
1446
-
1447
-        $term_args = array(
1448
-            'name'        => $category_name,
1449
-            'description' => $category_desc,
1450
-            'parent'      => $category_parent,
1451
-        );
1452
-
1453
-        $insert_ids = $update
1454
-            ? wp_update_term($cat_id, 'espresso_venue_categories', $term_args)
1455
-            : wp_insert_term(
1456
-                $category_name,
1457
-                'espresso_venue_categories',
1458
-                $term_args
1459
-            );
1460
-
1461
-        if (! is_array($insert_ids)) {
1462
-            $msg = __('An error occurred and the category has not been saved to the database.', 'event_espresso');
1463
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1464
-        } else {
1465
-            $cat_id = $insert_ids['term_id'];
1466
-            $msg = sprintf(__('The category %s was successfully created', 'event_espresso'), $category_name);
1467
-            EE_Error::add_success($msg);
1468
-        }
1469
-
1470
-        return $cat_id;
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * TODO handle category exports()
1476
-     *
1477
-     * @return file export
1478
-     */
1479
-    protected function _categories_export()
1480
-    {
1481
-
1482
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1483
-        $new_request_args = array(
1484
-            'export'       => 'report',
1485
-            'action'       => 'categories',
1486
-            'category_ids' => $this->_req_data['VEN_CAT_ID'],
1487
-        );
1488
-
1489
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
1490
-
1491
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1492
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1493
-            $EE_Export = EE_Export::instance($this->_req_data);
1494
-            $EE_Export->export();
1495
-        }
1496
-    }
1497
-
1498
-
1499
-    protected function _import_categories()
1500
-    {
1501
-
1502
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1503
-        EE_Import::instance()->import();
1504
-    }
1505
-
1506
-
1507
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1508
-    {
1509
-
1510
-        // testing term stuff
1511
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
1512
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1513
-        $limit = ($current_page - 1) * $per_page;
1514
-        $where = array('taxonomy' => 'espresso_venue_categories');
1515
-        if (isset($this->_req_data['s'])) {
1516
-            $sstr = '%' . $this->_req_data['s'] . '%';
1517
-            $where['OR'] = array(
1518
-                'Term.name'   => array('LIKE', $sstr),
1519
-                'description' => array('LIKE', $sstr),
1520
-            );
1521
-        }
1522
-
1523
-        $query_params = array(
1524
-            $where,
1525
-            'order_by'   => array($orderby => $order),
1526
-            'limit'      => $limit . ',' . $per_page,
1527
-            'force_join' => array('Term'),
1528
-        );
1529
-
1530
-        $categories = $count ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1531
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1532
-
1533
-        return $categories;
1534
-    }
1535
-
1536
-
1537
-    /* end category stuff */
1538
-    /**************/
1253
+		$venues = $count
1254
+			? $this->_venue_model->count(array($where), 'VNU_ID')
1255
+			: $this->_venue_model->get_all(
1256
+				array($where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort)
1257
+			);
1258
+
1259
+		return $venues;
1260
+	}
1261
+
1262
+
1263
+
1264
+
1265
+	/** Venue Category Stuff **/
1266
+
1267
+	/**
1268
+	 * set the _category property with the category object for the loaded page.
1269
+	 *
1270
+	 * @access private
1271
+	 * @return void
1272
+	 */
1273
+	private function _set_category_object()
1274
+	{
1275
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1276
+			return;
1277
+		} // already have the category object so get out.
1278
+
1279
+		// set default category object
1280
+		$this->_set_empty_category_object();
1281
+
1282
+		// only set if we've got an id
1283
+		if (! isset($this->_req_data['VEN_CAT_ID'])) {
1284
+			return;
1285
+		}
1286
+
1287
+		$category_id = absint($this->_req_data['VEN_CAT_ID']);
1288
+		$term = get_term($category_id, 'espresso_venue_categories');
1289
+
1290
+
1291
+		if (! empty($term)) {
1292
+			$this->_category->category_name = $term->name;
1293
+			$this->_category->category_identifier = $term->slug;
1294
+			$this->_category->category_desc = $term->description;
1295
+			$this->_category->id = $term->term_id;
1296
+			$this->_category->parent = $term->parent;
1297
+		}
1298
+	}
1299
+
1300
+
1301
+	private function _set_empty_category_object()
1302
+	{
1303
+		$this->_category = new stdClass();
1304
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1305
+		$this->_category->id = $this->_category->parent = 0;
1306
+	}
1307
+
1308
+
1309
+	protected function _category_list_table()
1310
+	{
1311
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1312
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1313
+			'add_category',
1314
+			'add_category',
1315
+			array(),
1316
+			'add-new-h2'
1317
+		);
1318
+		$this->_search_btn_label = __('Venue Categories', 'event_espresso');
1319
+		$this->display_admin_list_table_page_with_sidebar();
1320
+	}
1321
+
1322
+
1323
+	protected function _category_details($view)
1324
+	{
1325
+
1326
+		// load formatter helper
1327
+		// load field generator helper
1328
+
1329
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1330
+		$this->_set_add_edit_form_tags($route);
1331
+
1332
+		$this->_set_category_object();
1333
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1334
+
1335
+		$delete_action = 'delete_category';
1336
+
1337
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'category_list'), $this->_admin_base_url);
1338
+
1339
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1340
+
1341
+		// take care of contents
1342
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1343
+		$this->display_admin_page_with_sidebar();
1344
+	}
1345
+
1346
+
1347
+	protected function _category_details_content()
1348
+	{
1349
+		$editor_args['category_desc'] = array(
1350
+			'type'          => 'wp_editor',
1351
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1352
+			'class'         => 'my_editor_custom',
1353
+			'wpeditor_args' => array('media_buttons' => false),
1354
+		);
1355
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1356
+
1357
+		$all_terms = get_terms(
1358
+			array('espresso_venue_categories'),
1359
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
1360
+		);
1361
+
1362
+		// setup category select for term parents.
1363
+		$category_select_values[] = array(
1364
+			'text' => __('No Parent', 'event_espresso'),
1365
+			'id'   => 0,
1366
+		);
1367
+		foreach ($all_terms as $term) {
1368
+			$category_select_values[] = array(
1369
+				'text' => $term->name,
1370
+				'id'   => $term->term_id,
1371
+			);
1372
+		}
1373
+
1374
+		$category_select = EEH_Form_Fields::select_input(
1375
+			'category_parent',
1376
+			$category_select_values,
1377
+			$this->_category->parent
1378
+		);
1379
+		$template_args = array(
1380
+			'category'                 => $this->_category,
1381
+			'category_select'          => $category_select,
1382
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1383
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1384
+			'disable'                  => '',
1385
+			'disabled_message'         => false,
1386
+		);
1387
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1388
+		return EEH_Template::display_template($template, $template_args, true);
1389
+	}
1390
+
1391
+
1392
+	protected function _delete_categories()
1393
+	{
1394
+		$cat_ids = isset($this->_req_data['VEN_CAT_ID']) ? (array) $this->_req_data['VEN_CAT_ID']
1395
+			: (array) $this->_req_data['category_id'];
1396
+
1397
+		foreach ($cat_ids as $cat_id) {
1398
+			$this->_delete_category($cat_id);
1399
+		}
1400
+
1401
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1402
+		$query_args = array(
1403
+			'action' => 'category_list',
1404
+		);
1405
+		$this->_redirect_after_action(0, '', '', $query_args);
1406
+	}
1407
+
1408
+
1409
+	protected function _delete_category($cat_id)
1410
+	{
1411
+		$cat_id = absint($cat_id);
1412
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1413
+	}
1414
+
1415
+
1416
+	protected function _insert_or_update_category($new_category)
1417
+	{
1418
+
1419
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1420
+		$success = 0; // we already have a success message so lets not send another.
1421
+		if ($cat_id) {
1422
+			$query_args = array(
1423
+				'action'     => 'edit_category',
1424
+				'VEN_CAT_ID' => $cat_id,
1425
+			);
1426
+		} else {
1427
+			$query_args = array('action' => 'add_category');
1428
+		}
1429
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1430
+	}
1431
+
1432
+
1433
+	private function _insert_category($update = false)
1434
+	{
1435
+		$cat_id = $update ? $this->_req_data['VEN_CAT_ID'] : '';
1436
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
1437
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
1438
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
1439
+
1440
+		if (empty($category_name)) {
1441
+			$msg = __('You must add a name for the category.', 'event_espresso');
1442
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1443
+			return false;
1444
+		}
1445
+
1446
+
1447
+		$term_args = array(
1448
+			'name'        => $category_name,
1449
+			'description' => $category_desc,
1450
+			'parent'      => $category_parent,
1451
+		);
1452
+
1453
+		$insert_ids = $update
1454
+			? wp_update_term($cat_id, 'espresso_venue_categories', $term_args)
1455
+			: wp_insert_term(
1456
+				$category_name,
1457
+				'espresso_venue_categories',
1458
+				$term_args
1459
+			);
1460
+
1461
+		if (! is_array($insert_ids)) {
1462
+			$msg = __('An error occurred and the category has not been saved to the database.', 'event_espresso');
1463
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1464
+		} else {
1465
+			$cat_id = $insert_ids['term_id'];
1466
+			$msg = sprintf(__('The category %s was successfully created', 'event_espresso'), $category_name);
1467
+			EE_Error::add_success($msg);
1468
+		}
1469
+
1470
+		return $cat_id;
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * TODO handle category exports()
1476
+	 *
1477
+	 * @return file export
1478
+	 */
1479
+	protected function _categories_export()
1480
+	{
1481
+
1482
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1483
+		$new_request_args = array(
1484
+			'export'       => 'report',
1485
+			'action'       => 'categories',
1486
+			'category_ids' => $this->_req_data['VEN_CAT_ID'],
1487
+		);
1488
+
1489
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
1490
+
1491
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1492
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1493
+			$EE_Export = EE_Export::instance($this->_req_data);
1494
+			$EE_Export->export();
1495
+		}
1496
+	}
1497
+
1498
+
1499
+	protected function _import_categories()
1500
+	{
1501
+
1502
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1503
+		EE_Import::instance()->import();
1504
+	}
1505
+
1506
+
1507
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1508
+	{
1509
+
1510
+		// testing term stuff
1511
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
1512
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1513
+		$limit = ($current_page - 1) * $per_page;
1514
+		$where = array('taxonomy' => 'espresso_venue_categories');
1515
+		if (isset($this->_req_data['s'])) {
1516
+			$sstr = '%' . $this->_req_data['s'] . '%';
1517
+			$where['OR'] = array(
1518
+				'Term.name'   => array('LIKE', $sstr),
1519
+				'description' => array('LIKE', $sstr),
1520
+			);
1521
+		}
1522
+
1523
+		$query_params = array(
1524
+			$where,
1525
+			'order_by'   => array($orderby => $order),
1526
+			'limit'      => $limit . ',' . $per_page,
1527
+			'force_join' => array('Term'),
1528
+		);
1529
+
1530
+		$categories = $count ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1531
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1532
+
1533
+		return $categories;
1534
+	}
1535
+
1536
+
1537
+	/* end category stuff */
1538
+	/**************/
1539 1539
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2677 added lines, -2677 removed lines patch added patch discarded remove patch
@@ -12,2681 +12,2681 @@
 block discarded – undo
12 12
 class Events_Admin_Page extends EE_Admin_Page_CPT
13 13
 {
14 14
 
15
-    /**
16
-     * This will hold the event object for event_details screen.
17
-     *
18
-     * @access protected
19
-     * @var EE_Event $_event
20
-     */
21
-    protected $_event;
22
-
23
-
24
-    /**
25
-     * This will hold the category object for category_details screen.
26
-     *
27
-     * @var stdClass $_category
28
-     */
29
-    protected $_category;
30
-
31
-
32
-    /**
33
-     * This will hold the event model instance
34
-     *
35
-     * @var EEM_Event $_event_model
36
-     */
37
-    protected $_event_model;
38
-
39
-
40
-    /**
41
-     * @var EE_Event
42
-     */
43
-    protected $_cpt_model_obj = false;
44
-
45
-
46
-    /**
47
-     * Initialize page props for this admin page group.
48
-     */
49
-    protected function _init_page_props()
50
-    {
51
-        $this->page_slug = EVENTS_PG_SLUG;
52
-        $this->page_label = EVENTS_LABEL;
53
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
54
-        $this->_admin_base_path = EVENTS_ADMIN;
55
-        $this->_cpt_model_names = array(
56
-            'create_new' => 'EEM_Event',
57
-            'edit'       => 'EEM_Event',
58
-        );
59
-        $this->_cpt_edit_routes = array(
60
-            'espresso_events' => 'edit',
61
-        );
62
-        add_action(
63
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
64
-            array($this, 'verify_event_edit'),
65
-            10,
66
-            2
67
-        );
68
-    }
69
-
70
-
71
-    /**
72
-     * Sets the ajax hooks used for this admin page group.
73
-     */
74
-    protected function _ajax_hooks()
75
-    {
76
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
77
-    }
78
-
79
-
80
-    /**
81
-     * Sets the page properties for this admin page group.
82
-     */
83
-    protected function _define_page_props()
84
-    {
85
-        $this->_admin_page_title = EVENTS_LABEL;
86
-        $this->_labels = array(
87
-            'buttons'      => array(
88
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
89
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
90
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
91
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
92
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
93
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
94
-            ),
95
-            'editor_title' => array(
96
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
97
-            ),
98
-            'publishbox'   => array(
99
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
100
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
101
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
102
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
103
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
104
-            ),
105
-        );
106
-    }
107
-
108
-
109
-    /**
110
-     * Sets the page routes property for this admin page group.
111
-     */
112
-    protected function _set_page_routes()
113
-    {
114
-        // load formatter helper
115
-        // load field generator helper
116
-        // is there a evt_id in the request?
117
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
118
-            ? $this->_req_data['EVT_ID']
119
-            : 0;
120
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
121
-        $this->_page_routes = array(
122
-            'default'                       => array(
123
-                'func'       => '_events_overview_list_table',
124
-                'capability' => 'ee_read_events',
125
-            ),
126
-            'create_new'                    => array(
127
-                'func'       => '_create_new_cpt_item',
128
-                'capability' => 'ee_edit_events',
129
-            ),
130
-            'edit'                          => array(
131
-                'func'       => '_edit_cpt_item',
132
-                'capability' => 'ee_edit_event',
133
-                'obj_id'     => $evt_id,
134
-            ),
135
-            'copy_event'                    => array(
136
-                'func'       => '_copy_events',
137
-                'capability' => 'ee_edit_event',
138
-                'obj_id'     => $evt_id,
139
-                'noheader'   => true,
140
-            ),
141
-            'trash_event'                   => array(
142
-                'func'       => '_trash_or_restore_event',
143
-                'args'       => array('event_status' => 'trash'),
144
-                'capability' => 'ee_delete_event',
145
-                'obj_id'     => $evt_id,
146
-                'noheader'   => true,
147
-            ),
148
-            'trash_events'                  => array(
149
-                'func'       => '_trash_or_restore_events',
150
-                'args'       => array('event_status' => 'trash'),
151
-                'capability' => 'ee_delete_events',
152
-                'noheader'   => true,
153
-            ),
154
-            'restore_event'                 => array(
155
-                'func'       => '_trash_or_restore_event',
156
-                'args'       => array('event_status' => 'draft'),
157
-                'capability' => 'ee_delete_event',
158
-                'obj_id'     => $evt_id,
159
-                'noheader'   => true,
160
-            ),
161
-            'restore_events'                => array(
162
-                'func'       => '_trash_or_restore_events',
163
-                'args'       => array('event_status' => 'draft'),
164
-                'capability' => 'ee_delete_events',
165
-                'noheader'   => true,
166
-            ),
167
-            'delete_event'                  => array(
168
-                'func'       => '_delete_event',
169
-                'capability' => 'ee_delete_event',
170
-                'obj_id'     => $evt_id,
171
-                'noheader'   => true,
172
-            ),
173
-            'delete_events'                 => array(
174
-                'func'       => '_delete_events',
175
-                'capability' => 'ee_delete_events',
176
-                'noheader'   => true,
177
-            ),
178
-            'view_report'                   => array(
179
-                'func'      => '_view_report',
180
-                'capablity' => 'ee_edit_events',
181
-            ),
182
-            'default_event_settings'        => array(
183
-                'func'       => '_default_event_settings',
184
-                'capability' => 'manage_options',
185
-            ),
186
-            'update_default_event_settings' => array(
187
-                'func'       => '_update_default_event_settings',
188
-                'capability' => 'manage_options',
189
-                'noheader'   => true,
190
-            ),
191
-            'template_settings'             => array(
192
-                'func'       => '_template_settings',
193
-                'capability' => 'manage_options',
194
-            ),
195
-            // event category tab related
196
-            'add_category'                  => array(
197
-                'func'       => '_category_details',
198
-                'capability' => 'ee_edit_event_category',
199
-                'args'       => array('add'),
200
-            ),
201
-            'edit_category'                 => array(
202
-                'func'       => '_category_details',
203
-                'capability' => 'ee_edit_event_category',
204
-                'args'       => array('edit'),
205
-            ),
206
-            'delete_categories'             => array(
207
-                'func'       => '_delete_categories',
208
-                'capability' => 'ee_delete_event_category',
209
-                'noheader'   => true,
210
-            ),
211
-            'delete_category'               => array(
212
-                'func'       => '_delete_categories',
213
-                'capability' => 'ee_delete_event_category',
214
-                'noheader'   => true,
215
-            ),
216
-            'insert_category'               => array(
217
-                'func'       => '_insert_or_update_category',
218
-                'args'       => array('new_category' => true),
219
-                'capability' => 'ee_edit_event_category',
220
-                'noheader'   => true,
221
-            ),
222
-            'update_category'               => array(
223
-                'func'       => '_insert_or_update_category',
224
-                'args'       => array('new_category' => false),
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ),
228
-            'category_list'                 => array(
229
-                'func'       => '_category_list_table',
230
-                'capability' => 'ee_manage_event_categories',
231
-            ),
232
-        );
233
-    }
234
-
235
-
236
-    /**
237
-     * Set the _page_config property for this admin page group.
238
-     */
239
-    protected function _set_page_config()
240
-    {
241
-        $this->_page_config = array(
242
-            'default'                => array(
243
-                'nav'           => array(
244
-                    'label' => esc_html__('Overview', 'event_espresso'),
245
-                    'order' => 10,
246
-                ),
247
-                'list_table'    => 'Events_Admin_List_Table',
248
-                'help_tabs'     => array(
249
-                    'events_overview_help_tab'                       => array(
250
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
251
-                        'filename' => 'events_overview',
252
-                    ),
253
-                    'events_overview_table_column_headings_help_tab' => array(
254
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
255
-                        'filename' => 'events_overview_table_column_headings',
256
-                    ),
257
-                    'events_overview_filters_help_tab'               => array(
258
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
259
-                        'filename' => 'events_overview_filters',
260
-                    ),
261
-                    'events_overview_view_help_tab'                  => array(
262
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
263
-                        'filename' => 'events_overview_views',
264
-                    ),
265
-                    'events_overview_other_help_tab'                 => array(
266
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
267
-                        'filename' => 'events_overview_other',
268
-                    ),
269
-                ),
270
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
271
-                // 'help_tour'     => array(
272
-                //     'Event_Overview_Help_Tour',
273
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
274
-                // ),
275
-                'qtips'         => array(
276
-                    'EE_Event_List_Table_Tips',
277
-                ),
278
-                'require_nonce' => false,
279
-            ),
280
-            'create_new'             => array(
281
-                'nav'           => array(
282
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
283
-                    'order'      => 5,
284
-                    'persistent' => false,
285
-                ),
286
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
287
-                'help_tabs'     => array(
288
-                    'event_editor_help_tab'                            => array(
289
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
290
-                        'filename' => 'event_editor',
291
-                    ),
292
-                    'event_editor_title_richtexteditor_help_tab'       => array(
293
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
294
-                        'filename' => 'event_editor_title_richtexteditor',
295
-                    ),
296
-                    'event_editor_venue_details_help_tab'              => array(
297
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
298
-                        'filename' => 'event_editor_venue_details',
299
-                    ),
300
-                    'event_editor_event_datetimes_help_tab'            => array(
301
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
302
-                        'filename' => 'event_editor_event_datetimes',
303
-                    ),
304
-                    'event_editor_event_tickets_help_tab'              => array(
305
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
306
-                        'filename' => 'event_editor_event_tickets',
307
-                    ),
308
-                    'event_editor_event_registration_options_help_tab' => array(
309
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
310
-                        'filename' => 'event_editor_event_registration_options',
311
-                    ),
312
-                    'event_editor_tags_categories_help_tab'            => array(
313
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
314
-                        'filename' => 'event_editor_tags_categories',
315
-                    ),
316
-                    'event_editor_questions_registrants_help_tab'      => array(
317
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
318
-                        'filename' => 'event_editor_questions_registrants',
319
-                    ),
320
-                    'event_editor_save_new_event_help_tab'             => array(
321
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
322
-                        'filename' => 'event_editor_save_new_event',
323
-                    ),
324
-                    'event_editor_other_help_tab'                      => array(
325
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
326
-                        'filename' => 'event_editor_other',
327
-                    ),
328
-                ),
329
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
330
-                // 'help_tour'     => array(
331
-                //     'Event_Editor_Help_Tour',
332
-                // ),
333
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
-                'require_nonce' => false,
335
-            ),
336
-            'edit'                   => array(
337
-                'nav'           => array(
338
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
339
-                    'order'      => 5,
340
-                    'persistent' => false,
341
-                    'url'        => isset($this->_req_data['post'])
342
-                        ? EE_Admin_Page::add_query_args_and_nonce(
343
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
-                            $this->_current_page_view_url
345
-                        )
346
-                        : $this->_admin_base_url,
347
-                ),
348
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
-                'help_tabs'     => array(
350
-                    'event_editor_help_tab'                            => array(
351
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
352
-                        'filename' => 'event_editor',
353
-                    ),
354
-                    'event_editor_title_richtexteditor_help_tab'       => array(
355
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
-                        'filename' => 'event_editor_title_richtexteditor',
357
-                    ),
358
-                    'event_editor_venue_details_help_tab'              => array(
359
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
-                        'filename' => 'event_editor_venue_details',
361
-                    ),
362
-                    'event_editor_event_datetimes_help_tab'            => array(
363
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
-                        'filename' => 'event_editor_event_datetimes',
365
-                    ),
366
-                    'event_editor_event_tickets_help_tab'              => array(
367
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
-                        'filename' => 'event_editor_event_tickets',
369
-                    ),
370
-                    'event_editor_event_registration_options_help_tab' => array(
371
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_registration_options',
373
-                    ),
374
-                    'event_editor_tags_categories_help_tab'            => array(
375
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
-                        'filename' => 'event_editor_tags_categories',
377
-                    ),
378
-                    'event_editor_questions_registrants_help_tab'      => array(
379
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
-                        'filename' => 'event_editor_questions_registrants',
381
-                    ),
382
-                    'event_editor_save_new_event_help_tab'             => array(
383
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
384
-                        'filename' => 'event_editor_save_new_event',
385
-                    ),
386
-                    'event_editor_other_help_tab'                      => array(
387
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
388
-                        'filename' => 'event_editor_other',
389
-                    ),
390
-                ),
391
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
392
-                'require_nonce' => false,
393
-            ),
394
-            'default_event_settings' => array(
395
-                'nav'           => array(
396
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
397
-                    'order' => 40,
398
-                ),
399
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
400
-                'labels'        => array(
401
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
402
-                ),
403
-                'help_tabs'     => array(
404
-                    'default_settings_help_tab'        => array(
405
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
406
-                        'filename' => 'events_default_settings',
407
-                    ),
408
-                    'default_settings_status_help_tab' => array(
409
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
410
-                        'filename' => 'events_default_settings_status',
411
-                    ),
412
-                    'default_maximum_tickets_help_tab' => array(
413
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
414
-                        'filename' => 'events_default_settings_max_tickets',
415
-                    ),
416
-                ),
417
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
418
-                // 'help_tour'     => array('Event_Default_Settings_Help_Tour'),
419
-                'require_nonce' => false,
420
-            ),
421
-            // template settings
422
-            'template_settings'      => array(
423
-                'nav'           => array(
424
-                    'label' => esc_html__('Templates', 'event_espresso'),
425
-                    'order' => 30,
426
-                ),
427
-                'metaboxes'     => $this->_default_espresso_metaboxes,
428
-                'help_tabs'     => array(
429
-                    'general_settings_templates_help_tab' => array(
430
-                        'title'    => esc_html__('Templates', 'event_espresso'),
431
-                        'filename' => 'general_settings_templates',
432
-                    ),
433
-                ),
434
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
435
-                // 'help_tour'     => array('Templates_Help_Tour'),
436
-                'require_nonce' => false,
437
-            ),
438
-            // event category stuff
439
-            'add_category'           => array(
440
-                'nav'           => array(
441
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
442
-                    'order'      => 15,
443
-                    'persistent' => false,
444
-                ),
445
-                'help_tabs'     => array(
446
-                    'add_category_help_tab' => array(
447
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
448
-                        'filename' => 'events_add_category',
449
-                    ),
450
-                ),
451
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
452
-                // 'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
-                'metaboxes'     => array('_publish_post_box'),
454
-                'require_nonce' => false,
455
-            ),
456
-            'edit_category'          => array(
457
-                'nav'           => array(
458
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
459
-                    'order'      => 15,
460
-                    'persistent' => false,
461
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
-                        ? add_query_arg(
463
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
-                            $this->_current_page_view_url
465
-                        )
466
-                        : $this->_admin_base_url,
467
-                ),
468
-                'help_tabs'     => array(
469
-                    'edit_category_help_tab' => array(
470
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
-                        'filename' => 'events_edit_category',
472
-                    ),
473
-                ),
474
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
-                'metaboxes'     => array('_publish_post_box'),
476
-                'require_nonce' => false,
477
-            ),
478
-            'category_list'          => array(
479
-                'nav'           => array(
480
-                    'label' => esc_html__('Categories', 'event_espresso'),
481
-                    'order' => 20,
482
-                ),
483
-                'list_table'    => 'Event_Categories_Admin_List_Table',
484
-                'help_tabs'     => array(
485
-                    'events_categories_help_tab'                       => array(
486
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
487
-                        'filename' => 'events_categories',
488
-                    ),
489
-                    'events_categories_table_column_headings_help_tab' => array(
490
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
-                        'filename' => 'events_categories_table_column_headings',
492
-                    ),
493
-                    'events_categories_view_help_tab'                  => array(
494
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
-                        'filename' => 'events_categories_views',
496
-                    ),
497
-                    'events_categories_other_help_tab'                 => array(
498
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
-                        'filename' => 'events_categories_other',
500
-                    ),
501
-                ),
502
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
503
-                // 'help_tour'     => array(
504
-                //     'Event_Categories_Help_Tour',
505
-                // ),
506
-                'metaboxes'     => $this->_default_espresso_metaboxes,
507
-                'require_nonce' => false,
508
-            ),
509
-        );
510
-    }
511
-
512
-
513
-    /**
514
-     * Used to register any global screen options if necessary for every route in this admin page group.
515
-     */
516
-    protected function _add_screen_options()
517
-    {
518
-    }
519
-
520
-
521
-    /**
522
-     * Implementing the screen options for the 'default' route.
523
-     */
524
-    protected function _add_screen_options_default()
525
-    {
526
-        $this->_per_page_screen_option();
527
-    }
528
-
529
-
530
-    /**
531
-     * Implementing screen options for the category list route.
532
-     */
533
-    protected function _add_screen_options_category_list()
534
-    {
535
-        $page_title = $this->_admin_page_title;
536
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
537
-        $this->_per_page_screen_option();
538
-        $this->_admin_page_title = $page_title;
539
-    }
540
-
541
-
542
-    /**
543
-     * Used to register any global feature pointers for the admin page group.
544
-     */
545
-    protected function _add_feature_pointers()
546
-    {
547
-    }
548
-
549
-
550
-    /**
551
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
552
-     */
553
-    public function load_scripts_styles()
554
-    {
555
-        wp_register_style(
556
-            'events-admin-css',
557
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
558
-            array(),
559
-            EVENT_ESPRESSO_VERSION
560
-        );
561
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
562
-        wp_enqueue_style('events-admin-css');
563
-        wp_enqueue_style('ee-cat-admin');
564
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
565
-        // registers for all views
566
-        // scripts
567
-        wp_register_script(
568
-            'event_editor_js',
569
-            EVENTS_ASSETS_URL . 'event_editor.js',
570
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
571
-            EVENT_ESPRESSO_VERSION,
572
-            true
573
-        );
574
-    }
575
-
576
-
577
-    /**
578
-     * Enqueuing scripts and styles specific to this view
579
-     */
580
-    public function load_scripts_styles_create_new()
581
-    {
582
-        $this->load_scripts_styles_edit();
583
-    }
584
-
585
-
586
-    /**
587
-     * Enqueuing scripts and styles specific to this view
588
-     */
589
-    public function load_scripts_styles_edit()
590
-    {
591
-        // styles
592
-        wp_enqueue_style('espresso-ui-theme');
593
-        wp_register_style(
594
-            'event-editor-css',
595
-            EVENTS_ASSETS_URL . 'event-editor.css',
596
-            array('ee-admin-css'),
597
-            EVENT_ESPRESSO_VERSION
598
-        );
599
-        wp_enqueue_style('event-editor-css');
600
-        // scripts
601
-        wp_register_script(
602
-            'event-datetime-metabox',
603
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
604
-            array('event_editor_js', 'ee-datepicker'),
605
-            EVENT_ESPRESSO_VERSION
606
-        );
607
-        wp_enqueue_script('event-datetime-metabox');
608
-    }
609
-
610
-
611
-    /**
612
-     * Populating the _views property for the category list table view.
613
-     */
614
-    protected function _set_list_table_views_category_list()
615
-    {
616
-        $this->_views = array(
617
-            'all' => array(
618
-                'slug'        => 'all',
619
-                'label'       => esc_html__('All', 'event_espresso'),
620
-                'count'       => 0,
621
-                'bulk_action' => array(
622
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
623
-                ),
624
-            ),
625
-        );
626
-    }
627
-
628
-
629
-    /**
630
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
631
-     */
632
-    public function admin_init()
633
-    {
634
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
635
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
636
-            'event_espresso'
637
-        );
638
-    }
639
-
640
-
641
-    /**
642
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
643
-     * group.
644
-     */
645
-    public function admin_notices()
646
-    {
647
-    }
648
-
649
-
650
-    /**
651
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
-     * this admin page group.
653
-     */
654
-    public function admin_footer_scripts()
655
-    {
656
-    }
657
-
658
-
659
-    /**
660
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
661
-     * warning (via EE_Error::add_error());
662
-     *
663
-     * @param  EE_Event $event Event object
664
-     * @param string    $req_type
665
-     * @return void
666
-     * @throws EE_Error
667
-     * @access public
668
-     */
669
-    public function verify_event_edit($event = null, $req_type = '')
670
-    {
671
-        // don't need to do this when processing
672
-        if (! empty($req_type)) {
673
-            return;
674
-        }
675
-        // no event?
676
-        if (empty($event)) {
677
-            // set event
678
-            $event = $this->_cpt_model_obj;
679
-        }
680
-        // STILL no event?
681
-        if (! $event instanceof EE_Event) {
682
-            return;
683
-        }
684
-        $orig_status = $event->status();
685
-        // first check if event is active.
686
-        if ($orig_status === EEM_Event::cancelled
687
-            || $orig_status === EEM_Event::postponed
688
-            || $event->is_expired()
689
-            || $event->is_inactive()
690
-        ) {
691
-            return;
692
-        }
693
-        // made it here so it IS active... next check that any of the tickets are sold.
694
-        if ($event->is_sold_out(true)) {
695
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
696
-                EE_Error::add_attention(
697
-                    sprintf(
698
-                        esc_html__(
699
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
700
-                            'event_espresso'
701
-                        ),
702
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
703
-                    )
704
-                );
705
-            }
706
-            return;
707
-        } elseif ($orig_status === EEM_Event::sold_out) {
708
-            EE_Error::add_attention(
709
-                sprintf(
710
-                    esc_html__(
711
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
712
-                        'event_espresso'
713
-                    ),
714
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
715
-                )
716
-            );
717
-        }
718
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
719
-        if (! $event->tickets_on_sale()) {
720
-            return;
721
-        }
722
-        // made it here so show warning
723
-        $this->_edit_event_warning();
724
-    }
725
-
726
-
727
-    /**
728
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
729
-     * When needed, hook this into a EE_Error::add_error() notice.
730
-     *
731
-     * @access protected
732
-     * @return void
733
-     */
734
-    protected function _edit_event_warning()
735
-    {
736
-        // we don't want to add warnings during these requests
737
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
738
-            return;
739
-        }
740
-        EE_Error::add_attention(
741
-            sprintf(
742
-                esc_html__(
743
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
744
-                    'event_espresso'
745
-                ),
746
-                '<a class="espresso-help-tab-lnk">',
747
-                '</a>'
748
-            )
749
-        );
750
-    }
751
-
752
-
753
-    /**
754
-     * When a user is creating a new event, notify them if they haven't set their timezone.
755
-     * Otherwise, do the normal logic
756
-     *
757
-     * @return string
758
-     * @throws \EE_Error
759
-     */
760
-    protected function _create_new_cpt_item()
761
-    {
762
-        $has_timezone_string = get_option('timezone_string');
763
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
764
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
-            EE_Error::add_attention(
766
-                sprintf(
767
-                    __(
768
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
-                        'event_espresso'
770
-                    ),
771
-                    '<br>',
772
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
-                    . '</select>',
775
-                    '<button class="button button-secondary timezone-submit">',
776
-                    '</button><span class="spinner"></span>'
777
-                ),
778
-                __FILE__,
779
-                __FUNCTION__,
780
-                __LINE__
781
-            );
782
-        }
783
-        return parent::_create_new_cpt_item();
784
-    }
785
-
786
-
787
-    /**
788
-     * Sets the _views property for the default route in this admin page group.
789
-     */
790
-    protected function _set_list_table_views_default()
791
-    {
792
-        $this->_views = array(
793
-            'all'   => array(
794
-                'slug'        => 'all',
795
-                'label'       => esc_html__('View All Events', 'event_espresso'),
796
-                'count'       => 0,
797
-                'bulk_action' => array(
798
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
-                ),
800
-            ),
801
-            'draft' => array(
802
-                'slug'        => 'draft',
803
-                'label'       => esc_html__('Draft', 'event_espresso'),
804
-                'count'       => 0,
805
-                'bulk_action' => array(
806
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
-                ),
808
-            ),
809
-        );
810
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
-            $this->_views['trash'] = array(
812
-                'slug'        => 'trash',
813
-                'label'       => esc_html__('Trash', 'event_espresso'),
814
-                'count'       => 0,
815
-                'bulk_action' => array(
816
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
-                ),
819
-            );
820
-        }
821
-    }
822
-
823
-
824
-    /**
825
-     * Provides the legend item array for the default list table view.
826
-     *
827
-     * @return array
828
-     */
829
-    protected function _event_legend_items()
830
-    {
831
-        $items = array(
832
-            'view_details'   => array(
833
-                'class' => 'dashicons dashicons-search',
834
-                'desc'  => esc_html__('View Event', 'event_espresso'),
835
-            ),
836
-            'edit_event'     => array(
837
-                'class' => 'ee-icon ee-icon-calendar-edit',
838
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
-            ),
840
-            'view_attendees' => array(
841
-                'class' => 'dashicons dashicons-groups',
842
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
-            ),
844
-        );
845
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
-        $statuses = array(
847
-            'sold_out_status'  => array(
848
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
-            ),
851
-            'active_status'    => array(
852
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
-            ),
855
-            'upcoming_status'  => array(
856
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
-            ),
859
-            'postponed_status' => array(
860
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
-            ),
863
-            'cancelled_status' => array(
864
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
-            ),
867
-            'expired_status'   => array(
868
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
-            ),
871
-            'inactive_status'  => array(
872
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
-            ),
875
-        );
876
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
-        return array_merge($items, $statuses);
878
-    }
879
-
880
-
881
-    /**
882
-     * @return EEM_Event
883
-     */
884
-    private function _event_model()
885
-    {
886
-        if (! $this->_event_model instanceof EEM_Event) {
887
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
888
-        }
889
-        return $this->_event_model;
890
-    }
891
-
892
-
893
-    /**
894
-     * Adds extra buttons to the WP CPT permalink field row.
895
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
896
-     *
897
-     * @param  string $return    the current html
898
-     * @param  int    $id        the post id for the page
899
-     * @param  string $new_title What the title is
900
-     * @param  string $new_slug  what the slug is
901
-     * @return string            The new html string for the permalink area
902
-     */
903
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
904
-    {
905
-        // make sure this is only when editing
906
-        if (! empty($id)) {
907
-            $post = get_post($id);
908
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
909
-                       . esc_html__('Shortcode', 'event_espresso')
910
-                       . '</a> ';
911
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
912
-                       . $post->ID
913
-                       . ']">';
914
-        }
915
-        return $return;
916
-    }
917
-
918
-
919
-    /**
920
-     * _events_overview_list_table
921
-     * This contains the logic for showing the events_overview list
922
-     *
923
-     * @access protected
924
-     * @return void
925
-     * @throws \EE_Error
926
-     */
927
-    protected function _events_overview_list_table()
928
-    {
929
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
930
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
931
-            ? (array) $this->_template_args['after_list_table']
932
-            : array();
933
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
934
-                . EEH_Template::get_button_or_link(
935
-                    get_post_type_archive_link('espresso_events'),
936
-                    esc_html__("View Event Archive Page", "event_espresso"),
937
-                    'button'
938
-                );
939
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
940
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
941
-            'create_new',
942
-            'add',
943
-            array(),
944
-            'add-new-h2'
945
-        );
946
-        $this->display_admin_list_table_page_with_no_sidebar();
947
-    }
948
-
949
-
950
-    /**
951
-     * this allows for extra misc actions in the default WP publish box
952
-     *
953
-     * @return void
954
-     */
955
-    public function extra_misc_actions_publish_box()
956
-    {
957
-        $this->_generate_publish_box_extra_content();
958
-    }
959
-
960
-
961
-    /**
962
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
963
-     * saved.
964
-     * Typically you would use this to save any additional data.
965
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
966
-     * ALSO very important.  When a post transitions from scheduled to published,
967
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
968
-     * other meta saves. So MAKE sure that you handle this accordingly.
969
-     *
970
-     * @access protected
971
-     * @abstract
972
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
973
-     * @param  object $post    The post object of the cpt that was saved.
974
-     * @return void
975
-     * @throws \EE_Error
976
-     */
977
-    protected function _insert_update_cpt_item($post_id, $post)
978
-    {
979
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
980
-            // get out we're not processing an event save.
981
-            return;
982
-        }
983
-        $event_values = array(
984
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
985
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
986
-            'EVT_additional_limit'            => min(
987
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
988
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
989
-            ),
990
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
991
-                ? $this->_req_data['EVT_default_registration_status']
992
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
993
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
994
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
995
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
996
-                ? $this->_req_data['timezone_string'] : null,
997
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
998
-                ? $this->_req_data['externalURL'] : null,
999
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1000
-                ? $this->_req_data['event_phone'] : null,
1001
-        );
1002
-        // update event
1003
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1004
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1005
-        $get_one_where = array(
1006
-            $this->_event_model()->primary_key_name() => $post_id,
1007
-            'OR'                                      => array(
1008
-                'status'   => $post->post_status,
1009
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1010
-                // but the returned object here has a status of "publish", so use the original post status as well
1011
-                'status*1' => $this->_req_data['original_post_status'],
1012
-            ),
1013
-        );
1014
-        $event = $this->_event_model()->get_one(array($get_one_where));
1015
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1016
-        $event_update_callbacks = apply_filters(
1017
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1018
-            array(
1019
-                array($this, '_default_venue_update'),
1020
-                array($this, '_default_tickets_update'),
1021
-            )
1022
-        );
1023
-        $att_success = true;
1024
-        foreach ($event_update_callbacks as $e_callback) {
1025
-            $_success = is_callable($e_callback)
1026
-                ? call_user_func($e_callback, $event, $this->_req_data)
1027
-                : false;
1028
-            // if ANY of these updates fail then we want the appropriate global error message
1029
-            $att_success = ! $att_success ? $att_success : $_success;
1030
-        }
1031
-        // any errors?
1032
-        if ($success && false === $att_success) {
1033
-            EE_Error::add_error(
1034
-                esc_html__(
1035
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1036
-                    'event_espresso'
1037
-                ),
1038
-                __FILE__,
1039
-                __FUNCTION__,
1040
-                __LINE__
1041
-            );
1042
-        } elseif ($success === false) {
1043
-            EE_Error::add_error(
1044
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1045
-                __FILE__,
1046
-                __FUNCTION__,
1047
-                __LINE__
1048
-            );
1049
-        }
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     * @see parent::restore_item()
1055
-     * @param int $post_id
1056
-     * @param int $revision_id
1057
-     */
1058
-    protected function _restore_cpt_item($post_id, $revision_id)
1059
-    {
1060
-        // copy existing event meta to new post
1061
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1062
-        if ($post_evt instanceof EE_Event) {
1063
-            // meta revision restore
1064
-            $post_evt->restore_revision($revision_id);
1065
-            // related objs restore
1066
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1067
-        }
1068
-    }
1069
-
1070
-
1071
-    /**
1072
-     * Attach the venue to the Event
1073
-     *
1074
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1075
-     * @param  array     $data   The request data from the form
1076
-     * @return bool           Success or fail.
1077
-     */
1078
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1079
-    {
1080
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1081
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1082
-        $rows_affected = null;
1083
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1084
-        // very important.  If we don't have a venue name...
1085
-        // then we'll get out because not necessary to create empty venue
1086
-        if (empty($data['venue_title'])) {
1087
-            return false;
1088
-        }
1089
-        $venue_array = array(
1090
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1091
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1092
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1093
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1094
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1095
-                : null,
1096
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1097
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1098
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1099
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1100
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1101
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1102
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1103
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1104
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1105
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1106
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1107
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1108
-            'status'              => 'publish',
1109
-        );
1110
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1111
-        if (! empty($venue_id)) {
1112
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1113
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1114
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1115
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1116
-            return $rows_affected > 0 ? true : false;
1117
-        } else {
1118
-            // we insert the venue
1119
-            $venue_id = $venue_model->insert($venue_array);
1120
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1121
-            return ! empty($venue_id) ? true : false;
1122
-        }
1123
-        // when we have the ancestor come in it's already been handled by the revision save.
1124
-    }
1125
-
1126
-
1127
-    /**
1128
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1129
-     *
1130
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1131
-     * @param  array    $data   The request data from the form
1132
-     * @return array
1133
-     */
1134
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1135
-    {
1136
-        $success = true;
1137
-        $saved_dtt = null;
1138
-        $saved_tickets = array();
1139
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1140
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1141
-            // trim all values to ensure any excess whitespace is removed.
1142
-            $dtt = array_map('trim', $dtt);
1143
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1144
-                : $dtt['DTT_EVT_start'];
1145
-            $datetime_values = array(
1146
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1147
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1148
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1149
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1150
-                'DTT_order'     => $row,
1151
-            );
1152
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1153
-            if (! empty($dtt['DTT_ID'])) {
1154
-                $DTM = EE_Registry::instance()
1155
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1156
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1157
-                $DTM->set_date_format($incoming_date_formats[0]);
1158
-                $DTM->set_time_format($incoming_date_formats[1]);
1159
-                foreach ($datetime_values as $field => $value) {
1160
-                    $DTM->set($field, $value);
1161
-                }
1162
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1163
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1164
-            } else {
1165
-                $DTM = EE_Registry::instance()->load_class(
1166
-                    'Datetime',
1167
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1168
-                    false,
1169
-                    false
1170
-                );
1171
-                foreach ($datetime_values as $field => $value) {
1172
-                    $DTM->set($field, $value);
1173
-                }
1174
-            }
1175
-            $DTM->save();
1176
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1177
-            // load DTT helper
1178
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1179
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1180
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1181
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1182
-                $DTT->save();
1183
-            }
1184
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1185
-            $saved_dtt = $DTT;
1186
-            $success = ! $success ? $success : $DTT;
1187
-            // if ANY of these updates fail then we want the appropriate global error message.
1188
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1189
-        }
1190
-        // no dtts get deleted so we don't do any of that logic here.
1191
-        // update tickets next
1192
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1193
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1194
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1195
-            $update_prices = false;
1196
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1197
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1198
-            // trim inputs to ensure any excess whitespace is removed.
1199
-            $tkt = array_map('trim', $tkt);
1200
-            if (empty($tkt['TKT_start_date'])) {
1201
-                // let's use now in the set timezone.
1202
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1203
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1204
-            }
1205
-            if (empty($tkt['TKT_end_date'])) {
1206
-                // use the start date of the first datetime
1207
-                $dtt = $evtobj->first_datetime();
1208
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1209
-                    $incoming_date_formats[0],
1210
-                    $incoming_date_formats[1]
1211
-                );
1212
-            }
1213
-            $TKT_values = array(
1214
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1215
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1216
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1217
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1218
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1219
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1220
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1221
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1222
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1223
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1224
-                'TKT_row'         => $row,
1225
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1226
-                'TKT_price'       => $ticket_price,
1227
-            );
1228
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1229
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1230
-                $TKT_values['TKT_ID'] = 0;
1231
-                $TKT_values['TKT_is_default'] = 0;
1232
-                $TKT_values['TKT_price'] = $ticket_price;
1233
-                $update_prices = true;
1234
-            }
1235
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1236
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1237
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1238
-            if (! empty($tkt['TKT_ID'])) {
1239
-                $TKT = EE_Registry::instance()
1240
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1241
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1242
-                if ($TKT instanceof EE_Ticket) {
1243
-                    $ticket_sold = $TKT->count_related(
1244
-                        'Registration',
1245
-                        array(
1246
-                            array(
1247
-                                'STS_ID' => array(
1248
-                                    'NOT IN',
1249
-                                    array(EEM_Registration::status_id_incomplete),
1250
-                                ),
1251
-                            ),
1252
-                        )
1253
-                    ) > 0 ? true : false;
1254
-                    // let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1255
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1256
-                                      && ! $TKT->get('TKT_deleted');
1257
-                    $TKT->set_date_format($incoming_date_formats[0]);
1258
-                    $TKT->set_time_format($incoming_date_formats[1]);
1259
-                    // set new values
1260
-                    foreach ($TKT_values as $field => $value) {
1261
-                        if ($field == 'TKT_qty') {
1262
-                            $TKT->set_qty($value);
1263
-                        } else {
1264
-                            $TKT->set($field, $value);
1265
-                        }
1266
-                    }
1267
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1268
-                    if ($create_new_TKT) {
1269
-                        // archive the old ticket first
1270
-                        $TKT->set('TKT_deleted', 1);
1271
-                        $TKT->save();
1272
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1273
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1274
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1275
-                        $TKT = clone $TKT;
1276
-                        $TKT->set('TKT_ID', 0);
1277
-                        $TKT->set('TKT_deleted', 0);
1278
-                        $TKT->set('TKT_price', $ticket_price);
1279
-                        $TKT->set('TKT_sold', 0);
1280
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1281
-                        $update_prices = true;
1282
-                    }
1283
-                    // make sure price is set if it hasn't been already
1284
-                    $TKT->set('TKT_price', $ticket_price);
1285
-                }
1286
-            } else {
1287
-                // no TKT_id so a new TKT
1288
-                $TKT_values['TKT_price'] = $ticket_price;
1289
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1290
-                if ($TKT instanceof EE_Ticket) {
1291
-                    // need to reset values to properly account for the date formats
1292
-                    $TKT->set_date_format($incoming_date_formats[0]);
1293
-                    $TKT->set_time_format($incoming_date_formats[1]);
1294
-                    $TKT->set_timezone($evtobj->get_timezone());
1295
-                    // set new values
1296
-                    foreach ($TKT_values as $field => $value) {
1297
-                        if ($field == 'TKT_qty') {
1298
-                            $TKT->set_qty($value);
1299
-                        } else {
1300
-                            $TKT->set($field, $value);
1301
-                        }
1302
-                    }
1303
-                    $update_prices = true;
1304
-                }
1305
-            }
1306
-            // cap ticket qty by datetime reg limits
1307
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1308
-            // update ticket.
1309
-            $TKT->save();
1310
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1311
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1312
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1313
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1314
-                $TKT->save();
1315
-            }
1316
-            // initially let's add the ticket to the dtt
1317
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1318
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1319
-            // add prices to ticket
1320
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1321
-        }
1322
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1323
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1324
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1325
-        foreach ($tickets_removed as $id) {
1326
-            $id = absint($id);
1327
-            // get the ticket for this id
1328
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1329
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1330
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1331
-            foreach ($dtts as $dtt) {
1332
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1333
-            }
1334
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1335
-            $tkt_to_remove->delete_related_permanently('Price');
1336
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1337
-            $tkt_to_remove->delete_permanently();
1338
-        }
1339
-        return array($saved_dtt, $saved_tickets);
1340
-    }
1341
-
1342
-
1343
-    /**
1344
-     * This attaches a list of given prices to a ticket.
1345
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1346
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1347
-     * price info and prices are automatically "archived" via the ticket.
1348
-     *
1349
-     * @access  private
1350
-     * @param array     $prices     Array of prices from the form.
1351
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1352
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1353
-     * @return  void
1354
-     */
1355
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1356
-    {
1357
-        foreach ($prices as $row => $prc) {
1358
-            $PRC_values = array(
1359
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1360
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1361
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1362
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1363
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1364
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1365
-                'PRC_order'      => $row,
1366
-            );
1367
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1368
-                $PRC_values['PRC_ID'] = 0;
1369
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1370
-            } else {
1371
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1372
-                // update this price with new values
1373
-                foreach ($PRC_values as $field => $newprc) {
1374
-                    $PRC->set($field, $newprc);
1375
-                }
1376
-                $PRC->save();
1377
-            }
1378
-            $ticket->_add_relation_to($PRC, 'Price');
1379
-        }
1380
-    }
1381
-
1382
-
1383
-    /**
1384
-     * Add in our autosave ajax handlers
1385
-     *
1386
-     */
1387
-    protected function _ee_autosave_create_new()
1388
-    {
1389
-    }
1390
-
1391
-
1392
-    /**
1393
-     * More autosave handlers.
1394
-     */
1395
-    protected function _ee_autosave_edit()
1396
-    {
1397
-        return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     *    _generate_publish_box_extra_content
1403
-     */
1404
-    private function _generate_publish_box_extra_content()
1405
-    {
1406
-        // load formatter helper
1407
-        // args for getting related registrations
1408
-        $approved_query_args = array(
1409
-            array(
1410
-                'REG_deleted' => 0,
1411
-                'STS_ID'      => EEM_Registration::status_id_approved,
1412
-            ),
1413
-        );
1414
-        $not_approved_query_args = array(
1415
-            array(
1416
-                'REG_deleted' => 0,
1417
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1418
-            ),
1419
-        );
1420
-        $pending_payment_query_args = array(
1421
-            array(
1422
-                'REG_deleted' => 0,
1423
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1424
-            ),
1425
-        );
1426
-        // publish box
1427
-        $publish_box_extra_args = array(
1428
-            'view_approved_reg_url'        => add_query_arg(
1429
-                array(
1430
-                    'action'      => 'default',
1431
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1432
-                    '_reg_status' => EEM_Registration::status_id_approved,
1433
-                ),
1434
-                REG_ADMIN_URL
1435
-            ),
1436
-            'view_not_approved_reg_url'    => add_query_arg(
1437
-                array(
1438
-                    'action'      => 'default',
1439
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1440
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1441
-                ),
1442
-                REG_ADMIN_URL
1443
-            ),
1444
-            'view_pending_payment_reg_url' => add_query_arg(
1445
-                array(
1446
-                    'action'      => 'default',
1447
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1448
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1449
-                ),
1450
-                REG_ADMIN_URL
1451
-            ),
1452
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1453
-                'Registration',
1454
-                $approved_query_args
1455
-            ),
1456
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1457
-                'Registration',
1458
-                $not_approved_query_args
1459
-            ),
1460
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1461
-                'Registration',
1462
-                $pending_payment_query_args
1463
-            ),
1464
-            'misc_pub_section_class'       => apply_filters(
1465
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1466
-                'misc-pub-section'
1467
-            ),
1468
-        );
1469
-        ob_start();
1470
-        do_action(
1471
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1472
-            $this->_cpt_model_obj
1473
-        );
1474
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1475
-        // load template
1476
-        EEH_Template::display_template(
1477
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1478
-            $publish_box_extra_args
1479
-        );
1480
-    }
1481
-
1482
-
1483
-    /**
1484
-     * @return EE_Event
1485
-     */
1486
-    public function get_event_object()
1487
-    {
1488
-        return $this->_cpt_model_obj;
1489
-    }
1490
-
1491
-
1492
-
1493
-
1494
-    /** METABOXES * */
1495
-    /**
1496
-     * _register_event_editor_meta_boxes
1497
-     * add all metaboxes related to the event_editor
1498
-     *
1499
-     * @return void
1500
-     */
1501
-    protected function _register_event_editor_meta_boxes()
1502
-    {
1503
-        $this->verify_cpt_object();
1504
-        add_meta_box(
1505
-            'espresso_event_editor_tickets',
1506
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1507
-            array($this, 'ticket_metabox'),
1508
-            $this->page_slug,
1509
-            'normal',
1510
-            'high'
1511
-        );
1512
-        add_meta_box(
1513
-            'espresso_event_editor_event_options',
1514
-            esc_html__('Event Registration Options', 'event_espresso'),
1515
-            array($this, 'registration_options_meta_box'),
1516
-            $this->page_slug,
1517
-            'side',
1518
-            'default'
1519
-        );
1520
-        // NOTE: if you're looking for other metaboxes in here,
1521
-        // where a metabox has a related management page in the admin
1522
-        // you will find it setup in the related management page's "_Hooks" file.
1523
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1524
-    }
1525
-
1526
-
1527
-    /**
1528
-     * @throws DomainException
1529
-     * @throws EE_Error
1530
-     */
1531
-    public function ticket_metabox()
1532
-    {
1533
-        $existing_datetime_ids = $existing_ticket_ids = array();
1534
-        // defaults for template args
1535
-        $template_args = array(
1536
-            'existing_datetime_ids'    => '',
1537
-            'event_datetime_help_link' => '',
1538
-            'ticket_options_help_link' => '',
1539
-            'time'                     => null,
1540
-            'ticket_rows'              => '',
1541
-            'existing_ticket_ids'      => '',
1542
-            'total_ticket_rows'        => 1,
1543
-            'ticket_js_structure'      => '',
1544
-            'trash_icon'               => 'ee-lock-icon',
1545
-            'disabled'                 => '',
1546
-        );
1547
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1548
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1549
-        /**
1550
-         * 1. Start with retrieving Datetimes
1551
-         * 2. Fore each datetime get related tickets
1552
-         * 3. For each ticket get related prices
1553
-         */
1554
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1555
-        /** @type EE_Datetime $first_datetime */
1556
-        $first_datetime = reset($times);
1557
-        // do we get related tickets?
1558
-        if ($first_datetime instanceof EE_Datetime
1559
-            && $first_datetime->ID() !== 0
1560
-        ) {
1561
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1562
-            $template_args['time'] = $first_datetime;
1563
-            $related_tickets = $first_datetime->tickets(
1564
-                array(
1565
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1566
-                    'default_where_conditions' => 'none',
1567
-                )
1568
-            );
1569
-            if (! empty($related_tickets)) {
1570
-                $template_args['total_ticket_rows'] = count($related_tickets);
1571
-                $row = 0;
1572
-                foreach ($related_tickets as $ticket) {
1573
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1574
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1575
-                    $row++;
1576
-                }
1577
-            } else {
1578
-                $template_args['total_ticket_rows'] = 1;
1579
-                /** @type EE_Ticket $ticket */
1580
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1581
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1582
-            }
1583
-        } else {
1584
-            $template_args['time'] = $times[0];
1585
-            /** @type EE_Ticket $ticket */
1586
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1587
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1588
-            // NOTE: we're just sending the first default row
1589
-            // (decaf can't manage default tickets so this should be sufficient);
1590
-        }
1591
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1592
-            'event_editor_event_datetimes_help_tab'
1593
-        );
1594
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1595
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1596
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1597
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1598
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1599
-            true
1600
-        );
1601
-        $template = apply_filters(
1602
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1603
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1604
-        );
1605
-        EEH_Template::display_template($template, $template_args);
1606
-    }
1607
-
1608
-
1609
-    /**
1610
-     * Setup an individual ticket form for the decaf event editor page
1611
-     *
1612
-     * @access private
1613
-     * @param  EE_Ticket $ticket   the ticket object
1614
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1615
-     * @param int        $row
1616
-     * @return string generated html for the ticket row.
1617
-     */
1618
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1619
-    {
1620
-        $template_args = array(
1621
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1622
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1623
-                : '',
1624
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1625
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1626
-            'TKT_name'            => $ticket->get('TKT_name'),
1627
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1628
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1629
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1630
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1631
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1632
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1633
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1634
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1635
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1636
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1637
-                : ' disabled=disabled',
1638
-        );
1639
-        $price = $ticket->ID() !== 0
1640
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1641
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1642
-        $price_args = array(
1643
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1644
-            'PRC_amount'            => $price->get('PRC_amount'),
1645
-            'PRT_ID'                => $price->get('PRT_ID'),
1646
-            'PRC_ID'                => $price->get('PRC_ID'),
1647
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1648
-        );
1649
-        // make sure we have default start and end dates if skeleton
1650
-        // handle rows that should NOT be empty
1651
-        if (empty($template_args['TKT_start_date'])) {
1652
-            // if empty then the start date will be now.
1653
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1654
-        }
1655
-        if (empty($template_args['TKT_end_date'])) {
1656
-            // get the earliest datetime (if present);
1657
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1658
-                ? $this->_cpt_model_obj->get_first_related(
1659
-                    'Datetime',
1660
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1661
-                )
1662
-                : null;
1663
-            if (! empty($earliest_dtt)) {
1664
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1665
-            } else {
1666
-                $template_args['TKT_end_date'] = date(
1667
-                    'Y-m-d h:i a',
1668
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1669
-                );
1670
-            }
1671
-        }
1672
-        $template_args = array_merge($template_args, $price_args);
1673
-        $template = apply_filters(
1674
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1675
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1676
-            $ticket
1677
-        );
1678
-        return EEH_Template::display_template($template, $template_args, true);
1679
-    }
1680
-
1681
-
1682
-    /**
1683
-     * @throws DomainException
1684
-     */
1685
-    public function registration_options_meta_box()
1686
-    {
1687
-        $yes_no_values = array(
1688
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1689
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1690
-        );
1691
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1692
-            array(
1693
-                EEM_Registration::status_id_cancelled,
1694
-                EEM_Registration::status_id_declined,
1695
-                EEM_Registration::status_id_incomplete,
1696
-            ),
1697
-            true
1698
-        );
1699
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1700
-        $template_args['_event'] = $this->_cpt_model_obj;
1701
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1702
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1703
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1704
-            'default_reg_status',
1705
-            $default_reg_status_values,
1706
-            $this->_cpt_model_obj->default_registration_status()
1707
-        );
1708
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1709
-            'display_desc',
1710
-            $yes_no_values,
1711
-            $this->_cpt_model_obj->display_description()
1712
-        );
1713
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1714
-            'display_ticket_selector',
1715
-            $yes_no_values,
1716
-            $this->_cpt_model_obj->display_ticket_selector(),
1717
-            '',
1718
-            '',
1719
-            false
1720
-        );
1721
-        $template_args['additional_registration_options'] = apply_filters(
1722
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1723
-            '',
1724
-            $template_args,
1725
-            $yes_no_values,
1726
-            $default_reg_status_values
1727
-        );
1728
-        EEH_Template::display_template(
1729
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1730
-            $template_args
1731
-        );
1732
-    }
1733
-
1734
-
1735
-    /**
1736
-     * _get_events()
1737
-     * This method simply returns all the events (for the given _view and paging)
1738
-     *
1739
-     * @access public
1740
-     * @param int  $per_page     count of items per page (20 default);
1741
-     * @param int  $current_page what is the current page being viewed.
1742
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1743
-     *                           If FALSE then we return an array of event objects
1744
-     *                           that match the given _view and paging parameters.
1745
-     * @return array an array of event objects.
1746
-     */
1747
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1748
-    {
1749
-        $EEME = $this->_event_model();
1750
-        $offset = ($current_page - 1) * $per_page;
1751
-        $limit = $count ? null : $offset . ',' . $per_page;
1752
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1753
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1754
-        if (isset($this->_req_data['month_range'])) {
1755
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1756
-            // simulate the FIRST day of the month, that fixes issues for months like February
1757
-            // where PHP doesn't know what to assume for date.
1758
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1759
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1760
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1761
-        }
1762
-        $where = array();
1763
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1764
-        // determine what post_status our condition will have for the query.
1765
-        switch ($status) {
1766
-            case 'month':
1767
-            case 'today':
1768
-            case null:
1769
-            case 'all':
1770
-                break;
1771
-            case 'draft':
1772
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1773
-                break;
1774
-            default:
1775
-                $where['status'] = $status;
1776
-        }
1777
-        // categories?
1778
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1779
-            ? $this->_req_data['EVT_CAT'] : null;
1780
-        if (! empty($category)) {
1781
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1782
-            $where['Term_Taxonomy.term_id'] = $category;
1783
-        }
1784
-        // date where conditions
1785
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1786
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1787
-            $DateTime = new DateTime(
1788
-                $year_r . '-' . $month_r . '-01 00:00:00',
1789
-                new DateTimeZone('UTC')
1790
-            );
1791
-            $start = $DateTime->getTimestamp();
1792
-            // set the datetime to be the end of the month
1793
-            $DateTime->setDate(
1794
-                $year_r,
1795
-                $month_r,
1796
-                $DateTime->format('t')
1797
-            )->setTime(23, 59, 59);
1798
-            $end = $DateTime->getTimestamp();
1799
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1800
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1801
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1802
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1803
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1804
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1805
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1806
-            $now = date('Y-m-01');
1807
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1808
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1809
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1810
-                            ->setTime(23, 59, 59)
1811
-                            ->format(implode(' ', $start_formats));
1812
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1813
-        }
1814
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1815
-            $where['EVT_wp_user'] = get_current_user_id();
1816
-        } else {
1817
-            if (! isset($where['status'])) {
1818
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1819
-                    $where['OR'] = array(
1820
-                        'status*restrict_private' => array('!=', 'private'),
1821
-                        'AND'                     => array(
1822
-                            'status*inclusive' => array('=', 'private'),
1823
-                            'EVT_wp_user'      => get_current_user_id(),
1824
-                        ),
1825
-                    );
1826
-                }
1827
-            }
1828
-        }
1829
-        if (isset($this->_req_data['EVT_wp_user'])) {
1830
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1831
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1832
-            ) {
1833
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1834
-            }
1835
-        }
1836
-        // search query handling
1837
-        if (isset($this->_req_data['s'])) {
1838
-            $search_string = '%' . $this->_req_data['s'] . '%';
1839
-            $where['OR'] = array(
1840
-                'EVT_name'       => array('LIKE', $search_string),
1841
-                'EVT_desc'       => array('LIKE', $search_string),
1842
-                'EVT_short_desc' => array('LIKE', $search_string),
1843
-            );
1844
-        }
1845
-        // filter events by venue.
1846
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1847
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1848
-        }
1849
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1850
-        $query_params = apply_filters(
1851
-            'FHEE__Events_Admin_Page__get_events__query_params',
1852
-            array(
1853
-                $where,
1854
-                'limit'    => $limit,
1855
-                'order_by' => $orderby,
1856
-                'order'    => $order,
1857
-                'group_by' => 'EVT_ID',
1858
-            ),
1859
-            $this->_req_data
1860
-        );
1861
-
1862
-        // let's first check if we have special requests coming in.
1863
-        if (isset($this->_req_data['active_status'])) {
1864
-            switch ($this->_req_data['active_status']) {
1865
-                case 'upcoming':
1866
-                    return $EEME->get_upcoming_events($query_params, $count);
1867
-                    break;
1868
-                case 'expired':
1869
-                    return $EEME->get_expired_events($query_params, $count);
1870
-                    break;
1871
-                case 'active':
1872
-                    return $EEME->get_active_events($query_params, $count);
1873
-                    break;
1874
-                case 'inactive':
1875
-                    return $EEME->get_inactive_events($query_params, $count);
1876
-                    break;
1877
-            }
1878
-        }
1879
-
1880
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1881
-        return $events;
1882
-    }
1883
-
1884
-
1885
-    /**
1886
-     * handling for WordPress CPT actions (trash, restore, delete)
1887
-     *
1888
-     * @param string $post_id
1889
-     */
1890
-    public function trash_cpt_item($post_id)
1891
-    {
1892
-        $this->_req_data['EVT_ID'] = $post_id;
1893
-        $this->_trash_or_restore_event('trash', false);
1894
-    }
1895
-
1896
-
1897
-    /**
1898
-     * @param string $post_id
1899
-     */
1900
-    public function restore_cpt_item($post_id)
1901
-    {
1902
-        $this->_req_data['EVT_ID'] = $post_id;
1903
-        $this->_trash_or_restore_event('draft', false);
1904
-    }
1905
-
1906
-
1907
-    /**
1908
-     * @param string $post_id
1909
-     */
1910
-    public function delete_cpt_item($post_id)
1911
-    {
1912
-        $this->_req_data['EVT_ID'] = $post_id;
1913
-        $this->_delete_event(false);
1914
-    }
1915
-
1916
-
1917
-    /**
1918
-     * _trash_or_restore_event
1919
-     *
1920
-     * @access protected
1921
-     * @param  string $event_status
1922
-     * @param bool    $redirect_after
1923
-     */
1924
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1925
-    {
1926
-        // determine the event id and set to array.
1927
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1928
-        // loop thru events
1929
-        if ($EVT_ID) {
1930
-            // clean status
1931
-            $event_status = sanitize_key($event_status);
1932
-            // grab status
1933
-            if (! empty($event_status)) {
1934
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1935
-            } else {
1936
-                $success = false;
1937
-                $msg = esc_html__(
1938
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1939
-                    'event_espresso'
1940
-                );
1941
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1942
-            }
1943
-        } else {
1944
-            $success = false;
1945
-            $msg = esc_html__(
1946
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1947
-                'event_espresso'
1948
-            );
1949
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1950
-        }
1951
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1952
-        if ($redirect_after) {
1953
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1954
-        }
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     * _trash_or_restore_events
1960
-     *
1961
-     * @access protected
1962
-     * @param  string $event_status
1963
-     * @return void
1964
-     */
1965
-    protected function _trash_or_restore_events($event_status = 'trash')
1966
-    {
1967
-        // clean status
1968
-        $event_status = sanitize_key($event_status);
1969
-        // grab status
1970
-        if (! empty($event_status)) {
1971
-            $success = true;
1972
-            // determine the event id and set to array.
1973
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1974
-            // loop thru events
1975
-            foreach ($EVT_IDs as $EVT_ID) {
1976
-                if ($EVT_ID = absint($EVT_ID)) {
1977
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1978
-                    $success = $results !== false ? $success : false;
1979
-                } else {
1980
-                    $msg = sprintf(
1981
-                        esc_html__(
1982
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1983
-                            'event_espresso'
1984
-                        ),
1985
-                        $EVT_ID
1986
-                    );
1987
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1988
-                    $success = false;
1989
-                }
1990
-            }
1991
-        } else {
1992
-            $success = false;
1993
-            $msg = esc_html__(
1994
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1995
-                'event_espresso'
1996
-            );
1997
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
-        }
1999
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2000
-        $success = $success ? 2 : false;
2001
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2002
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2003
-    }
2004
-
2005
-
2006
-    /**
2007
-     * _trash_or_restore_events
2008
-     *
2009
-     * @access  private
2010
-     * @param  int    $EVT_ID
2011
-     * @param  string $event_status
2012
-     * @return bool
2013
-     */
2014
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2015
-    {
2016
-        // grab event id
2017
-        if (! $EVT_ID) {
2018
-            $msg = esc_html__(
2019
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2020
-                'event_espresso'
2021
-            );
2022
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2023
-            return false;
2024
-        }
2025
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2026
-        // clean status
2027
-        $event_status = sanitize_key($event_status);
2028
-        // grab status
2029
-        if (empty($event_status)) {
2030
-            $msg = esc_html__(
2031
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2032
-                'event_espresso'
2033
-            );
2034
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2035
-            return false;
2036
-        }
2037
-        // was event trashed or restored ?
2038
-        switch ($event_status) {
2039
-            case 'draft':
2040
-                $action = 'restored from the trash';
2041
-                $hook = 'AHEE_event_restored_from_trash';
2042
-                break;
2043
-            case 'trash':
2044
-                $action = 'moved to the trash';
2045
-                $hook = 'AHEE_event_moved_to_trash';
2046
-                break;
2047
-            default:
2048
-                $action = 'updated';
2049
-                $hook = false;
2050
-        }
2051
-        // use class to change status
2052
-        $this->_cpt_model_obj->set_status($event_status);
2053
-        $success = $this->_cpt_model_obj->save();
2054
-        if ($success === false) {
2055
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2056
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2057
-            return false;
2058
-        }
2059
-        if ($hook) {
2060
-            do_action($hook);
2061
-        }
2062
-        return true;
2063
-    }
2064
-
2065
-
2066
-    /**
2067
-     * _delete_event
2068
-     *
2069
-     * @access protected
2070
-     * @param bool $redirect_after
2071
-     */
2072
-    protected function _delete_event($redirect_after = true)
2073
-    {
2074
-        // determine the event id and set to array.
2075
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2076
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2077
-        // loop thru events
2078
-        if ($EVT_ID) {
2079
-            $success = $this->_permanently_delete_event($EVT_ID);
2080
-            // get list of events with no prices
2081
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2082
-            // remove this event from the list of events with no prices
2083
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2084
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2085
-            }
2086
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2087
-        } else {
2088
-            $success = false;
2089
-            $msg = esc_html__(
2090
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2091
-                'event_espresso'
2092
-            );
2093
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2094
-        }
2095
-        if ($redirect_after) {
2096
-            $this->_redirect_after_action(
2097
-                $success,
2098
-                'Event',
2099
-                'deleted',
2100
-                array('action' => 'default', 'status' => 'trash')
2101
-            );
2102
-        }
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * _delete_events
2108
-     *
2109
-     * @access protected
2110
-     * @return void
2111
-     */
2112
-    protected function _delete_events()
2113
-    {
2114
-        $success = true;
2115
-        // get list of events with no prices
2116
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2117
-        // determine the event id and set to array.
2118
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2119
-        // loop thru events
2120
-        foreach ($EVT_IDs as $EVT_ID) {
2121
-            $EVT_ID = absint($EVT_ID);
2122
-            if ($EVT_ID) {
2123
-                $results = $this->_permanently_delete_event($EVT_ID);
2124
-                $success = $results !== false ? $success : false;
2125
-                // remove this event from the list of events with no prices
2126
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2127
-            } else {
2128
-                $success = false;
2129
-                $msg = esc_html__(
2130
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2131
-                    'event_espresso'
2132
-                );
2133
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2134
-            }
2135
-        }
2136
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2137
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2138
-        $success = $success ? 2 : false;
2139
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2140
-    }
2141
-
2142
-
2143
-    /**
2144
-     * _permanently_delete_event
2145
-     *
2146
-     * @access  private
2147
-     * @param  int $EVT_ID
2148
-     * @return bool
2149
-     */
2150
-    private function _permanently_delete_event($EVT_ID = 0)
2151
-    {
2152
-        // grab event id
2153
-        if (! $EVT_ID) {
2154
-            $msg = esc_html__(
2155
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2156
-                'event_espresso'
2157
-            );
2158
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
-            return false;
2160
-        }
2161
-        if (! $this->_cpt_model_obj instanceof EE_Event
2162
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2163
-        ) {
2164
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2165
-        }
2166
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2167
-            return false;
2168
-        }
2169
-        // need to delete related tickets and prices first.
2170
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2171
-        foreach ($datetimes as $datetime) {
2172
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2173
-            $tickets = $datetime->get_many_related('Ticket');
2174
-            foreach ($tickets as $ticket) {
2175
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2176
-                $ticket->delete_related_permanently('Price');
2177
-                $ticket->delete_permanently();
2178
-            }
2179
-            $datetime->delete();
2180
-        }
2181
-        // what about related venues or terms?
2182
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2183
-        foreach ($venues as $venue) {
2184
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2185
-        }
2186
-        // any attached question groups?
2187
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2188
-        if (! empty($question_groups)) {
2189
-            foreach ($question_groups as $question_group) {
2190
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2191
-            }
2192
-        }
2193
-        // Message Template Groups
2194
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2195
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2196
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2197
-        foreach ($term_taxonomies as $term_taxonomy) {
2198
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2199
-        }
2200
-        $success = $this->_cpt_model_obj->delete_permanently();
2201
-        // did it all go as planned ?
2202
-        if ($success) {
2203
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2204
-            EE_Error::add_success($msg);
2205
-        } else {
2206
-            $msg = sprintf(
2207
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2208
-                $EVT_ID
2209
-            );
2210
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
-            return false;
2212
-        }
2213
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2214
-        return true;
2215
-    }
2216
-
2217
-
2218
-    /**
2219
-     * get total number of events
2220
-     *
2221
-     * @access public
2222
-     * @return int
2223
-     */
2224
-    public function total_events()
2225
-    {
2226
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2227
-        return $count;
2228
-    }
2229
-
2230
-
2231
-    /**
2232
-     * get total number of draft events
2233
-     *
2234
-     * @access public
2235
-     * @return int
2236
-     */
2237
-    public function total_events_draft()
2238
-    {
2239
-        $where = array(
2240
-            'status' => array('IN', array('draft', 'auto-draft')),
2241
-        );
2242
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2243
-        return $count;
2244
-    }
2245
-
2246
-
2247
-    /**
2248
-     * get total number of trashed events
2249
-     *
2250
-     * @access public
2251
-     * @return int
2252
-     */
2253
-    public function total_trashed_events()
2254
-    {
2255
-        $where = array(
2256
-            'status' => 'trash',
2257
-        );
2258
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2259
-        return $count;
2260
-    }
2261
-
2262
-
2263
-    /**
2264
-     *    _default_event_settings
2265
-     *    This generates the Default Settings Tab
2266
-     *
2267
-     * @return void
2268
-     * @throws EE_Error
2269
-     */
2270
-    protected function _default_event_settings()
2271
-    {
2272
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2273
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2274
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2275
-        $this->display_admin_page_with_sidebar();
2276
-    }
2277
-
2278
-
2279
-    /**
2280
-     * Return the form for event settings.
2281
-     *
2282
-     * @return EE_Form_Section_Proper
2283
-     * @throws EE_Error
2284
-     */
2285
-    protected function _default_event_settings_form()
2286
-    {
2287
-        $registration_config = EE_Registry::instance()->CFG->registration;
2288
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2289
-            // exclude
2290
-            array(
2291
-                EEM_Registration::status_id_cancelled,
2292
-                EEM_Registration::status_id_declined,
2293
-                EEM_Registration::status_id_incomplete,
2294
-                EEM_Registration::status_id_wait_list,
2295
-            ),
2296
-            true
2297
-        );
2298
-        return new EE_Form_Section_Proper(
2299
-            array(
2300
-                'name'            => 'update_default_event_settings',
2301
-                'html_id'         => 'update_default_event_settings',
2302
-                'html_class'      => 'form-table',
2303
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2304
-                'subsections'     => apply_filters(
2305
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2306
-                    array(
2307
-                        'default_reg_status'  => new EE_Select_Input(
2308
-                            $registration_stati_for_selection,
2309
-                            array(
2310
-                                'default'         => isset($registration_config->default_STS_ID)
2311
-                                                     && array_key_exists(
2312
-                                                         $registration_config->default_STS_ID,
2313
-                                                         $registration_stati_for_selection
2314
-                                                     )
2315
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2316
-                                    : EEM_Registration::status_id_pending_payment,
2317
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2318
-                                                     . EEH_Template::get_help_tab_link(
2319
-                                                         'default_settings_status_help_tab'
2320
-                                                     ),
2321
-                                'html_help_text'  => esc_html__(
2322
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2323
-                                    'event_espresso'
2324
-                                ),
2325
-                            )
2326
-                        ),
2327
-                        'default_max_tickets' => new EE_Integer_Input(
2328
-                            array(
2329
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2330
-                                    ? $registration_config->default_maximum_number_of_tickets
2331
-                                    : EEM_Event::get_default_additional_limit(),
2332
-                                'html_label_text' => esc_html__(
2333
-                                    'Default Maximum Tickets Allowed Per Order:',
2334
-                                    'event_espresso'
2335
-                                )
2336
-                                                     . EEH_Template::get_help_tab_link(
2337
-                                                         'default_maximum_tickets_help_tab"'
2338
-                                                     ),
2339
-                                'html_help_text'  => esc_html__(
2340
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2341
-                                    'event_espresso'
2342
-                                ),
2343
-                            )
2344
-                        ),
2345
-                    )
2346
-                ),
2347
-            )
2348
-        );
2349
-    }
2350
-
2351
-
2352
-    /**
2353
-     * _update_default_event_settings
2354
-     *
2355
-     * @access protected
2356
-     * @return void
2357
-     * @throws EE_Error
2358
-     */
2359
-    protected function _update_default_event_settings()
2360
-    {
2361
-        $registration_config = EE_Registry::instance()->CFG->registration;
2362
-        $form = $this->_default_event_settings_form();
2363
-        if ($form->was_submitted()) {
2364
-            $form->receive_form_submission();
2365
-            if ($form->is_valid()) {
2366
-                $valid_data = $form->valid_data();
2367
-                if (isset($valid_data['default_reg_status'])) {
2368
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2369
-                }
2370
-                if (isset($valid_data['default_max_tickets'])) {
2371
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2372
-                }
2373
-                // update because data was valid!
2374
-                EE_Registry::instance()->CFG->update_espresso_config();
2375
-                EE_Error::overwrite_success();
2376
-                EE_Error::add_success(
2377
-                    __('Default Event Settings were updated', 'event_espresso')
2378
-                );
2379
-            }
2380
-        }
2381
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2382
-    }
2383
-
2384
-
2385
-    /*************        Templates        *************/
2386
-    protected function _template_settings()
2387
-    {
2388
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2389
-        $this->_template_args['preview_img'] = '<img src="'
2390
-                                               . EVENTS_ASSETS_URL
2391
-                                               . '/images/'
2392
-                                               . 'caffeinated_template_features.jpg" alt="'
2393
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2394
-                                               . '" />';
2395
-        $this->_template_args['preview_text'] = '<strong>'
2396
-                                                . esc_html__(
2397
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2398
-                                                    'event_espresso'
2399
-                                                ) . '</strong>';
2400
-        $this->display_admin_caf_preview_page('template_settings_tab');
2401
-    }
2402
-
2403
-
2404
-    /** Event Category Stuff **/
2405
-    /**
2406
-     * set the _category property with the category object for the loaded page.
2407
-     *
2408
-     * @access private
2409
-     * @return void
2410
-     */
2411
-    private function _set_category_object()
2412
-    {
2413
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2414
-            return;
2415
-        } //already have the category object so get out.
2416
-        // set default category object
2417
-        $this->_set_empty_category_object();
2418
-        // only set if we've got an id
2419
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2420
-            return;
2421
-        }
2422
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2423
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2424
-        if (! empty($term)) {
2425
-            $this->_category->category_name = $term->name;
2426
-            $this->_category->category_identifier = $term->slug;
2427
-            $this->_category->category_desc = $term->description;
2428
-            $this->_category->id = $term->term_id;
2429
-            $this->_category->parent = $term->parent;
2430
-        }
2431
-    }
2432
-
2433
-
2434
-    /**
2435
-     * Clears out category properties.
2436
-     */
2437
-    private function _set_empty_category_object()
2438
-    {
2439
-        $this->_category = new stdClass();
2440
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2441
-        $this->_category->id = $this->_category->parent = 0;
2442
-    }
2443
-
2444
-
2445
-    /**
2446
-     * @throws EE_Error
2447
-     */
2448
-    protected function _category_list_table()
2449
-    {
2450
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2451
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2452
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2453
-            'add_category',
2454
-            'add_category',
2455
-            array(),
2456
-            'add-new-h2'
2457
-        );
2458
-        $this->display_admin_list_table_page_with_sidebar();
2459
-    }
2460
-
2461
-
2462
-    /**
2463
-     * Output category details view.
2464
-     */
2465
-    protected function _category_details($view)
2466
-    {
2467
-        // load formatter helper
2468
-        // load field generator helper
2469
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2470
-        $this->_set_add_edit_form_tags($route);
2471
-        $this->_set_category_object();
2472
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2473
-        $delete_action = 'delete_category';
2474
-        // custom redirect
2475
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2476
-            array('action' => 'category_list'),
2477
-            $this->_admin_base_url
2478
-        );
2479
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2480
-        // take care of contents
2481
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2482
-        $this->display_admin_page_with_sidebar();
2483
-    }
2484
-
2485
-
2486
-    /**
2487
-     * Output category details content.
2488
-     */
2489
-    protected function _category_details_content()
2490
-    {
2491
-        $editor_args['category_desc'] = array(
2492
-            'type'          => 'wp_editor',
2493
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2494
-            'class'         => 'my_editor_custom',
2495
-            'wpeditor_args' => array('media_buttons' => false),
2496
-        );
2497
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2498
-        $all_terms = get_terms(
2499
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2500
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2501
-        );
2502
-        // setup category select for term parents.
2503
-        $category_select_values[] = array(
2504
-            'text' => esc_html__('No Parent', 'event_espresso'),
2505
-            'id'   => 0,
2506
-        );
2507
-        foreach ($all_terms as $term) {
2508
-            $category_select_values[] = array(
2509
-                'text' => $term->name,
2510
-                'id'   => $term->term_id,
2511
-            );
2512
-        }
2513
-        $category_select = EEH_Form_Fields::select_input(
2514
-            'category_parent',
2515
-            $category_select_values,
2516
-            $this->_category->parent
2517
-        );
2518
-        $template_args = array(
2519
-            'category'                 => $this->_category,
2520
-            'category_select'          => $category_select,
2521
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2522
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2523
-            'disable'                  => '',
2524
-            'disabled_message'         => false,
2525
-        );
2526
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2527
-        return EEH_Template::display_template($template, $template_args, true);
2528
-    }
2529
-
2530
-
2531
-    /**
2532
-     * Handles deleting categories.
2533
-     */
2534
-    protected function _delete_categories()
2535
-    {
2536
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2537
-            : (array) $this->_req_data['category_id'];
2538
-        foreach ($cat_ids as $cat_id) {
2539
-            $this->_delete_category($cat_id);
2540
-        }
2541
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2542
-        $query_args = array(
2543
-            'action' => 'category_list',
2544
-        );
2545
-        $this->_redirect_after_action(0, '', '', $query_args);
2546
-    }
2547
-
2548
-
2549
-    /**
2550
-     * Handles deleting specific category.
2551
-     *
2552
-     * @param int $cat_id
2553
-     */
2554
-    protected function _delete_category($cat_id)
2555
-    {
2556
-        $cat_id = absint($cat_id);
2557
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2558
-    }
2559
-
2560
-
2561
-    /**
2562
-     * Handles triggering the update or insertion of a new category.
2563
-     *
2564
-     * @param bool $new_category true means we're triggering the insert of a new category.
2565
-     */
2566
-    protected function _insert_or_update_category($new_category)
2567
-    {
2568
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2569
-        $success = 0; // we already have a success message so lets not send another.
2570
-        if ($cat_id) {
2571
-            $query_args = array(
2572
-                'action'     => 'edit_category',
2573
-                'EVT_CAT_ID' => $cat_id,
2574
-            );
2575
-        } else {
2576
-            $query_args = array('action' => 'add_category');
2577
-        }
2578
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2579
-    }
2580
-
2581
-
2582
-    /**
2583
-     * Inserts or updates category
2584
-     *
2585
-     * @param bool $update (true indicates we're updating a category).
2586
-     * @return bool|mixed|string
2587
-     */
2588
-    private function _insert_category($update = false)
2589
-    {
2590
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2591
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2592
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2593
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2594
-        if (empty($category_name)) {
2595
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2596
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2597
-            return false;
2598
-        }
2599
-        $term_args = array(
2600
-            'name'        => $category_name,
2601
-            'description' => $category_desc,
2602
-            'parent'      => $category_parent,
2603
-        );
2604
-        // was the category_identifier input disabled?
2605
-        if (isset($this->_req_data['category_identifier'])) {
2606
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2607
-        }
2608
-        $insert_ids = $update
2609
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2610
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2611
-        if (! is_array($insert_ids)) {
2612
-            $msg = esc_html__(
2613
-                'An error occurred and the category has not been saved to the database.',
2614
-                'event_espresso'
2615
-            );
2616
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2617
-        } else {
2618
-            $cat_id = $insert_ids['term_id'];
2619
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2620
-            EE_Error::add_success($msg);
2621
-        }
2622
-        return $cat_id;
2623
-    }
2624
-
2625
-
2626
-    /**
2627
-     * Gets categories or count of categories matching the arguments in the request.
2628
-     *
2629
-     * @param int  $per_page
2630
-     * @param int  $current_page
2631
-     * @param bool $count
2632
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2633
-     */
2634
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2635
-    {
2636
-        // testing term stuff
2637
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2638
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2639
-        $limit = ($current_page - 1) * $per_page;
2640
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2641
-        if (isset($this->_req_data['s'])) {
2642
-            $sstr = '%' . $this->_req_data['s'] . '%';
2643
-            $where['OR'] = array(
2644
-                'Term.name'   => array('LIKE', $sstr),
2645
-                'description' => array('LIKE', $sstr),
2646
-            );
2647
-        }
2648
-        $query_params = array(
2649
-            $where,
2650
-            'order_by'   => array($orderby => $order),
2651
-            'limit'      => $limit . ',' . $per_page,
2652
-            'force_join' => array('Term'),
2653
-        );
2654
-        $categories = $count
2655
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2656
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2657
-        return $categories;
2658
-    }
2659
-
2660
-    /* end category stuff */
2661
-    /**************/
2662
-
2663
-
2664
-    /**
2665
-     * Callback for the `ee_save_timezone_setting` ajax action.
2666
-     *
2667
-     * @throws EE_Error
2668
-     */
2669
-    public function save_timezonestring_setting()
2670
-    {
2671
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2672
-            ? $this->_req_data['timezone_selected']
2673
-            : '';
2674
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2675
-            EE_Error::add_error(
2676
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2677
-                __FILE__,
2678
-                __FUNCTION__,
2679
-                __LINE__
2680
-            );
2681
-            $this->_template_args['error'] = true;
2682
-            $this->_return_json();
2683
-        }
2684
-
2685
-        update_option('timezone_string', $timezone_string);
2686
-        EE_Error::add_success(
2687
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2688
-        );
2689
-        $this->_template_args['success'] = true;
2690
-        $this->_return_json(true, array('action' => 'create_new'));
2691
-    }
15
+	/**
16
+	 * This will hold the event object for event_details screen.
17
+	 *
18
+	 * @access protected
19
+	 * @var EE_Event $_event
20
+	 */
21
+	protected $_event;
22
+
23
+
24
+	/**
25
+	 * This will hold the category object for category_details screen.
26
+	 *
27
+	 * @var stdClass $_category
28
+	 */
29
+	protected $_category;
30
+
31
+
32
+	/**
33
+	 * This will hold the event model instance
34
+	 *
35
+	 * @var EEM_Event $_event_model
36
+	 */
37
+	protected $_event_model;
38
+
39
+
40
+	/**
41
+	 * @var EE_Event
42
+	 */
43
+	protected $_cpt_model_obj = false;
44
+
45
+
46
+	/**
47
+	 * Initialize page props for this admin page group.
48
+	 */
49
+	protected function _init_page_props()
50
+	{
51
+		$this->page_slug = EVENTS_PG_SLUG;
52
+		$this->page_label = EVENTS_LABEL;
53
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
54
+		$this->_admin_base_path = EVENTS_ADMIN;
55
+		$this->_cpt_model_names = array(
56
+			'create_new' => 'EEM_Event',
57
+			'edit'       => 'EEM_Event',
58
+		);
59
+		$this->_cpt_edit_routes = array(
60
+			'espresso_events' => 'edit',
61
+		);
62
+		add_action(
63
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
64
+			array($this, 'verify_event_edit'),
65
+			10,
66
+			2
67
+		);
68
+	}
69
+
70
+
71
+	/**
72
+	 * Sets the ajax hooks used for this admin page group.
73
+	 */
74
+	protected function _ajax_hooks()
75
+	{
76
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
77
+	}
78
+
79
+
80
+	/**
81
+	 * Sets the page properties for this admin page group.
82
+	 */
83
+	protected function _define_page_props()
84
+	{
85
+		$this->_admin_page_title = EVENTS_LABEL;
86
+		$this->_labels = array(
87
+			'buttons'      => array(
88
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
89
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
90
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
91
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
92
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
93
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
94
+			),
95
+			'editor_title' => array(
96
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
97
+			),
98
+			'publishbox'   => array(
99
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
100
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
101
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
102
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
103
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
104
+			),
105
+		);
106
+	}
107
+
108
+
109
+	/**
110
+	 * Sets the page routes property for this admin page group.
111
+	 */
112
+	protected function _set_page_routes()
113
+	{
114
+		// load formatter helper
115
+		// load field generator helper
116
+		// is there a evt_id in the request?
117
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
118
+			? $this->_req_data['EVT_ID']
119
+			: 0;
120
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
121
+		$this->_page_routes = array(
122
+			'default'                       => array(
123
+				'func'       => '_events_overview_list_table',
124
+				'capability' => 'ee_read_events',
125
+			),
126
+			'create_new'                    => array(
127
+				'func'       => '_create_new_cpt_item',
128
+				'capability' => 'ee_edit_events',
129
+			),
130
+			'edit'                          => array(
131
+				'func'       => '_edit_cpt_item',
132
+				'capability' => 'ee_edit_event',
133
+				'obj_id'     => $evt_id,
134
+			),
135
+			'copy_event'                    => array(
136
+				'func'       => '_copy_events',
137
+				'capability' => 'ee_edit_event',
138
+				'obj_id'     => $evt_id,
139
+				'noheader'   => true,
140
+			),
141
+			'trash_event'                   => array(
142
+				'func'       => '_trash_or_restore_event',
143
+				'args'       => array('event_status' => 'trash'),
144
+				'capability' => 'ee_delete_event',
145
+				'obj_id'     => $evt_id,
146
+				'noheader'   => true,
147
+			),
148
+			'trash_events'                  => array(
149
+				'func'       => '_trash_or_restore_events',
150
+				'args'       => array('event_status' => 'trash'),
151
+				'capability' => 'ee_delete_events',
152
+				'noheader'   => true,
153
+			),
154
+			'restore_event'                 => array(
155
+				'func'       => '_trash_or_restore_event',
156
+				'args'       => array('event_status' => 'draft'),
157
+				'capability' => 'ee_delete_event',
158
+				'obj_id'     => $evt_id,
159
+				'noheader'   => true,
160
+			),
161
+			'restore_events'                => array(
162
+				'func'       => '_trash_or_restore_events',
163
+				'args'       => array('event_status' => 'draft'),
164
+				'capability' => 'ee_delete_events',
165
+				'noheader'   => true,
166
+			),
167
+			'delete_event'                  => array(
168
+				'func'       => '_delete_event',
169
+				'capability' => 'ee_delete_event',
170
+				'obj_id'     => $evt_id,
171
+				'noheader'   => true,
172
+			),
173
+			'delete_events'                 => array(
174
+				'func'       => '_delete_events',
175
+				'capability' => 'ee_delete_events',
176
+				'noheader'   => true,
177
+			),
178
+			'view_report'                   => array(
179
+				'func'      => '_view_report',
180
+				'capablity' => 'ee_edit_events',
181
+			),
182
+			'default_event_settings'        => array(
183
+				'func'       => '_default_event_settings',
184
+				'capability' => 'manage_options',
185
+			),
186
+			'update_default_event_settings' => array(
187
+				'func'       => '_update_default_event_settings',
188
+				'capability' => 'manage_options',
189
+				'noheader'   => true,
190
+			),
191
+			'template_settings'             => array(
192
+				'func'       => '_template_settings',
193
+				'capability' => 'manage_options',
194
+			),
195
+			// event category tab related
196
+			'add_category'                  => array(
197
+				'func'       => '_category_details',
198
+				'capability' => 'ee_edit_event_category',
199
+				'args'       => array('add'),
200
+			),
201
+			'edit_category'                 => array(
202
+				'func'       => '_category_details',
203
+				'capability' => 'ee_edit_event_category',
204
+				'args'       => array('edit'),
205
+			),
206
+			'delete_categories'             => array(
207
+				'func'       => '_delete_categories',
208
+				'capability' => 'ee_delete_event_category',
209
+				'noheader'   => true,
210
+			),
211
+			'delete_category'               => array(
212
+				'func'       => '_delete_categories',
213
+				'capability' => 'ee_delete_event_category',
214
+				'noheader'   => true,
215
+			),
216
+			'insert_category'               => array(
217
+				'func'       => '_insert_or_update_category',
218
+				'args'       => array('new_category' => true),
219
+				'capability' => 'ee_edit_event_category',
220
+				'noheader'   => true,
221
+			),
222
+			'update_category'               => array(
223
+				'func'       => '_insert_or_update_category',
224
+				'args'       => array('new_category' => false),
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			),
228
+			'category_list'                 => array(
229
+				'func'       => '_category_list_table',
230
+				'capability' => 'ee_manage_event_categories',
231
+			),
232
+		);
233
+	}
234
+
235
+
236
+	/**
237
+	 * Set the _page_config property for this admin page group.
238
+	 */
239
+	protected function _set_page_config()
240
+	{
241
+		$this->_page_config = array(
242
+			'default'                => array(
243
+				'nav'           => array(
244
+					'label' => esc_html__('Overview', 'event_espresso'),
245
+					'order' => 10,
246
+				),
247
+				'list_table'    => 'Events_Admin_List_Table',
248
+				'help_tabs'     => array(
249
+					'events_overview_help_tab'                       => array(
250
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
251
+						'filename' => 'events_overview',
252
+					),
253
+					'events_overview_table_column_headings_help_tab' => array(
254
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
255
+						'filename' => 'events_overview_table_column_headings',
256
+					),
257
+					'events_overview_filters_help_tab'               => array(
258
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
259
+						'filename' => 'events_overview_filters',
260
+					),
261
+					'events_overview_view_help_tab'                  => array(
262
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
263
+						'filename' => 'events_overview_views',
264
+					),
265
+					'events_overview_other_help_tab'                 => array(
266
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
267
+						'filename' => 'events_overview_other',
268
+					),
269
+				),
270
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
271
+				// 'help_tour'     => array(
272
+				//     'Event_Overview_Help_Tour',
273
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
274
+				// ),
275
+				'qtips'         => array(
276
+					'EE_Event_List_Table_Tips',
277
+				),
278
+				'require_nonce' => false,
279
+			),
280
+			'create_new'             => array(
281
+				'nav'           => array(
282
+					'label'      => esc_html__('Add Event', 'event_espresso'),
283
+					'order'      => 5,
284
+					'persistent' => false,
285
+				),
286
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
287
+				'help_tabs'     => array(
288
+					'event_editor_help_tab'                            => array(
289
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
290
+						'filename' => 'event_editor',
291
+					),
292
+					'event_editor_title_richtexteditor_help_tab'       => array(
293
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
294
+						'filename' => 'event_editor_title_richtexteditor',
295
+					),
296
+					'event_editor_venue_details_help_tab'              => array(
297
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
298
+						'filename' => 'event_editor_venue_details',
299
+					),
300
+					'event_editor_event_datetimes_help_tab'            => array(
301
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
302
+						'filename' => 'event_editor_event_datetimes',
303
+					),
304
+					'event_editor_event_tickets_help_tab'              => array(
305
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
306
+						'filename' => 'event_editor_event_tickets',
307
+					),
308
+					'event_editor_event_registration_options_help_tab' => array(
309
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
310
+						'filename' => 'event_editor_event_registration_options',
311
+					),
312
+					'event_editor_tags_categories_help_tab'            => array(
313
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
314
+						'filename' => 'event_editor_tags_categories',
315
+					),
316
+					'event_editor_questions_registrants_help_tab'      => array(
317
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
318
+						'filename' => 'event_editor_questions_registrants',
319
+					),
320
+					'event_editor_save_new_event_help_tab'             => array(
321
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
322
+						'filename' => 'event_editor_save_new_event',
323
+					),
324
+					'event_editor_other_help_tab'                      => array(
325
+						'title'    => esc_html__('Event Other', 'event_espresso'),
326
+						'filename' => 'event_editor_other',
327
+					),
328
+				),
329
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
330
+				// 'help_tour'     => array(
331
+				//     'Event_Editor_Help_Tour',
332
+				// ),
333
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
334
+				'require_nonce' => false,
335
+			),
336
+			'edit'                   => array(
337
+				'nav'           => array(
338
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
339
+					'order'      => 5,
340
+					'persistent' => false,
341
+					'url'        => isset($this->_req_data['post'])
342
+						? EE_Admin_Page::add_query_args_and_nonce(
343
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
344
+							$this->_current_page_view_url
345
+						)
346
+						: $this->_admin_base_url,
347
+				),
348
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
349
+				'help_tabs'     => array(
350
+					'event_editor_help_tab'                            => array(
351
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
352
+						'filename' => 'event_editor',
353
+					),
354
+					'event_editor_title_richtexteditor_help_tab'       => array(
355
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
356
+						'filename' => 'event_editor_title_richtexteditor',
357
+					),
358
+					'event_editor_venue_details_help_tab'              => array(
359
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
360
+						'filename' => 'event_editor_venue_details',
361
+					),
362
+					'event_editor_event_datetimes_help_tab'            => array(
363
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
364
+						'filename' => 'event_editor_event_datetimes',
365
+					),
366
+					'event_editor_event_tickets_help_tab'              => array(
367
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
368
+						'filename' => 'event_editor_event_tickets',
369
+					),
370
+					'event_editor_event_registration_options_help_tab' => array(
371
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
372
+						'filename' => 'event_editor_event_registration_options',
373
+					),
374
+					'event_editor_tags_categories_help_tab'            => array(
375
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
376
+						'filename' => 'event_editor_tags_categories',
377
+					),
378
+					'event_editor_questions_registrants_help_tab'      => array(
379
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
380
+						'filename' => 'event_editor_questions_registrants',
381
+					),
382
+					'event_editor_save_new_event_help_tab'             => array(
383
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
384
+						'filename' => 'event_editor_save_new_event',
385
+					),
386
+					'event_editor_other_help_tab'                      => array(
387
+						'title'    => esc_html__('Event Other', 'event_espresso'),
388
+						'filename' => 'event_editor_other',
389
+					),
390
+				),
391
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
392
+				'require_nonce' => false,
393
+			),
394
+			'default_event_settings' => array(
395
+				'nav'           => array(
396
+					'label' => esc_html__('Default Settings', 'event_espresso'),
397
+					'order' => 40,
398
+				),
399
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
400
+				'labels'        => array(
401
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
402
+				),
403
+				'help_tabs'     => array(
404
+					'default_settings_help_tab'        => array(
405
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
406
+						'filename' => 'events_default_settings',
407
+					),
408
+					'default_settings_status_help_tab' => array(
409
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
410
+						'filename' => 'events_default_settings_status',
411
+					),
412
+					'default_maximum_tickets_help_tab' => array(
413
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
414
+						'filename' => 'events_default_settings_max_tickets',
415
+					),
416
+				),
417
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
418
+				// 'help_tour'     => array('Event_Default_Settings_Help_Tour'),
419
+				'require_nonce' => false,
420
+			),
421
+			// template settings
422
+			'template_settings'      => array(
423
+				'nav'           => array(
424
+					'label' => esc_html__('Templates', 'event_espresso'),
425
+					'order' => 30,
426
+				),
427
+				'metaboxes'     => $this->_default_espresso_metaboxes,
428
+				'help_tabs'     => array(
429
+					'general_settings_templates_help_tab' => array(
430
+						'title'    => esc_html__('Templates', 'event_espresso'),
431
+						'filename' => 'general_settings_templates',
432
+					),
433
+				),
434
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
435
+				// 'help_tour'     => array('Templates_Help_Tour'),
436
+				'require_nonce' => false,
437
+			),
438
+			// event category stuff
439
+			'add_category'           => array(
440
+				'nav'           => array(
441
+					'label'      => esc_html__('Add Category', 'event_espresso'),
442
+					'order'      => 15,
443
+					'persistent' => false,
444
+				),
445
+				'help_tabs'     => array(
446
+					'add_category_help_tab' => array(
447
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
448
+						'filename' => 'events_add_category',
449
+					),
450
+				),
451
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
452
+				// 'help_tour'     => array('Event_Add_Category_Help_Tour'),
453
+				'metaboxes'     => array('_publish_post_box'),
454
+				'require_nonce' => false,
455
+			),
456
+			'edit_category'          => array(
457
+				'nav'           => array(
458
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
459
+					'order'      => 15,
460
+					'persistent' => false,
461
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
462
+						? add_query_arg(
463
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
464
+							$this->_current_page_view_url
465
+						)
466
+						: $this->_admin_base_url,
467
+				),
468
+				'help_tabs'     => array(
469
+					'edit_category_help_tab' => array(
470
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
471
+						'filename' => 'events_edit_category',
472
+					),
473
+				),
474
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
475
+				'metaboxes'     => array('_publish_post_box'),
476
+				'require_nonce' => false,
477
+			),
478
+			'category_list'          => array(
479
+				'nav'           => array(
480
+					'label' => esc_html__('Categories', 'event_espresso'),
481
+					'order' => 20,
482
+				),
483
+				'list_table'    => 'Event_Categories_Admin_List_Table',
484
+				'help_tabs'     => array(
485
+					'events_categories_help_tab'                       => array(
486
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
487
+						'filename' => 'events_categories',
488
+					),
489
+					'events_categories_table_column_headings_help_tab' => array(
490
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
491
+						'filename' => 'events_categories_table_column_headings',
492
+					),
493
+					'events_categories_view_help_tab'                  => array(
494
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
495
+						'filename' => 'events_categories_views',
496
+					),
497
+					'events_categories_other_help_tab'                 => array(
498
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
499
+						'filename' => 'events_categories_other',
500
+					),
501
+				),
502
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
503
+				// 'help_tour'     => array(
504
+				//     'Event_Categories_Help_Tour',
505
+				// ),
506
+				'metaboxes'     => $this->_default_espresso_metaboxes,
507
+				'require_nonce' => false,
508
+			),
509
+		);
510
+	}
511
+
512
+
513
+	/**
514
+	 * Used to register any global screen options if necessary for every route in this admin page group.
515
+	 */
516
+	protected function _add_screen_options()
517
+	{
518
+	}
519
+
520
+
521
+	/**
522
+	 * Implementing the screen options for the 'default' route.
523
+	 */
524
+	protected function _add_screen_options_default()
525
+	{
526
+		$this->_per_page_screen_option();
527
+	}
528
+
529
+
530
+	/**
531
+	 * Implementing screen options for the category list route.
532
+	 */
533
+	protected function _add_screen_options_category_list()
534
+	{
535
+		$page_title = $this->_admin_page_title;
536
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
537
+		$this->_per_page_screen_option();
538
+		$this->_admin_page_title = $page_title;
539
+	}
540
+
541
+
542
+	/**
543
+	 * Used to register any global feature pointers for the admin page group.
544
+	 */
545
+	protected function _add_feature_pointers()
546
+	{
547
+	}
548
+
549
+
550
+	/**
551
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
552
+	 */
553
+	public function load_scripts_styles()
554
+	{
555
+		wp_register_style(
556
+			'events-admin-css',
557
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
558
+			array(),
559
+			EVENT_ESPRESSO_VERSION
560
+		);
561
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
562
+		wp_enqueue_style('events-admin-css');
563
+		wp_enqueue_style('ee-cat-admin');
564
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
565
+		// registers for all views
566
+		// scripts
567
+		wp_register_script(
568
+			'event_editor_js',
569
+			EVENTS_ASSETS_URL . 'event_editor.js',
570
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
571
+			EVENT_ESPRESSO_VERSION,
572
+			true
573
+		);
574
+	}
575
+
576
+
577
+	/**
578
+	 * Enqueuing scripts and styles specific to this view
579
+	 */
580
+	public function load_scripts_styles_create_new()
581
+	{
582
+		$this->load_scripts_styles_edit();
583
+	}
584
+
585
+
586
+	/**
587
+	 * Enqueuing scripts and styles specific to this view
588
+	 */
589
+	public function load_scripts_styles_edit()
590
+	{
591
+		// styles
592
+		wp_enqueue_style('espresso-ui-theme');
593
+		wp_register_style(
594
+			'event-editor-css',
595
+			EVENTS_ASSETS_URL . 'event-editor.css',
596
+			array('ee-admin-css'),
597
+			EVENT_ESPRESSO_VERSION
598
+		);
599
+		wp_enqueue_style('event-editor-css');
600
+		// scripts
601
+		wp_register_script(
602
+			'event-datetime-metabox',
603
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
604
+			array('event_editor_js', 'ee-datepicker'),
605
+			EVENT_ESPRESSO_VERSION
606
+		);
607
+		wp_enqueue_script('event-datetime-metabox');
608
+	}
609
+
610
+
611
+	/**
612
+	 * Populating the _views property for the category list table view.
613
+	 */
614
+	protected function _set_list_table_views_category_list()
615
+	{
616
+		$this->_views = array(
617
+			'all' => array(
618
+				'slug'        => 'all',
619
+				'label'       => esc_html__('All', 'event_espresso'),
620
+				'count'       => 0,
621
+				'bulk_action' => array(
622
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
623
+				),
624
+			),
625
+		);
626
+	}
627
+
628
+
629
+	/**
630
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
631
+	 */
632
+	public function admin_init()
633
+	{
634
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
635
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
636
+			'event_espresso'
637
+		);
638
+	}
639
+
640
+
641
+	/**
642
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
643
+	 * group.
644
+	 */
645
+	public function admin_notices()
646
+	{
647
+	}
648
+
649
+
650
+	/**
651
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
652
+	 * this admin page group.
653
+	 */
654
+	public function admin_footer_scripts()
655
+	{
656
+	}
657
+
658
+
659
+	/**
660
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
661
+	 * warning (via EE_Error::add_error());
662
+	 *
663
+	 * @param  EE_Event $event Event object
664
+	 * @param string    $req_type
665
+	 * @return void
666
+	 * @throws EE_Error
667
+	 * @access public
668
+	 */
669
+	public function verify_event_edit($event = null, $req_type = '')
670
+	{
671
+		// don't need to do this when processing
672
+		if (! empty($req_type)) {
673
+			return;
674
+		}
675
+		// no event?
676
+		if (empty($event)) {
677
+			// set event
678
+			$event = $this->_cpt_model_obj;
679
+		}
680
+		// STILL no event?
681
+		if (! $event instanceof EE_Event) {
682
+			return;
683
+		}
684
+		$orig_status = $event->status();
685
+		// first check if event is active.
686
+		if ($orig_status === EEM_Event::cancelled
687
+			|| $orig_status === EEM_Event::postponed
688
+			|| $event->is_expired()
689
+			|| $event->is_inactive()
690
+		) {
691
+			return;
692
+		}
693
+		// made it here so it IS active... next check that any of the tickets are sold.
694
+		if ($event->is_sold_out(true)) {
695
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
696
+				EE_Error::add_attention(
697
+					sprintf(
698
+						esc_html__(
699
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
700
+							'event_espresso'
701
+						),
702
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
703
+					)
704
+				);
705
+			}
706
+			return;
707
+		} elseif ($orig_status === EEM_Event::sold_out) {
708
+			EE_Error::add_attention(
709
+				sprintf(
710
+					esc_html__(
711
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
712
+						'event_espresso'
713
+					),
714
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
715
+				)
716
+			);
717
+		}
718
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
719
+		if (! $event->tickets_on_sale()) {
720
+			return;
721
+		}
722
+		// made it here so show warning
723
+		$this->_edit_event_warning();
724
+	}
725
+
726
+
727
+	/**
728
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
729
+	 * When needed, hook this into a EE_Error::add_error() notice.
730
+	 *
731
+	 * @access protected
732
+	 * @return void
733
+	 */
734
+	protected function _edit_event_warning()
735
+	{
736
+		// we don't want to add warnings during these requests
737
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
738
+			return;
739
+		}
740
+		EE_Error::add_attention(
741
+			sprintf(
742
+				esc_html__(
743
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
744
+					'event_espresso'
745
+				),
746
+				'<a class="espresso-help-tab-lnk">',
747
+				'</a>'
748
+			)
749
+		);
750
+	}
751
+
752
+
753
+	/**
754
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
755
+	 * Otherwise, do the normal logic
756
+	 *
757
+	 * @return string
758
+	 * @throws \EE_Error
759
+	 */
760
+	protected function _create_new_cpt_item()
761
+	{
762
+		$has_timezone_string = get_option('timezone_string');
763
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
764
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
765
+			EE_Error::add_attention(
766
+				sprintf(
767
+					__(
768
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
769
+						'event_espresso'
770
+					),
771
+					'<br>',
772
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
773
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
774
+					. '</select>',
775
+					'<button class="button button-secondary timezone-submit">',
776
+					'</button><span class="spinner"></span>'
777
+				),
778
+				__FILE__,
779
+				__FUNCTION__,
780
+				__LINE__
781
+			);
782
+		}
783
+		return parent::_create_new_cpt_item();
784
+	}
785
+
786
+
787
+	/**
788
+	 * Sets the _views property for the default route in this admin page group.
789
+	 */
790
+	protected function _set_list_table_views_default()
791
+	{
792
+		$this->_views = array(
793
+			'all'   => array(
794
+				'slug'        => 'all',
795
+				'label'       => esc_html__('View All Events', 'event_espresso'),
796
+				'count'       => 0,
797
+				'bulk_action' => array(
798
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
799
+				),
800
+			),
801
+			'draft' => array(
802
+				'slug'        => 'draft',
803
+				'label'       => esc_html__('Draft', 'event_espresso'),
804
+				'count'       => 0,
805
+				'bulk_action' => array(
806
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
807
+				),
808
+			),
809
+		);
810
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
811
+			$this->_views['trash'] = array(
812
+				'slug'        => 'trash',
813
+				'label'       => esc_html__('Trash', 'event_espresso'),
814
+				'count'       => 0,
815
+				'bulk_action' => array(
816
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
817
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
818
+				),
819
+			);
820
+		}
821
+	}
822
+
823
+
824
+	/**
825
+	 * Provides the legend item array for the default list table view.
826
+	 *
827
+	 * @return array
828
+	 */
829
+	protected function _event_legend_items()
830
+	{
831
+		$items = array(
832
+			'view_details'   => array(
833
+				'class' => 'dashicons dashicons-search',
834
+				'desc'  => esc_html__('View Event', 'event_espresso'),
835
+			),
836
+			'edit_event'     => array(
837
+				'class' => 'ee-icon ee-icon-calendar-edit',
838
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
839
+			),
840
+			'view_attendees' => array(
841
+				'class' => 'dashicons dashicons-groups',
842
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
843
+			),
844
+		);
845
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
846
+		$statuses = array(
847
+			'sold_out_status'  => array(
848
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
849
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
850
+			),
851
+			'active_status'    => array(
852
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
853
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
854
+			),
855
+			'upcoming_status'  => array(
856
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
857
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
858
+			),
859
+			'postponed_status' => array(
860
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
861
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
862
+			),
863
+			'cancelled_status' => array(
864
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
865
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
866
+			),
867
+			'expired_status'   => array(
868
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
869
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
870
+			),
871
+			'inactive_status'  => array(
872
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
873
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
874
+			),
875
+		);
876
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
877
+		return array_merge($items, $statuses);
878
+	}
879
+
880
+
881
+	/**
882
+	 * @return EEM_Event
883
+	 */
884
+	private function _event_model()
885
+	{
886
+		if (! $this->_event_model instanceof EEM_Event) {
887
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
888
+		}
889
+		return $this->_event_model;
890
+	}
891
+
892
+
893
+	/**
894
+	 * Adds extra buttons to the WP CPT permalink field row.
895
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
896
+	 *
897
+	 * @param  string $return    the current html
898
+	 * @param  int    $id        the post id for the page
899
+	 * @param  string $new_title What the title is
900
+	 * @param  string $new_slug  what the slug is
901
+	 * @return string            The new html string for the permalink area
902
+	 */
903
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
904
+	{
905
+		// make sure this is only when editing
906
+		if (! empty($id)) {
907
+			$post = get_post($id);
908
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
909
+					   . esc_html__('Shortcode', 'event_espresso')
910
+					   . '</a> ';
911
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
912
+					   . $post->ID
913
+					   . ']">';
914
+		}
915
+		return $return;
916
+	}
917
+
918
+
919
+	/**
920
+	 * _events_overview_list_table
921
+	 * This contains the logic for showing the events_overview list
922
+	 *
923
+	 * @access protected
924
+	 * @return void
925
+	 * @throws \EE_Error
926
+	 */
927
+	protected function _events_overview_list_table()
928
+	{
929
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
930
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
931
+			? (array) $this->_template_args['after_list_table']
932
+			: array();
933
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
934
+				. EEH_Template::get_button_or_link(
935
+					get_post_type_archive_link('espresso_events'),
936
+					esc_html__("View Event Archive Page", "event_espresso"),
937
+					'button'
938
+				);
939
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
940
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
941
+			'create_new',
942
+			'add',
943
+			array(),
944
+			'add-new-h2'
945
+		);
946
+		$this->display_admin_list_table_page_with_no_sidebar();
947
+	}
948
+
949
+
950
+	/**
951
+	 * this allows for extra misc actions in the default WP publish box
952
+	 *
953
+	 * @return void
954
+	 */
955
+	public function extra_misc_actions_publish_box()
956
+	{
957
+		$this->_generate_publish_box_extra_content();
958
+	}
959
+
960
+
961
+	/**
962
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
963
+	 * saved.
964
+	 * Typically you would use this to save any additional data.
965
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
966
+	 * ALSO very important.  When a post transitions from scheduled to published,
967
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
968
+	 * other meta saves. So MAKE sure that you handle this accordingly.
969
+	 *
970
+	 * @access protected
971
+	 * @abstract
972
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
973
+	 * @param  object $post    The post object of the cpt that was saved.
974
+	 * @return void
975
+	 * @throws \EE_Error
976
+	 */
977
+	protected function _insert_update_cpt_item($post_id, $post)
978
+	{
979
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
980
+			// get out we're not processing an event save.
981
+			return;
982
+		}
983
+		$event_values = array(
984
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
985
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
986
+			'EVT_additional_limit'            => min(
987
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
988
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
989
+			),
990
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
991
+				? $this->_req_data['EVT_default_registration_status']
992
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
993
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
994
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
995
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
996
+				? $this->_req_data['timezone_string'] : null,
997
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
998
+				? $this->_req_data['externalURL'] : null,
999
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1000
+				? $this->_req_data['event_phone'] : null,
1001
+		);
1002
+		// update event
1003
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1004
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1005
+		$get_one_where = array(
1006
+			$this->_event_model()->primary_key_name() => $post_id,
1007
+			'OR'                                      => array(
1008
+				'status'   => $post->post_status,
1009
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1010
+				// but the returned object here has a status of "publish", so use the original post status as well
1011
+				'status*1' => $this->_req_data['original_post_status'],
1012
+			),
1013
+		);
1014
+		$event = $this->_event_model()->get_one(array($get_one_where));
1015
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1016
+		$event_update_callbacks = apply_filters(
1017
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1018
+			array(
1019
+				array($this, '_default_venue_update'),
1020
+				array($this, '_default_tickets_update'),
1021
+			)
1022
+		);
1023
+		$att_success = true;
1024
+		foreach ($event_update_callbacks as $e_callback) {
1025
+			$_success = is_callable($e_callback)
1026
+				? call_user_func($e_callback, $event, $this->_req_data)
1027
+				: false;
1028
+			// if ANY of these updates fail then we want the appropriate global error message
1029
+			$att_success = ! $att_success ? $att_success : $_success;
1030
+		}
1031
+		// any errors?
1032
+		if ($success && false === $att_success) {
1033
+			EE_Error::add_error(
1034
+				esc_html__(
1035
+					'Event Details saved successfully but something went wrong with saving attachments.',
1036
+					'event_espresso'
1037
+				),
1038
+				__FILE__,
1039
+				__FUNCTION__,
1040
+				__LINE__
1041
+			);
1042
+		} elseif ($success === false) {
1043
+			EE_Error::add_error(
1044
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1045
+				__FILE__,
1046
+				__FUNCTION__,
1047
+				__LINE__
1048
+			);
1049
+		}
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 * @see parent::restore_item()
1055
+	 * @param int $post_id
1056
+	 * @param int $revision_id
1057
+	 */
1058
+	protected function _restore_cpt_item($post_id, $revision_id)
1059
+	{
1060
+		// copy existing event meta to new post
1061
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1062
+		if ($post_evt instanceof EE_Event) {
1063
+			// meta revision restore
1064
+			$post_evt->restore_revision($revision_id);
1065
+			// related objs restore
1066
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1067
+		}
1068
+	}
1069
+
1070
+
1071
+	/**
1072
+	 * Attach the venue to the Event
1073
+	 *
1074
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1075
+	 * @param  array     $data   The request data from the form
1076
+	 * @return bool           Success or fail.
1077
+	 */
1078
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1079
+	{
1080
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1081
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1082
+		$rows_affected = null;
1083
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1084
+		// very important.  If we don't have a venue name...
1085
+		// then we'll get out because not necessary to create empty venue
1086
+		if (empty($data['venue_title'])) {
1087
+			return false;
1088
+		}
1089
+		$venue_array = array(
1090
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1091
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1092
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1093
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1094
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1095
+				: null,
1096
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1097
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1098
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1099
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1100
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1101
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1102
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1103
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1104
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1105
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1106
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1107
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1108
+			'status'              => 'publish',
1109
+		);
1110
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1111
+		if (! empty($venue_id)) {
1112
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1113
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1114
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1115
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1116
+			return $rows_affected > 0 ? true : false;
1117
+		} else {
1118
+			// we insert the venue
1119
+			$venue_id = $venue_model->insert($venue_array);
1120
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1121
+			return ! empty($venue_id) ? true : false;
1122
+		}
1123
+		// when we have the ancestor come in it's already been handled by the revision save.
1124
+	}
1125
+
1126
+
1127
+	/**
1128
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1129
+	 *
1130
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1131
+	 * @param  array    $data   The request data from the form
1132
+	 * @return array
1133
+	 */
1134
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1135
+	{
1136
+		$success = true;
1137
+		$saved_dtt = null;
1138
+		$saved_tickets = array();
1139
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1140
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1141
+			// trim all values to ensure any excess whitespace is removed.
1142
+			$dtt = array_map('trim', $dtt);
1143
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1144
+				: $dtt['DTT_EVT_start'];
1145
+			$datetime_values = array(
1146
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1147
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1148
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1149
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1150
+				'DTT_order'     => $row,
1151
+			);
1152
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1153
+			if (! empty($dtt['DTT_ID'])) {
1154
+				$DTM = EE_Registry::instance()
1155
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1156
+								  ->get_one_by_ID($dtt['DTT_ID']);
1157
+				$DTM->set_date_format($incoming_date_formats[0]);
1158
+				$DTM->set_time_format($incoming_date_formats[1]);
1159
+				foreach ($datetime_values as $field => $value) {
1160
+					$DTM->set($field, $value);
1161
+				}
1162
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1163
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1164
+			} else {
1165
+				$DTM = EE_Registry::instance()->load_class(
1166
+					'Datetime',
1167
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1168
+					false,
1169
+					false
1170
+				);
1171
+				foreach ($datetime_values as $field => $value) {
1172
+					$DTM->set($field, $value);
1173
+				}
1174
+			}
1175
+			$DTM->save();
1176
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1177
+			// load DTT helper
1178
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1179
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1180
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1181
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1182
+				$DTT->save();
1183
+			}
1184
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1185
+			$saved_dtt = $DTT;
1186
+			$success = ! $success ? $success : $DTT;
1187
+			// if ANY of these updates fail then we want the appropriate global error message.
1188
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1189
+		}
1190
+		// no dtts get deleted so we don't do any of that logic here.
1191
+		// update tickets next
1192
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1193
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1194
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1195
+			$update_prices = false;
1196
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1197
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1198
+			// trim inputs to ensure any excess whitespace is removed.
1199
+			$tkt = array_map('trim', $tkt);
1200
+			if (empty($tkt['TKT_start_date'])) {
1201
+				// let's use now in the set timezone.
1202
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1203
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1204
+			}
1205
+			if (empty($tkt['TKT_end_date'])) {
1206
+				// use the start date of the first datetime
1207
+				$dtt = $evtobj->first_datetime();
1208
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1209
+					$incoming_date_formats[0],
1210
+					$incoming_date_formats[1]
1211
+				);
1212
+			}
1213
+			$TKT_values = array(
1214
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1215
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1216
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1217
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1218
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1219
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1220
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1221
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1222
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1223
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1224
+				'TKT_row'         => $row,
1225
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1226
+				'TKT_price'       => $ticket_price,
1227
+			);
1228
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1229
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1230
+				$TKT_values['TKT_ID'] = 0;
1231
+				$TKT_values['TKT_is_default'] = 0;
1232
+				$TKT_values['TKT_price'] = $ticket_price;
1233
+				$update_prices = true;
1234
+			}
1235
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1236
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1237
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1238
+			if (! empty($tkt['TKT_ID'])) {
1239
+				$TKT = EE_Registry::instance()
1240
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1241
+								  ->get_one_by_ID($tkt['TKT_ID']);
1242
+				if ($TKT instanceof EE_Ticket) {
1243
+					$ticket_sold = $TKT->count_related(
1244
+						'Registration',
1245
+						array(
1246
+							array(
1247
+								'STS_ID' => array(
1248
+									'NOT IN',
1249
+									array(EEM_Registration::status_id_incomplete),
1250
+								),
1251
+							),
1252
+						)
1253
+					) > 0 ? true : false;
1254
+					// let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1255
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1256
+									  && ! $TKT->get('TKT_deleted');
1257
+					$TKT->set_date_format($incoming_date_formats[0]);
1258
+					$TKT->set_time_format($incoming_date_formats[1]);
1259
+					// set new values
1260
+					foreach ($TKT_values as $field => $value) {
1261
+						if ($field == 'TKT_qty') {
1262
+							$TKT->set_qty($value);
1263
+						} else {
1264
+							$TKT->set($field, $value);
1265
+						}
1266
+					}
1267
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1268
+					if ($create_new_TKT) {
1269
+						// archive the old ticket first
1270
+						$TKT->set('TKT_deleted', 1);
1271
+						$TKT->save();
1272
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1273
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1274
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1275
+						$TKT = clone $TKT;
1276
+						$TKT->set('TKT_ID', 0);
1277
+						$TKT->set('TKT_deleted', 0);
1278
+						$TKT->set('TKT_price', $ticket_price);
1279
+						$TKT->set('TKT_sold', 0);
1280
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1281
+						$update_prices = true;
1282
+					}
1283
+					// make sure price is set if it hasn't been already
1284
+					$TKT->set('TKT_price', $ticket_price);
1285
+				}
1286
+			} else {
1287
+				// no TKT_id so a new TKT
1288
+				$TKT_values['TKT_price'] = $ticket_price;
1289
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1290
+				if ($TKT instanceof EE_Ticket) {
1291
+					// need to reset values to properly account for the date formats
1292
+					$TKT->set_date_format($incoming_date_formats[0]);
1293
+					$TKT->set_time_format($incoming_date_formats[1]);
1294
+					$TKT->set_timezone($evtobj->get_timezone());
1295
+					// set new values
1296
+					foreach ($TKT_values as $field => $value) {
1297
+						if ($field == 'TKT_qty') {
1298
+							$TKT->set_qty($value);
1299
+						} else {
1300
+							$TKT->set($field, $value);
1301
+						}
1302
+					}
1303
+					$update_prices = true;
1304
+				}
1305
+			}
1306
+			// cap ticket qty by datetime reg limits
1307
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1308
+			// update ticket.
1309
+			$TKT->save();
1310
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1311
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1312
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1313
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1314
+				$TKT->save();
1315
+			}
1316
+			// initially let's add the ticket to the dtt
1317
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1318
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1319
+			// add prices to ticket
1320
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1321
+		}
1322
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1323
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1324
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1325
+		foreach ($tickets_removed as $id) {
1326
+			$id = absint($id);
1327
+			// get the ticket for this id
1328
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1329
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1330
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1331
+			foreach ($dtts as $dtt) {
1332
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1333
+			}
1334
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1335
+			$tkt_to_remove->delete_related_permanently('Price');
1336
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1337
+			$tkt_to_remove->delete_permanently();
1338
+		}
1339
+		return array($saved_dtt, $saved_tickets);
1340
+	}
1341
+
1342
+
1343
+	/**
1344
+	 * This attaches a list of given prices to a ticket.
1345
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1346
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1347
+	 * price info and prices are automatically "archived" via the ticket.
1348
+	 *
1349
+	 * @access  private
1350
+	 * @param array     $prices     Array of prices from the form.
1351
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1352
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1353
+	 * @return  void
1354
+	 */
1355
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1356
+	{
1357
+		foreach ($prices as $row => $prc) {
1358
+			$PRC_values = array(
1359
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1360
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1361
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1362
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1363
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1364
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1365
+				'PRC_order'      => $row,
1366
+			);
1367
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1368
+				$PRC_values['PRC_ID'] = 0;
1369
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1370
+			} else {
1371
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1372
+				// update this price with new values
1373
+				foreach ($PRC_values as $field => $newprc) {
1374
+					$PRC->set($field, $newprc);
1375
+				}
1376
+				$PRC->save();
1377
+			}
1378
+			$ticket->_add_relation_to($PRC, 'Price');
1379
+		}
1380
+	}
1381
+
1382
+
1383
+	/**
1384
+	 * Add in our autosave ajax handlers
1385
+	 *
1386
+	 */
1387
+	protected function _ee_autosave_create_new()
1388
+	{
1389
+	}
1390
+
1391
+
1392
+	/**
1393
+	 * More autosave handlers.
1394
+	 */
1395
+	protected function _ee_autosave_edit()
1396
+	{
1397
+		return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 *    _generate_publish_box_extra_content
1403
+	 */
1404
+	private function _generate_publish_box_extra_content()
1405
+	{
1406
+		// load formatter helper
1407
+		// args for getting related registrations
1408
+		$approved_query_args = array(
1409
+			array(
1410
+				'REG_deleted' => 0,
1411
+				'STS_ID'      => EEM_Registration::status_id_approved,
1412
+			),
1413
+		);
1414
+		$not_approved_query_args = array(
1415
+			array(
1416
+				'REG_deleted' => 0,
1417
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1418
+			),
1419
+		);
1420
+		$pending_payment_query_args = array(
1421
+			array(
1422
+				'REG_deleted' => 0,
1423
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1424
+			),
1425
+		);
1426
+		// publish box
1427
+		$publish_box_extra_args = array(
1428
+			'view_approved_reg_url'        => add_query_arg(
1429
+				array(
1430
+					'action'      => 'default',
1431
+					'event_id'    => $this->_cpt_model_obj->ID(),
1432
+					'_reg_status' => EEM_Registration::status_id_approved,
1433
+				),
1434
+				REG_ADMIN_URL
1435
+			),
1436
+			'view_not_approved_reg_url'    => add_query_arg(
1437
+				array(
1438
+					'action'      => 'default',
1439
+					'event_id'    => $this->_cpt_model_obj->ID(),
1440
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1441
+				),
1442
+				REG_ADMIN_URL
1443
+			),
1444
+			'view_pending_payment_reg_url' => add_query_arg(
1445
+				array(
1446
+					'action'      => 'default',
1447
+					'event_id'    => $this->_cpt_model_obj->ID(),
1448
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1449
+				),
1450
+				REG_ADMIN_URL
1451
+			),
1452
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1453
+				'Registration',
1454
+				$approved_query_args
1455
+			),
1456
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1457
+				'Registration',
1458
+				$not_approved_query_args
1459
+			),
1460
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1461
+				'Registration',
1462
+				$pending_payment_query_args
1463
+			),
1464
+			'misc_pub_section_class'       => apply_filters(
1465
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1466
+				'misc-pub-section'
1467
+			),
1468
+		);
1469
+		ob_start();
1470
+		do_action(
1471
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1472
+			$this->_cpt_model_obj
1473
+		);
1474
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1475
+		// load template
1476
+		EEH_Template::display_template(
1477
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1478
+			$publish_box_extra_args
1479
+		);
1480
+	}
1481
+
1482
+
1483
+	/**
1484
+	 * @return EE_Event
1485
+	 */
1486
+	public function get_event_object()
1487
+	{
1488
+		return $this->_cpt_model_obj;
1489
+	}
1490
+
1491
+
1492
+
1493
+
1494
+	/** METABOXES * */
1495
+	/**
1496
+	 * _register_event_editor_meta_boxes
1497
+	 * add all metaboxes related to the event_editor
1498
+	 *
1499
+	 * @return void
1500
+	 */
1501
+	protected function _register_event_editor_meta_boxes()
1502
+	{
1503
+		$this->verify_cpt_object();
1504
+		add_meta_box(
1505
+			'espresso_event_editor_tickets',
1506
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1507
+			array($this, 'ticket_metabox'),
1508
+			$this->page_slug,
1509
+			'normal',
1510
+			'high'
1511
+		);
1512
+		add_meta_box(
1513
+			'espresso_event_editor_event_options',
1514
+			esc_html__('Event Registration Options', 'event_espresso'),
1515
+			array($this, 'registration_options_meta_box'),
1516
+			$this->page_slug,
1517
+			'side',
1518
+			'default'
1519
+		);
1520
+		// NOTE: if you're looking for other metaboxes in here,
1521
+		// where a metabox has a related management page in the admin
1522
+		// you will find it setup in the related management page's "_Hooks" file.
1523
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1524
+	}
1525
+
1526
+
1527
+	/**
1528
+	 * @throws DomainException
1529
+	 * @throws EE_Error
1530
+	 */
1531
+	public function ticket_metabox()
1532
+	{
1533
+		$existing_datetime_ids = $existing_ticket_ids = array();
1534
+		// defaults for template args
1535
+		$template_args = array(
1536
+			'existing_datetime_ids'    => '',
1537
+			'event_datetime_help_link' => '',
1538
+			'ticket_options_help_link' => '',
1539
+			'time'                     => null,
1540
+			'ticket_rows'              => '',
1541
+			'existing_ticket_ids'      => '',
1542
+			'total_ticket_rows'        => 1,
1543
+			'ticket_js_structure'      => '',
1544
+			'trash_icon'               => 'ee-lock-icon',
1545
+			'disabled'                 => '',
1546
+		);
1547
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1548
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1549
+		/**
1550
+		 * 1. Start with retrieving Datetimes
1551
+		 * 2. Fore each datetime get related tickets
1552
+		 * 3. For each ticket get related prices
1553
+		 */
1554
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1555
+		/** @type EE_Datetime $first_datetime */
1556
+		$first_datetime = reset($times);
1557
+		// do we get related tickets?
1558
+		if ($first_datetime instanceof EE_Datetime
1559
+			&& $first_datetime->ID() !== 0
1560
+		) {
1561
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1562
+			$template_args['time'] = $first_datetime;
1563
+			$related_tickets = $first_datetime->tickets(
1564
+				array(
1565
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1566
+					'default_where_conditions' => 'none',
1567
+				)
1568
+			);
1569
+			if (! empty($related_tickets)) {
1570
+				$template_args['total_ticket_rows'] = count($related_tickets);
1571
+				$row = 0;
1572
+				foreach ($related_tickets as $ticket) {
1573
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1574
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1575
+					$row++;
1576
+				}
1577
+			} else {
1578
+				$template_args['total_ticket_rows'] = 1;
1579
+				/** @type EE_Ticket $ticket */
1580
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1581
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1582
+			}
1583
+		} else {
1584
+			$template_args['time'] = $times[0];
1585
+			/** @type EE_Ticket $ticket */
1586
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1587
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1588
+			// NOTE: we're just sending the first default row
1589
+			// (decaf can't manage default tickets so this should be sufficient);
1590
+		}
1591
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1592
+			'event_editor_event_datetimes_help_tab'
1593
+		);
1594
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1595
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1596
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1597
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1598
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1599
+			true
1600
+		);
1601
+		$template = apply_filters(
1602
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1603
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1604
+		);
1605
+		EEH_Template::display_template($template, $template_args);
1606
+	}
1607
+
1608
+
1609
+	/**
1610
+	 * Setup an individual ticket form for the decaf event editor page
1611
+	 *
1612
+	 * @access private
1613
+	 * @param  EE_Ticket $ticket   the ticket object
1614
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1615
+	 * @param int        $row
1616
+	 * @return string generated html for the ticket row.
1617
+	 */
1618
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1619
+	{
1620
+		$template_args = array(
1621
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1622
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1623
+				: '',
1624
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1625
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1626
+			'TKT_name'            => $ticket->get('TKT_name'),
1627
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1628
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1629
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1630
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1631
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1632
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1633
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1634
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1635
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1636
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1637
+				: ' disabled=disabled',
1638
+		);
1639
+		$price = $ticket->ID() !== 0
1640
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1641
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1642
+		$price_args = array(
1643
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1644
+			'PRC_amount'            => $price->get('PRC_amount'),
1645
+			'PRT_ID'                => $price->get('PRT_ID'),
1646
+			'PRC_ID'                => $price->get('PRC_ID'),
1647
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1648
+		);
1649
+		// make sure we have default start and end dates if skeleton
1650
+		// handle rows that should NOT be empty
1651
+		if (empty($template_args['TKT_start_date'])) {
1652
+			// if empty then the start date will be now.
1653
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1654
+		}
1655
+		if (empty($template_args['TKT_end_date'])) {
1656
+			// get the earliest datetime (if present);
1657
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1658
+				? $this->_cpt_model_obj->get_first_related(
1659
+					'Datetime',
1660
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1661
+				)
1662
+				: null;
1663
+			if (! empty($earliest_dtt)) {
1664
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1665
+			} else {
1666
+				$template_args['TKT_end_date'] = date(
1667
+					'Y-m-d h:i a',
1668
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1669
+				);
1670
+			}
1671
+		}
1672
+		$template_args = array_merge($template_args, $price_args);
1673
+		$template = apply_filters(
1674
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1675
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1676
+			$ticket
1677
+		);
1678
+		return EEH_Template::display_template($template, $template_args, true);
1679
+	}
1680
+
1681
+
1682
+	/**
1683
+	 * @throws DomainException
1684
+	 */
1685
+	public function registration_options_meta_box()
1686
+	{
1687
+		$yes_no_values = array(
1688
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1689
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1690
+		);
1691
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1692
+			array(
1693
+				EEM_Registration::status_id_cancelled,
1694
+				EEM_Registration::status_id_declined,
1695
+				EEM_Registration::status_id_incomplete,
1696
+			),
1697
+			true
1698
+		);
1699
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1700
+		$template_args['_event'] = $this->_cpt_model_obj;
1701
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1702
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1703
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1704
+			'default_reg_status',
1705
+			$default_reg_status_values,
1706
+			$this->_cpt_model_obj->default_registration_status()
1707
+		);
1708
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1709
+			'display_desc',
1710
+			$yes_no_values,
1711
+			$this->_cpt_model_obj->display_description()
1712
+		);
1713
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1714
+			'display_ticket_selector',
1715
+			$yes_no_values,
1716
+			$this->_cpt_model_obj->display_ticket_selector(),
1717
+			'',
1718
+			'',
1719
+			false
1720
+		);
1721
+		$template_args['additional_registration_options'] = apply_filters(
1722
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1723
+			'',
1724
+			$template_args,
1725
+			$yes_no_values,
1726
+			$default_reg_status_values
1727
+		);
1728
+		EEH_Template::display_template(
1729
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1730
+			$template_args
1731
+		);
1732
+	}
1733
+
1734
+
1735
+	/**
1736
+	 * _get_events()
1737
+	 * This method simply returns all the events (for the given _view and paging)
1738
+	 *
1739
+	 * @access public
1740
+	 * @param int  $per_page     count of items per page (20 default);
1741
+	 * @param int  $current_page what is the current page being viewed.
1742
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1743
+	 *                           If FALSE then we return an array of event objects
1744
+	 *                           that match the given _view and paging parameters.
1745
+	 * @return array an array of event objects.
1746
+	 */
1747
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1748
+	{
1749
+		$EEME = $this->_event_model();
1750
+		$offset = ($current_page - 1) * $per_page;
1751
+		$limit = $count ? null : $offset . ',' . $per_page;
1752
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1753
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1754
+		if (isset($this->_req_data['month_range'])) {
1755
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1756
+			// simulate the FIRST day of the month, that fixes issues for months like February
1757
+			// where PHP doesn't know what to assume for date.
1758
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1759
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1760
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1761
+		}
1762
+		$where = array();
1763
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1764
+		// determine what post_status our condition will have for the query.
1765
+		switch ($status) {
1766
+			case 'month':
1767
+			case 'today':
1768
+			case null:
1769
+			case 'all':
1770
+				break;
1771
+			case 'draft':
1772
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1773
+				break;
1774
+			default:
1775
+				$where['status'] = $status;
1776
+		}
1777
+		// categories?
1778
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1779
+			? $this->_req_data['EVT_CAT'] : null;
1780
+		if (! empty($category)) {
1781
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1782
+			$where['Term_Taxonomy.term_id'] = $category;
1783
+		}
1784
+		// date where conditions
1785
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1786
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1787
+			$DateTime = new DateTime(
1788
+				$year_r . '-' . $month_r . '-01 00:00:00',
1789
+				new DateTimeZone('UTC')
1790
+			);
1791
+			$start = $DateTime->getTimestamp();
1792
+			// set the datetime to be the end of the month
1793
+			$DateTime->setDate(
1794
+				$year_r,
1795
+				$month_r,
1796
+				$DateTime->format('t')
1797
+			)->setTime(23, 59, 59);
1798
+			$end = $DateTime->getTimestamp();
1799
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1800
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1801
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1802
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1803
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1804
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1805
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1806
+			$now = date('Y-m-01');
1807
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1808
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1809
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1810
+							->setTime(23, 59, 59)
1811
+							->format(implode(' ', $start_formats));
1812
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1813
+		}
1814
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1815
+			$where['EVT_wp_user'] = get_current_user_id();
1816
+		} else {
1817
+			if (! isset($where['status'])) {
1818
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1819
+					$where['OR'] = array(
1820
+						'status*restrict_private' => array('!=', 'private'),
1821
+						'AND'                     => array(
1822
+							'status*inclusive' => array('=', 'private'),
1823
+							'EVT_wp_user'      => get_current_user_id(),
1824
+						),
1825
+					);
1826
+				}
1827
+			}
1828
+		}
1829
+		if (isset($this->_req_data['EVT_wp_user'])) {
1830
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1831
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1832
+			) {
1833
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1834
+			}
1835
+		}
1836
+		// search query handling
1837
+		if (isset($this->_req_data['s'])) {
1838
+			$search_string = '%' . $this->_req_data['s'] . '%';
1839
+			$where['OR'] = array(
1840
+				'EVT_name'       => array('LIKE', $search_string),
1841
+				'EVT_desc'       => array('LIKE', $search_string),
1842
+				'EVT_short_desc' => array('LIKE', $search_string),
1843
+			);
1844
+		}
1845
+		// filter events by venue.
1846
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1847
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1848
+		}
1849
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1850
+		$query_params = apply_filters(
1851
+			'FHEE__Events_Admin_Page__get_events__query_params',
1852
+			array(
1853
+				$where,
1854
+				'limit'    => $limit,
1855
+				'order_by' => $orderby,
1856
+				'order'    => $order,
1857
+				'group_by' => 'EVT_ID',
1858
+			),
1859
+			$this->_req_data
1860
+		);
1861
+
1862
+		// let's first check if we have special requests coming in.
1863
+		if (isset($this->_req_data['active_status'])) {
1864
+			switch ($this->_req_data['active_status']) {
1865
+				case 'upcoming':
1866
+					return $EEME->get_upcoming_events($query_params, $count);
1867
+					break;
1868
+				case 'expired':
1869
+					return $EEME->get_expired_events($query_params, $count);
1870
+					break;
1871
+				case 'active':
1872
+					return $EEME->get_active_events($query_params, $count);
1873
+					break;
1874
+				case 'inactive':
1875
+					return $EEME->get_inactive_events($query_params, $count);
1876
+					break;
1877
+			}
1878
+		}
1879
+
1880
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1881
+		return $events;
1882
+	}
1883
+
1884
+
1885
+	/**
1886
+	 * handling for WordPress CPT actions (trash, restore, delete)
1887
+	 *
1888
+	 * @param string $post_id
1889
+	 */
1890
+	public function trash_cpt_item($post_id)
1891
+	{
1892
+		$this->_req_data['EVT_ID'] = $post_id;
1893
+		$this->_trash_or_restore_event('trash', false);
1894
+	}
1895
+
1896
+
1897
+	/**
1898
+	 * @param string $post_id
1899
+	 */
1900
+	public function restore_cpt_item($post_id)
1901
+	{
1902
+		$this->_req_data['EVT_ID'] = $post_id;
1903
+		$this->_trash_or_restore_event('draft', false);
1904
+	}
1905
+
1906
+
1907
+	/**
1908
+	 * @param string $post_id
1909
+	 */
1910
+	public function delete_cpt_item($post_id)
1911
+	{
1912
+		$this->_req_data['EVT_ID'] = $post_id;
1913
+		$this->_delete_event(false);
1914
+	}
1915
+
1916
+
1917
+	/**
1918
+	 * _trash_or_restore_event
1919
+	 *
1920
+	 * @access protected
1921
+	 * @param  string $event_status
1922
+	 * @param bool    $redirect_after
1923
+	 */
1924
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1925
+	{
1926
+		// determine the event id and set to array.
1927
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1928
+		// loop thru events
1929
+		if ($EVT_ID) {
1930
+			// clean status
1931
+			$event_status = sanitize_key($event_status);
1932
+			// grab status
1933
+			if (! empty($event_status)) {
1934
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1935
+			} else {
1936
+				$success = false;
1937
+				$msg = esc_html__(
1938
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1939
+					'event_espresso'
1940
+				);
1941
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1942
+			}
1943
+		} else {
1944
+			$success = false;
1945
+			$msg = esc_html__(
1946
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1947
+				'event_espresso'
1948
+			);
1949
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1950
+		}
1951
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1952
+		if ($redirect_after) {
1953
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1954
+		}
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 * _trash_or_restore_events
1960
+	 *
1961
+	 * @access protected
1962
+	 * @param  string $event_status
1963
+	 * @return void
1964
+	 */
1965
+	protected function _trash_or_restore_events($event_status = 'trash')
1966
+	{
1967
+		// clean status
1968
+		$event_status = sanitize_key($event_status);
1969
+		// grab status
1970
+		if (! empty($event_status)) {
1971
+			$success = true;
1972
+			// determine the event id and set to array.
1973
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1974
+			// loop thru events
1975
+			foreach ($EVT_IDs as $EVT_ID) {
1976
+				if ($EVT_ID = absint($EVT_ID)) {
1977
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1978
+					$success = $results !== false ? $success : false;
1979
+				} else {
1980
+					$msg = sprintf(
1981
+						esc_html__(
1982
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1983
+							'event_espresso'
1984
+						),
1985
+						$EVT_ID
1986
+					);
1987
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1988
+					$success = false;
1989
+				}
1990
+			}
1991
+		} else {
1992
+			$success = false;
1993
+			$msg = esc_html__(
1994
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1995
+				'event_espresso'
1996
+			);
1997
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
+		}
1999
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2000
+		$success = $success ? 2 : false;
2001
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2002
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2003
+	}
2004
+
2005
+
2006
+	/**
2007
+	 * _trash_or_restore_events
2008
+	 *
2009
+	 * @access  private
2010
+	 * @param  int    $EVT_ID
2011
+	 * @param  string $event_status
2012
+	 * @return bool
2013
+	 */
2014
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2015
+	{
2016
+		// grab event id
2017
+		if (! $EVT_ID) {
2018
+			$msg = esc_html__(
2019
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2020
+				'event_espresso'
2021
+			);
2022
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2023
+			return false;
2024
+		}
2025
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2026
+		// clean status
2027
+		$event_status = sanitize_key($event_status);
2028
+		// grab status
2029
+		if (empty($event_status)) {
2030
+			$msg = esc_html__(
2031
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2032
+				'event_espresso'
2033
+			);
2034
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2035
+			return false;
2036
+		}
2037
+		// was event trashed or restored ?
2038
+		switch ($event_status) {
2039
+			case 'draft':
2040
+				$action = 'restored from the trash';
2041
+				$hook = 'AHEE_event_restored_from_trash';
2042
+				break;
2043
+			case 'trash':
2044
+				$action = 'moved to the trash';
2045
+				$hook = 'AHEE_event_moved_to_trash';
2046
+				break;
2047
+			default:
2048
+				$action = 'updated';
2049
+				$hook = false;
2050
+		}
2051
+		// use class to change status
2052
+		$this->_cpt_model_obj->set_status($event_status);
2053
+		$success = $this->_cpt_model_obj->save();
2054
+		if ($success === false) {
2055
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2056
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2057
+			return false;
2058
+		}
2059
+		if ($hook) {
2060
+			do_action($hook);
2061
+		}
2062
+		return true;
2063
+	}
2064
+
2065
+
2066
+	/**
2067
+	 * _delete_event
2068
+	 *
2069
+	 * @access protected
2070
+	 * @param bool $redirect_after
2071
+	 */
2072
+	protected function _delete_event($redirect_after = true)
2073
+	{
2074
+		// determine the event id and set to array.
2075
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2076
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2077
+		// loop thru events
2078
+		if ($EVT_ID) {
2079
+			$success = $this->_permanently_delete_event($EVT_ID);
2080
+			// get list of events with no prices
2081
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2082
+			// remove this event from the list of events with no prices
2083
+			if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2084
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2085
+			}
2086
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2087
+		} else {
2088
+			$success = false;
2089
+			$msg = esc_html__(
2090
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2091
+				'event_espresso'
2092
+			);
2093
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2094
+		}
2095
+		if ($redirect_after) {
2096
+			$this->_redirect_after_action(
2097
+				$success,
2098
+				'Event',
2099
+				'deleted',
2100
+				array('action' => 'default', 'status' => 'trash')
2101
+			);
2102
+		}
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * _delete_events
2108
+	 *
2109
+	 * @access protected
2110
+	 * @return void
2111
+	 */
2112
+	protected function _delete_events()
2113
+	{
2114
+		$success = true;
2115
+		// get list of events with no prices
2116
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2117
+		// determine the event id and set to array.
2118
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2119
+		// loop thru events
2120
+		foreach ($EVT_IDs as $EVT_ID) {
2121
+			$EVT_ID = absint($EVT_ID);
2122
+			if ($EVT_ID) {
2123
+				$results = $this->_permanently_delete_event($EVT_ID);
2124
+				$success = $results !== false ? $success : false;
2125
+				// remove this event from the list of events with no prices
2126
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2127
+			} else {
2128
+				$success = false;
2129
+				$msg = esc_html__(
2130
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2131
+					'event_espresso'
2132
+				);
2133
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2134
+			}
2135
+		}
2136
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2137
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2138
+		$success = $success ? 2 : false;
2139
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2140
+	}
2141
+
2142
+
2143
+	/**
2144
+	 * _permanently_delete_event
2145
+	 *
2146
+	 * @access  private
2147
+	 * @param  int $EVT_ID
2148
+	 * @return bool
2149
+	 */
2150
+	private function _permanently_delete_event($EVT_ID = 0)
2151
+	{
2152
+		// grab event id
2153
+		if (! $EVT_ID) {
2154
+			$msg = esc_html__(
2155
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2156
+				'event_espresso'
2157
+			);
2158
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
+			return false;
2160
+		}
2161
+		if (! $this->_cpt_model_obj instanceof EE_Event
2162
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2163
+		) {
2164
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2165
+		}
2166
+		if (! $this->_cpt_model_obj instanceof EE_Event) {
2167
+			return false;
2168
+		}
2169
+		// need to delete related tickets and prices first.
2170
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2171
+		foreach ($datetimes as $datetime) {
2172
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2173
+			$tickets = $datetime->get_many_related('Ticket');
2174
+			foreach ($tickets as $ticket) {
2175
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2176
+				$ticket->delete_related_permanently('Price');
2177
+				$ticket->delete_permanently();
2178
+			}
2179
+			$datetime->delete();
2180
+		}
2181
+		// what about related venues or terms?
2182
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2183
+		foreach ($venues as $venue) {
2184
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2185
+		}
2186
+		// any attached question groups?
2187
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2188
+		if (! empty($question_groups)) {
2189
+			foreach ($question_groups as $question_group) {
2190
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2191
+			}
2192
+		}
2193
+		// Message Template Groups
2194
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2195
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2196
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2197
+		foreach ($term_taxonomies as $term_taxonomy) {
2198
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2199
+		}
2200
+		$success = $this->_cpt_model_obj->delete_permanently();
2201
+		// did it all go as planned ?
2202
+		if ($success) {
2203
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2204
+			EE_Error::add_success($msg);
2205
+		} else {
2206
+			$msg = sprintf(
2207
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2208
+				$EVT_ID
2209
+			);
2210
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
+			return false;
2212
+		}
2213
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2214
+		return true;
2215
+	}
2216
+
2217
+
2218
+	/**
2219
+	 * get total number of events
2220
+	 *
2221
+	 * @access public
2222
+	 * @return int
2223
+	 */
2224
+	public function total_events()
2225
+	{
2226
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2227
+		return $count;
2228
+	}
2229
+
2230
+
2231
+	/**
2232
+	 * get total number of draft events
2233
+	 *
2234
+	 * @access public
2235
+	 * @return int
2236
+	 */
2237
+	public function total_events_draft()
2238
+	{
2239
+		$where = array(
2240
+			'status' => array('IN', array('draft', 'auto-draft')),
2241
+		);
2242
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2243
+		return $count;
2244
+	}
2245
+
2246
+
2247
+	/**
2248
+	 * get total number of trashed events
2249
+	 *
2250
+	 * @access public
2251
+	 * @return int
2252
+	 */
2253
+	public function total_trashed_events()
2254
+	{
2255
+		$where = array(
2256
+			'status' => 'trash',
2257
+		);
2258
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2259
+		return $count;
2260
+	}
2261
+
2262
+
2263
+	/**
2264
+	 *    _default_event_settings
2265
+	 *    This generates the Default Settings Tab
2266
+	 *
2267
+	 * @return void
2268
+	 * @throws EE_Error
2269
+	 */
2270
+	protected function _default_event_settings()
2271
+	{
2272
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2273
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2274
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2275
+		$this->display_admin_page_with_sidebar();
2276
+	}
2277
+
2278
+
2279
+	/**
2280
+	 * Return the form for event settings.
2281
+	 *
2282
+	 * @return EE_Form_Section_Proper
2283
+	 * @throws EE_Error
2284
+	 */
2285
+	protected function _default_event_settings_form()
2286
+	{
2287
+		$registration_config = EE_Registry::instance()->CFG->registration;
2288
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2289
+			// exclude
2290
+			array(
2291
+				EEM_Registration::status_id_cancelled,
2292
+				EEM_Registration::status_id_declined,
2293
+				EEM_Registration::status_id_incomplete,
2294
+				EEM_Registration::status_id_wait_list,
2295
+			),
2296
+			true
2297
+		);
2298
+		return new EE_Form_Section_Proper(
2299
+			array(
2300
+				'name'            => 'update_default_event_settings',
2301
+				'html_id'         => 'update_default_event_settings',
2302
+				'html_class'      => 'form-table',
2303
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2304
+				'subsections'     => apply_filters(
2305
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2306
+					array(
2307
+						'default_reg_status'  => new EE_Select_Input(
2308
+							$registration_stati_for_selection,
2309
+							array(
2310
+								'default'         => isset($registration_config->default_STS_ID)
2311
+													 && array_key_exists(
2312
+														 $registration_config->default_STS_ID,
2313
+														 $registration_stati_for_selection
2314
+													 )
2315
+									? sanitize_text_field($registration_config->default_STS_ID)
2316
+									: EEM_Registration::status_id_pending_payment,
2317
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2318
+													 . EEH_Template::get_help_tab_link(
2319
+														 'default_settings_status_help_tab'
2320
+													 ),
2321
+								'html_help_text'  => esc_html__(
2322
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2323
+									'event_espresso'
2324
+								),
2325
+							)
2326
+						),
2327
+						'default_max_tickets' => new EE_Integer_Input(
2328
+							array(
2329
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2330
+									? $registration_config->default_maximum_number_of_tickets
2331
+									: EEM_Event::get_default_additional_limit(),
2332
+								'html_label_text' => esc_html__(
2333
+									'Default Maximum Tickets Allowed Per Order:',
2334
+									'event_espresso'
2335
+								)
2336
+													 . EEH_Template::get_help_tab_link(
2337
+														 'default_maximum_tickets_help_tab"'
2338
+													 ),
2339
+								'html_help_text'  => esc_html__(
2340
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2341
+									'event_espresso'
2342
+								),
2343
+							)
2344
+						),
2345
+					)
2346
+				),
2347
+			)
2348
+		);
2349
+	}
2350
+
2351
+
2352
+	/**
2353
+	 * _update_default_event_settings
2354
+	 *
2355
+	 * @access protected
2356
+	 * @return void
2357
+	 * @throws EE_Error
2358
+	 */
2359
+	protected function _update_default_event_settings()
2360
+	{
2361
+		$registration_config = EE_Registry::instance()->CFG->registration;
2362
+		$form = $this->_default_event_settings_form();
2363
+		if ($form->was_submitted()) {
2364
+			$form->receive_form_submission();
2365
+			if ($form->is_valid()) {
2366
+				$valid_data = $form->valid_data();
2367
+				if (isset($valid_data['default_reg_status'])) {
2368
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2369
+				}
2370
+				if (isset($valid_data['default_max_tickets'])) {
2371
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2372
+				}
2373
+				// update because data was valid!
2374
+				EE_Registry::instance()->CFG->update_espresso_config();
2375
+				EE_Error::overwrite_success();
2376
+				EE_Error::add_success(
2377
+					__('Default Event Settings were updated', 'event_espresso')
2378
+				);
2379
+			}
2380
+		}
2381
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2382
+	}
2383
+
2384
+
2385
+	/*************        Templates        *************/
2386
+	protected function _template_settings()
2387
+	{
2388
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2389
+		$this->_template_args['preview_img'] = '<img src="'
2390
+											   . EVENTS_ASSETS_URL
2391
+											   . '/images/'
2392
+											   . 'caffeinated_template_features.jpg" alt="'
2393
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2394
+											   . '" />';
2395
+		$this->_template_args['preview_text'] = '<strong>'
2396
+												. esc_html__(
2397
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2398
+													'event_espresso'
2399
+												) . '</strong>';
2400
+		$this->display_admin_caf_preview_page('template_settings_tab');
2401
+	}
2402
+
2403
+
2404
+	/** Event Category Stuff **/
2405
+	/**
2406
+	 * set the _category property with the category object for the loaded page.
2407
+	 *
2408
+	 * @access private
2409
+	 * @return void
2410
+	 */
2411
+	private function _set_category_object()
2412
+	{
2413
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2414
+			return;
2415
+		} //already have the category object so get out.
2416
+		// set default category object
2417
+		$this->_set_empty_category_object();
2418
+		// only set if we've got an id
2419
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2420
+			return;
2421
+		}
2422
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2423
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2424
+		if (! empty($term)) {
2425
+			$this->_category->category_name = $term->name;
2426
+			$this->_category->category_identifier = $term->slug;
2427
+			$this->_category->category_desc = $term->description;
2428
+			$this->_category->id = $term->term_id;
2429
+			$this->_category->parent = $term->parent;
2430
+		}
2431
+	}
2432
+
2433
+
2434
+	/**
2435
+	 * Clears out category properties.
2436
+	 */
2437
+	private function _set_empty_category_object()
2438
+	{
2439
+		$this->_category = new stdClass();
2440
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2441
+		$this->_category->id = $this->_category->parent = 0;
2442
+	}
2443
+
2444
+
2445
+	/**
2446
+	 * @throws EE_Error
2447
+	 */
2448
+	protected function _category_list_table()
2449
+	{
2450
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2451
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2452
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2453
+			'add_category',
2454
+			'add_category',
2455
+			array(),
2456
+			'add-new-h2'
2457
+		);
2458
+		$this->display_admin_list_table_page_with_sidebar();
2459
+	}
2460
+
2461
+
2462
+	/**
2463
+	 * Output category details view.
2464
+	 */
2465
+	protected function _category_details($view)
2466
+	{
2467
+		// load formatter helper
2468
+		// load field generator helper
2469
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2470
+		$this->_set_add_edit_form_tags($route);
2471
+		$this->_set_category_object();
2472
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2473
+		$delete_action = 'delete_category';
2474
+		// custom redirect
2475
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2476
+			array('action' => 'category_list'),
2477
+			$this->_admin_base_url
2478
+		);
2479
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2480
+		// take care of contents
2481
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2482
+		$this->display_admin_page_with_sidebar();
2483
+	}
2484
+
2485
+
2486
+	/**
2487
+	 * Output category details content.
2488
+	 */
2489
+	protected function _category_details_content()
2490
+	{
2491
+		$editor_args['category_desc'] = array(
2492
+			'type'          => 'wp_editor',
2493
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2494
+			'class'         => 'my_editor_custom',
2495
+			'wpeditor_args' => array('media_buttons' => false),
2496
+		);
2497
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2498
+		$all_terms = get_terms(
2499
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2500
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2501
+		);
2502
+		// setup category select for term parents.
2503
+		$category_select_values[] = array(
2504
+			'text' => esc_html__('No Parent', 'event_espresso'),
2505
+			'id'   => 0,
2506
+		);
2507
+		foreach ($all_terms as $term) {
2508
+			$category_select_values[] = array(
2509
+				'text' => $term->name,
2510
+				'id'   => $term->term_id,
2511
+			);
2512
+		}
2513
+		$category_select = EEH_Form_Fields::select_input(
2514
+			'category_parent',
2515
+			$category_select_values,
2516
+			$this->_category->parent
2517
+		);
2518
+		$template_args = array(
2519
+			'category'                 => $this->_category,
2520
+			'category_select'          => $category_select,
2521
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2522
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2523
+			'disable'                  => '',
2524
+			'disabled_message'         => false,
2525
+		);
2526
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2527
+		return EEH_Template::display_template($template, $template_args, true);
2528
+	}
2529
+
2530
+
2531
+	/**
2532
+	 * Handles deleting categories.
2533
+	 */
2534
+	protected function _delete_categories()
2535
+	{
2536
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2537
+			: (array) $this->_req_data['category_id'];
2538
+		foreach ($cat_ids as $cat_id) {
2539
+			$this->_delete_category($cat_id);
2540
+		}
2541
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2542
+		$query_args = array(
2543
+			'action' => 'category_list',
2544
+		);
2545
+		$this->_redirect_after_action(0, '', '', $query_args);
2546
+	}
2547
+
2548
+
2549
+	/**
2550
+	 * Handles deleting specific category.
2551
+	 *
2552
+	 * @param int $cat_id
2553
+	 */
2554
+	protected function _delete_category($cat_id)
2555
+	{
2556
+		$cat_id = absint($cat_id);
2557
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2558
+	}
2559
+
2560
+
2561
+	/**
2562
+	 * Handles triggering the update or insertion of a new category.
2563
+	 *
2564
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2565
+	 */
2566
+	protected function _insert_or_update_category($new_category)
2567
+	{
2568
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2569
+		$success = 0; // we already have a success message so lets not send another.
2570
+		if ($cat_id) {
2571
+			$query_args = array(
2572
+				'action'     => 'edit_category',
2573
+				'EVT_CAT_ID' => $cat_id,
2574
+			);
2575
+		} else {
2576
+			$query_args = array('action' => 'add_category');
2577
+		}
2578
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2579
+	}
2580
+
2581
+
2582
+	/**
2583
+	 * Inserts or updates category
2584
+	 *
2585
+	 * @param bool $update (true indicates we're updating a category).
2586
+	 * @return bool|mixed|string
2587
+	 */
2588
+	private function _insert_category($update = false)
2589
+	{
2590
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2591
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2592
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2593
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2594
+		if (empty($category_name)) {
2595
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2596
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2597
+			return false;
2598
+		}
2599
+		$term_args = array(
2600
+			'name'        => $category_name,
2601
+			'description' => $category_desc,
2602
+			'parent'      => $category_parent,
2603
+		);
2604
+		// was the category_identifier input disabled?
2605
+		if (isset($this->_req_data['category_identifier'])) {
2606
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2607
+		}
2608
+		$insert_ids = $update
2609
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2610
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2611
+		if (! is_array($insert_ids)) {
2612
+			$msg = esc_html__(
2613
+				'An error occurred and the category has not been saved to the database.',
2614
+				'event_espresso'
2615
+			);
2616
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2617
+		} else {
2618
+			$cat_id = $insert_ids['term_id'];
2619
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2620
+			EE_Error::add_success($msg);
2621
+		}
2622
+		return $cat_id;
2623
+	}
2624
+
2625
+
2626
+	/**
2627
+	 * Gets categories or count of categories matching the arguments in the request.
2628
+	 *
2629
+	 * @param int  $per_page
2630
+	 * @param int  $current_page
2631
+	 * @param bool $count
2632
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2633
+	 */
2634
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2635
+	{
2636
+		// testing term stuff
2637
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2638
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2639
+		$limit = ($current_page - 1) * $per_page;
2640
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2641
+		if (isset($this->_req_data['s'])) {
2642
+			$sstr = '%' . $this->_req_data['s'] . '%';
2643
+			$where['OR'] = array(
2644
+				'Term.name'   => array('LIKE', $sstr),
2645
+				'description' => array('LIKE', $sstr),
2646
+			);
2647
+		}
2648
+		$query_params = array(
2649
+			$where,
2650
+			'order_by'   => array($orderby => $order),
2651
+			'limit'      => $limit . ',' . $per_page,
2652
+			'force_join' => array('Term'),
2653
+		);
2654
+		$categories = $count
2655
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2656
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2657
+		return $categories;
2658
+	}
2659
+
2660
+	/* end category stuff */
2661
+	/**************/
2662
+
2663
+
2664
+	/**
2665
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2666
+	 *
2667
+	 * @throws EE_Error
2668
+	 */
2669
+	public function save_timezonestring_setting()
2670
+	{
2671
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2672
+			? $this->_req_data['timezone_selected']
2673
+			: '';
2674
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2675
+			EE_Error::add_error(
2676
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2677
+				__FILE__,
2678
+				__FUNCTION__,
2679
+				__LINE__
2680
+			);
2681
+			$this->_template_args['error'] = true;
2682
+			$this->_return_json();
2683
+		}
2684
+
2685
+		update_option('timezone_string', $timezone_string);
2686
+		EE_Error::add_success(
2687
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2688
+		);
2689
+		$this->_template_args['success'] = true;
2690
+		$this->_return_json(true, array('action' => 'create_new'));
2691
+	}
2692 2692
 }
Please login to merge, or discard this patch.
admin_pages/general_settings/General_Settings_Admin_Page.core.php 1 patch
Indentation   +1398 added lines, -1398 removed lines patch added patch discarded remove patch
@@ -20,1413 +20,1413 @@
 block discarded – undo
20 20
 class General_Settings_Admin_Page extends EE_Admin_Page
21 21
 {
22 22
 
23
-    /**
24
-     * _question_group
25
-     * holds the specific question group object for the question group details screen
26
-     *
27
-     * @var object
28
-     */
29
-    protected $_question_group;
30
-
31
-
32
-    /**
33
-     * Initialize basic properties.
34
-     */
35
-    protected function _init_page_props()
36
-    {
37
-        $this->page_slug = GEN_SET_PG_SLUG;
38
-        $this->page_label = GEN_SET_LABEL;
39
-        $this->_admin_base_url = GEN_SET_ADMIN_URL;
40
-        $this->_admin_base_path = GEN_SET_ADMIN;
41
-    }
42
-
43
-
44
-    /**
45
-     * Set ajax hooks
46
-     */
47
-    protected function _ajax_hooks()
48
-    {
49
-        add_action('wp_ajax_espresso_display_country_settings', array($this, 'display_country_settings'));
50
-        add_action('wp_ajax_espresso_display_country_states', array($this, 'display_country_states'));
51
-        add_action('wp_ajax_espresso_delete_state', array($this, 'delete_state'), 10, 3);
52
-        add_action('wp_ajax_espresso_add_new_state', array($this, 'add_new_state'));
53
-    }
54
-
55
-
56
-    /**
57
-     * More page properties initialization.
58
-     */
59
-    protected function _define_page_props()
60
-    {
61
-        $this->_admin_page_title = GEN_SET_LABEL;
62
-        $this->_labels = array(
63
-            'publishbox' => esc_html__('Update Settings', 'event_espresso'),
64
-        );
65
-    }
66
-
67
-
68
-    /**
69
-     * Set page routes property.
70
-     */
71
-    protected function _set_page_routes()
72
-    {
73
-        $this->_page_routes = array(
74
-
75
-            'critical_pages'                => array(
76
-                'func'       => '_espresso_page_settings',
77
-                'capability' => 'manage_options',
78
-            ),
79
-            'update_espresso_page_settings' => array(
80
-                'func'       => '_update_espresso_page_settings',
81
-                'capability' => 'manage_options',
82
-                'noheader'   => true,
83
-            ),
84
-            'default'                       => array(
85
-                'func'       => '_your_organization_settings',
86
-                'capability' => 'manage_options',
87
-            ),
88
-
89
-            'update_your_organization_settings' => array(
90
-                'func'       => '_update_your_organization_settings',
91
-                'capability' => 'manage_options',
92
-                'noheader'   => true,
93
-            ),
94
-
95
-            'admin_option_settings' => array(
96
-                'func'       => '_admin_option_settings',
97
-                'capability' => 'manage_options',
98
-            ),
99
-
100
-            'update_admin_option_settings' => array(
101
-                'func'       => '_update_admin_option_settings',
102
-                'capability' => 'manage_options',
103
-                'noheader'   => true,
104
-            ),
105
-
106
-            'country_settings' => array(
107
-                'func'       => '_country_settings',
108
-                'capability' => 'manage_options',
109
-            ),
110
-
111
-            'update_country_settings' => array(
112
-                'func'       => '_update_country_settings',
113
-                'capability' => 'manage_options',
114
-                'noheader'   => true,
115
-            ),
116
-
117
-            'display_country_settings' => array(
118
-                'func'       => 'display_country_settings',
119
-                'capability' => 'manage_options',
120
-                'noheader'   => true,
121
-            ),
122
-
123
-            'add_new_state' => array(
124
-                'func'       => 'add_new_state',
125
-                'capability' => 'manage_options',
126
-                'noheader'   => true,
127
-            ),
128
-
129
-            'delete_state'            => array(
130
-                'func'       => 'delete_state',
131
-                'capability' => 'manage_options',
132
-                'noheader'   => true,
133
-            ),
134
-            'privacy_settings'        => array(
135
-                'func'       => 'privacySettings',
136
-                'capability' => 'manage_options',
137
-            ),
138
-            'update_privacy_settings' => array(
139
-                'func'               => 'updatePrivacySettings',
140
-                'capability'         => 'manage_options',
141
-                'noheader'           => true,
142
-                'headers_sent_route' => 'privacy_settings',
143
-            ),
144
-        );
145
-    }
146
-
147
-
148
-    /**
149
-     * Set page configuration property
150
-     */
151
-    protected function _set_page_config()
152
-    {
153
-        $this->_page_config = array(
154
-            'critical_pages'        => array(
155
-                'nav'           => array(
156
-                    'label' => esc_html__('Critical Pages', 'event_espresso'),
157
-                    'order' => 50,
158
-                ),
159
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
160
-                'help_tabs'     => array(
161
-                    'general_settings_critical_pages_help_tab' => array(
162
-                        'title'    => esc_html__('Critical Pages', 'event_espresso'),
163
-                        'filename' => 'general_settings_critical_pages',
164
-                    ),
165
-                ),
166
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
167
-                // 'help_tour'     => array('Critical_Pages_Help_Tour'),
168
-                'require_nonce' => false,
169
-            ),
170
-            'default'               => array(
171
-                'nav'           => array(
172
-                    'label' => esc_html__('Your Organization', 'event_espresso'),
173
-                    'order' => 20,
174
-                ),
175
-                'help_tabs'     => array(
176
-                    'general_settings_your_organization_help_tab' => array(
177
-                        'title'    => esc_html__('Your Organization', 'event_espresso'),
178
-                        'filename' => 'general_settings_your_organization',
179
-                    ),
180
-                ),
181
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
182
-                // 'help_tour'     => array('Your_Organization_Help_Tour'),
183
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
184
-                'require_nonce' => false,
185
-            ),
186
-            'admin_option_settings' => array(
187
-                'nav'           => array(
188
-                    'label' => esc_html__('Admin Options', 'event_espresso'),
189
-                    'order' => 60,
190
-                ),
191
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
192
-                'help_tabs'     => array(
193
-                    'general_settings_admin_options_help_tab' => array(
194
-                        'title'    => esc_html__('Admin Options', 'event_espresso'),
195
-                        'filename' => 'general_settings_admin_options',
196
-                    ),
197
-                ),
198
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
199
-                // 'help_tour'     => array('Admin_Options_Help_Tour'),
200
-                'require_nonce' => false,
201
-            ),
202
-            'country_settings'      => array(
203
-                'nav'           => array(
204
-                    'label' => esc_html__('Countries', 'event_espresso'),
205
-                    'order' => 70,
206
-                ),
207
-                'help_tabs'     => array(
208
-                    'general_settings_countries_help_tab' => array(
209
-                        'title'    => esc_html__('Countries', 'event_espresso'),
210
-                        'filename' => 'general_settings_countries',
211
-                    ),
212
-                ),
213
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
214
-                // 'help_tour'     => array('Countries_Help_Tour'),
215
-                'require_nonce' => false,
216
-            ),
217
-            'privacy_settings'      => array(
218
-                'nav'           => array(
219
-                    'label' => esc_html__('Privacy', 'event_espresso'),
220
-                    'order' => 80,
221
-                ),
222
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
223
-                'require_nonce' => false,
224
-            ),
225
-        );
226
-    }
227
-
228
-
229
-    protected function _add_screen_options()
230
-    {
231
-    }
232
-
233
-
234
-    protected function _add_feature_pointers()
235
-    {
236
-    }
237
-
238
-
239
-    /**
240
-     * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
241
-     */
242
-    public function load_scripts_styles()
243
-    {
244
-        // styles
245
-        wp_enqueue_style('espresso-ui-theme');
246
-        // scripts
247
-        wp_enqueue_script('ee_admin_js');
248
-    }
249
-
250
-
251
-    /**
252
-     * Execute logic running on `admin_init`
253
-     */
254
-    public function admin_init()
255
-    {
256
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(__(
257
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
258
-            'event_espresso'
259
-        ));
260
-        EE_Registry::$i18n_js_strings['error_occurred'] = wp_strip_all_tags(__(
261
-            'An error occurred! Please refresh the page and try again.',
262
-            'event_espresso'
263
-        ));
264
-        EE_Registry::$i18n_js_strings['confirm_delete_state'] = wp_strip_all_tags(__(
265
-            'Are you sure you want to delete this State / Province?',
266
-            'event_espresso'
267
-        ));
268
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
269
-        EE_Registry::$i18n_js_strings['ajax_url'] = admin_url(
270
-            'admin-ajax.php?page=espresso_general_settings',
271
-            $protocol
272
-        );
273
-    }
274
-
275
-
276
-    public function admin_notices()
277
-    {
278
-    }
279
-
280
-
281
-    public function admin_footer_scripts()
282
-    {
283
-    }
284
-
285
-
286
-    /**
287
-     * Enqueue scripts and styles for the default route.
288
-     */
289
-    public function load_scripts_styles_default()
290
-    {
291
-        // styles
292
-        wp_enqueue_style('thickbox');
293
-        // scripts
294
-        wp_enqueue_script('media-upload');
295
-        wp_enqueue_script('thickbox');
296
-        wp_register_script(
297
-            'organization_settings',
298
-            GEN_SET_ASSETS_URL . 'your_organization_settings.js',
299
-            array('jquery', 'media-upload', 'thickbox'),
300
-            EVENT_ESPRESSO_VERSION,
301
-            true
302
-        );
303
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', array(), EVENT_ESPRESSO_VERSION);
304
-        wp_enqueue_script('organization_settings');
305
-        wp_enqueue_style('organization-css');
306
-        $confirm_image_delete = array(
307
-            'text' => wp_strip_all_tags(
308
-                __(
309
-                    'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
310
-                    'event_espresso'
311
-                )
312
-            ),
313
-        );
314
-        wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
315
-    }
316
-
317
-
318
-    /**
319
-     * Enqueue scripts and styles for the country settings route.
320
-     */
321
-    public function load_scripts_styles_country_settings()
322
-    {
323
-        // scripts
324
-        wp_register_script(
325
-            'gen_settings_countries',
326
-            GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
327
-            array('ee_admin_js'),
328
-            EVENT_ESPRESSO_VERSION,
329
-            true
330
-        );
331
-        wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', array(), EVENT_ESPRESSO_VERSION);
332
-        wp_enqueue_script('gen_settings_countries');
333
-        wp_enqueue_style('organization-css');
334
-    }
335
-
336
-
337
-    /*************        Espresso Pages        *************/
338
-    /**
339
-     * _espresso_page_settings
340
-     *
341
-     * @throws \EE_Error
342
-     * @throws DomainException
343
-     * @throws DomainException
344
-     * @throws InvalidDataTypeException
345
-     * @throws InvalidArgumentException
346
-     */
347
-    protected function _espresso_page_settings()
348
-    {
349
-        // Check to make sure all of the main pages are setup properly,
350
-        // if not create the default pages and display an admin notice
351
-        EEH_Activation::verify_default_pages_exist();
352
-        $this->_transient_garbage_collection();
353
-        $this->_template_args['values'] = $this->_yes_no_values;
354
-        $this->_template_args['reg_page_id'] = isset(EE_Registry::instance()->CFG->core->reg_page_id)
355
-            ? EE_Registry::instance()->CFG->core->reg_page_id
356
-            : null;
357
-        $this->_template_args['reg_page_obj'] = isset(EE_Registry::instance()->CFG->core->reg_page_id)
358
-            ? get_page(EE_Registry::instance()->CFG->core->reg_page_id)
359
-            : false;
360
-        $this->_template_args['txn_page_id'] = isset(EE_Registry::instance()->CFG->core->txn_page_id)
361
-            ? EE_Registry::instance()->CFG->core->txn_page_id
362
-            : null;
363
-        $this->_template_args['txn_page_obj'] = isset(EE_Registry::instance()->CFG->core->txn_page_id)
364
-            ? get_page(EE_Registry::instance()->CFG->core->txn_page_id)
365
-            : false;
366
-        $this->_template_args['thank_you_page_id'] = isset(EE_Registry::instance()->CFG->core->thank_you_page_id)
367
-            ? EE_Registry::instance()->CFG->core->thank_you_page_id
368
-            : null;
369
-        $this->_template_args['thank_you_page_obj'] = isset(EE_Registry::instance()->CFG->core->thank_you_page_id)
370
-            ? get_page(EE_Registry::instance()->CFG->core->thank_you_page_id)
371
-            : false;
372
-        $this->_template_args['cancel_page_id'] = isset(EE_Registry::instance()->CFG->core->cancel_page_id)
373
-            ? EE_Registry::instance()->CFG->core->cancel_page_id
374
-            : null;
375
-        $this->_template_args['cancel_page_obj'] = isset(EE_Registry::instance()->CFG->core->cancel_page_id)
376
-            ? get_page(EE_Registry::instance()->CFG->core->cancel_page_id)
377
-            : false;
378
-        $this->_set_add_edit_form_tags('update_espresso_page_settings');
379
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
380
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
381
-            GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
382
-            $this->_template_args,
383
-            true
384
-        );
385
-        $this->display_admin_page_with_sidebar();
386
-    }
387
-
388
-
389
-    /**
390
-     * Handler for updating espresso page settings.
391
-     *
392
-     * @throws EE_Error
393
-     */
394
-    protected function _update_espresso_page_settings()
395
-    {
396
-        // capture incoming request data && set page IDs
397
-        EE_Registry::instance()->CFG->core->reg_page_id = isset($this->_req_data['reg_page_id'])
398
-            ? absint($this->_req_data['reg_page_id'])
399
-            : EE_Registry::instance()->CFG->core->reg_page_id;
400
-        EE_Registry::instance()->CFG->core->txn_page_id = isset($this->_req_data['txn_page_id'])
401
-            ? absint($this->_req_data['txn_page_id'])
402
-            : EE_Registry::instance()->CFG->core->txn_page_id;
403
-        EE_Registry::instance()->CFG->core->thank_you_page_id = isset($this->_req_data['thank_you_page_id'])
404
-            ? absint($this->_req_data['thank_you_page_id'])
405
-            : EE_Registry::instance()->CFG->core->thank_you_page_id;
406
-        EE_Registry::instance()->CFG->core->cancel_page_id = isset($this->_req_data['cancel_page_id'])
407
-            ? absint($this->_req_data['cancel_page_id'])
408
-            : EE_Registry::instance()->CFG->core->cancel_page_id;
409
-
410
-        EE_Registry::instance()->CFG->core = apply_filters(
411
-            'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
412
-            EE_Registry::instance()->CFG->core,
413
-            $this->_req_data
414
-        );
415
-        $what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
416
-        $this->_redirect_after_action(
417
-            $this->_update_espresso_configuration(
418
-                $what,
419
-                EE_Registry::instance()->CFG->core,
420
-                __FILE__,
421
-                __FUNCTION__,
422
-                __LINE__
423
-            ),
424
-            $what,
425
-            '',
426
-            array(
427
-                'action' => 'critical_pages',
428
-            ),
429
-            true
430
-        );
431
-    }
432
-
433
-
434
-    /*************        Your Organization        *************/
435
-
436
-
437
-    /**
438
-     * @throws DomainException
439
-     * @throws EE_Error
440
-     * @throws InvalidArgumentException
441
-     * @throws InvalidDataTypeException
442
-     * @throws InvalidInterfaceException
443
-     */
444
-    protected function _your_organization_settings()
445
-    {
446
-        $this->_template_args['admin_page_content'] = '';
447
-        try {
448
-            /** @var EventEspresso\admin_pages\general_settings\OrganizationSettings $organization_settings_form */
449
-            $organization_settings_form = $this->loader->getShared(
450
-                'EventEspresso\admin_pages\general_settings\OrganizationSettings'
451
-            );
452
-            $this->_template_args['admin_page_content'] = $organization_settings_form->display();
453
-        } catch (Exception $e) {
454
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
455
-        }
456
-        $this->_set_add_edit_form_tags('update_your_organization_settings');
457
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
458
-        $this->display_admin_page_with_sidebar();
459
-    }
460
-
461
-
462
-    /**
463
-     * Handler for updating organization settings.
464
-     *
465
-     * @throws EE_Error
466
-     */
467
-    protected function _update_your_organization_settings()
468
-    {
469
-        try {
470
-            /** @var EventEspresso\admin_pages\general_settings\OrganizationSettings $organization_settings_form */
471
-            $organization_settings_form = $this->loader->getShared(
472
-                'EventEspresso\admin_pages\general_settings\OrganizationSettings'
473
-            );
474
-            $success = $organization_settings_form->process($this->_req_data);
475
-            EE_Registry::instance()->CFG = apply_filters(
476
-                'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
477
-                EE_Registry::instance()->CFG
478
-            );
479
-        } catch (Exception $e) {
480
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
481
-            $success = false;
482
-        }
483
-
484
-        if ($success) {
485
-            $success = $this->_update_espresso_configuration(
486
-                esc_html__('Your Organization Settings', 'event_espresso'),
487
-                EE_Registry::instance()->CFG,
488
-                __FILE__,
489
-                __FUNCTION__,
490
-                __LINE__
491
-            );
492
-        }
493
-
494
-        $this->_redirect_after_action($success, '', '', array('action' => 'default'), true);
495
-    }
496
-
497
-
498
-
499
-    /*************        Admin Options        *************/
500
-
501
-
502
-    /**
503
-     * _admin_option_settings
504
-     *
505
-     * @throws \EE_Error
506
-     * @throws \LogicException
507
-     */
508
-    protected function _admin_option_settings()
509
-    {
510
-        $this->_template_args['admin_page_content'] = '';
511
-        try {
512
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
513
-            // still need this for the old school form in Extend_General_Settings_Admin_Page
514
-            $this->_template_args['values'] = $this->_yes_no_values;
515
-            // also need to account for the do_action that was in the old template
516
-            $admin_options_settings_form->setTemplateArgs($this->_template_args);
517
-            $this->_template_args['admin_page_content'] = $admin_options_settings_form->display();
518
-        } catch (Exception $e) {
519
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
-        }
521
-        $this->_set_add_edit_form_tags('update_admin_option_settings');
522
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
523
-        $this->display_admin_page_with_sidebar();
524
-    }
525
-
526
-
527
-    /**
528
-     * _update_admin_option_settings
529
-     *
530
-     * @throws \EE_Error
531
-     * @throws InvalidDataTypeException
532
-     * @throws \EventEspresso\core\exceptions\InvalidFormSubmissionException
533
-     * @throws \InvalidArgumentException
534
-     * @throws \LogicException
535
-     */
536
-    protected function _update_admin_option_settings()
537
-    {
538
-        try {
539
-            $admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
540
-            $admin_options_settings_form->process($this->_req_data[ $admin_options_settings_form->slug() ]);
541
-            EE_Registry::instance()->CFG->admin = apply_filters(
542
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
543
-                EE_Registry::instance()->CFG->admin
544
-            );
545
-        } catch (Exception $e) {
546
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
547
-        }
548
-        $this->_redirect_after_action(
549
-            apply_filters(
550
-                'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
551
-                $this->_update_espresso_configuration(
552
-                    'Admin Options',
553
-                    EE_Registry::instance()->CFG->admin,
554
-                    __FILE__,
555
-                    __FUNCTION__,
556
-                    __LINE__
557
-                )
558
-            ),
559
-            'Admin Options',
560
-            'updated',
561
-            array('action' => 'admin_option_settings')
562
-        );
563
-    }
564
-
565
-
566
-    /*************        Countries        *************/
567
-
568
-
569
-    /**
570
-     * @return string
571
-     */
572
-    protected function getCountryIsoForSite()
573
-    {
574
-        return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
575
-            ? EE_Registry::instance()->CFG->organization->CNT_ISO
576
-            : 'US';
577
-    }
578
-
579
-
580
-    /**
581
-     * @param string          $CNT_ISO
582
-     * @param EE_Country|null $country
583
-     * @return EE_Base_Class|EE_Country
584
-     * @throws EE_Error
585
-     * @throws InvalidArgumentException
586
-     * @throws InvalidDataTypeException
587
-     * @throws InvalidInterfaceException
588
-     * @throws ReflectionException
589
-     */
590
-    protected function verifyOrGetCountryFromIso($CNT_ISO, EE_Country $country = null)
591
-    {
592
-        /** @var EE_Country $country */
593
-        return $country instanceof EE_Country && $country->ID() === $CNT_ISO
594
-            ? $country
595
-            : EEM_Country::instance()->get_one_by_ID($CNT_ISO);
596
-    }
597
-
598
-
599
-    /**
600
-     * Output Country Settings view.
601
-     *
602
-     * @throws DomainException
603
-     * @throws EE_Error
604
-     * @throws InvalidArgumentException
605
-     * @throws InvalidDataTypeException
606
-     * @throws InvalidInterfaceException
607
-     * @throws ReflectionException
608
-     */
609
-    protected function _country_settings()
610
-    {
611
-        $CNT_ISO_for_site = $this->getCountryIsoForSite();
612
-        $CNT_ISO = isset($this->_req_data['country'])
613
-            ? strtoupper(sanitize_text_field($this->_req_data['country']))
614
-            : $CNT_ISO_for_site;
615
-
616
-        // load field generator helper
617
-
618
-        $this->_template_args['values'] = $this->_yes_no_values;
619
-
620
-        $this->_template_args['countries'] = new EE_Question_Form_Input(
621
-            EE_Question::new_instance(
622
-                array(
623
-                    'QST_ID'           => 0,
624
-                    'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
625
-                    'QST_system'       => 'admin-country',
626
-                )
627
-            ),
628
-            EE_Answer::new_instance(
629
-                array(
630
-                    'ANS_ID'    => 0,
631
-                    'ANS_value' => $CNT_ISO,
632
-                )
633
-            ),
634
-            array(
635
-                'input_id'       => 'country',
636
-                'input_name'     => 'country',
637
-                'input_prefix'   => '',
638
-                'append_qstn_id' => false,
639
-            )
640
-        );
641
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO_for_site);
642
-        add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'country_form_field_label_wrap'), 10, 2);
643
-        add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'country_form_field_input__wrap'), 10, 2);
644
-        $this->_template_args['country_details_settings'] = $this->display_country_settings(
645
-            $country->ID(),
646
-            $country
647
-        );
648
-        $this->_template_args['country_states_settings'] = $this->display_country_states(
649
-            $country->ID(),
650
-            $country
651
-        );
652
-        $this->_template_args['CNT_name_for_site'] = $country->name();
653
-
654
-        $this->_set_add_edit_form_tags('update_country_settings');
655
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
656
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
657
-            GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
658
-            $this->_template_args,
659
-            true
660
-        );
661
-        $this->display_admin_page_with_no_sidebar();
662
-    }
663
-
664
-
665
-    /**
666
-     *        display_country_settings
667
-     *
668
-     * @param string          $CNT_ISO
669
-     * @param EE_Country|null $country
670
-     * @return mixed string | array$country
671
-     * @throws DomainException
672
-     * @throws EE_Error
673
-     * @throws InvalidArgumentException
674
-     * @throws InvalidDataTypeException
675
-     * @throws InvalidInterfaceException
676
-     * @throws ReflectionException
677
-     */
678
-    public function display_country_settings($CNT_ISO = '', EE_Country $country = null)
679
-    {
680
-        $CNT_ISO_for_site = $this->getCountryIsoForSite();
681
-
682
-        $CNT_ISO = isset($this->_req_data['country'])
683
-            ? strtoupper(sanitize_text_field($this->_req_data['country']))
684
-            : $CNT_ISO;
685
-        if (! $CNT_ISO) {
686
-            return '';
687
-        }
688
-
689
-        // for ajax
690
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
691
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
692
-        add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'country_form_field_label_wrap'), 10, 2);
693
-        add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'country_form_field_input__wrap'), 10, 2);
694
-        $country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
695
-        $CNT_cur_disabled = $CNT_ISO !== $CNT_ISO_for_site;
696
-        $this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
697
-
698
-        $country_input_types = array(
699
-            'CNT_active'      => array(
700
-                'type'             => 'RADIO_BTN',
701
-                'input_name'       => 'cntry[' . $CNT_ISO . ']',
702
-                'class'            => '',
703
-                'options'          => $this->_yes_no_values,
704
-                'use_desc_4_label' => true,
705
-            ),
706
-            'CNT_ISO'         => array(
707
-                'type'       => 'TEXT',
708
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
709
-                'class'      => 'small-text',
710
-            ),
711
-            'CNT_ISO3'        => array(
712
-                'type'       => 'TEXT',
713
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
714
-                'class'      => 'small-text',
715
-            ),
716
-            'RGN_ID'          => array(
717
-                'type'       => 'TEXT',
718
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
719
-                'class'      => 'small-text',
720
-            ),
721
-            'CNT_name'        => array(
722
-                'type'       => 'TEXT',
723
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
724
-                'class'      => 'regular-text',
725
-            ),
726
-            'CNT_cur_code'    => array(
727
-                'type'       => 'TEXT',
728
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
729
-                'class'      => 'small-text',
730
-                'disabled'   => $CNT_cur_disabled,
731
-            ),
732
-            'CNT_cur_single'  => array(
733
-                'type'       => 'TEXT',
734
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
735
-                'class'      => 'medium-text',
736
-                'disabled'   => $CNT_cur_disabled,
737
-            ),
738
-            'CNT_cur_plural'  => array(
739
-                'type'       => 'TEXT',
740
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
741
-                'class'      => 'medium-text',
742
-                'disabled'   => $CNT_cur_disabled,
743
-            ),
744
-            'CNT_cur_sign'    => array(
745
-                'type'         => 'TEXT',
746
-                'input_name'   => 'cntry[' . $CNT_ISO . ']',
747
-                'class'        => 'small-text',
748
-                'htmlentities' => false,
749
-                'disabled'     => $CNT_cur_disabled,
750
-            ),
751
-            'CNT_cur_sign_b4' => array(
752
-                'type'             => 'RADIO_BTN',
753
-                'input_name'       => 'cntry[' . $CNT_ISO . ']',
754
-                'class'            => '',
755
-                'options'          => $this->_yes_no_values,
756
-                'use_desc_4_label' => true,
757
-                'disabled'         => $CNT_cur_disabled,
758
-            ),
759
-            'CNT_cur_dec_plc' => array(
760
-                'type'       => 'RADIO_BTN',
761
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
762
-                'class'      => '',
763
-                'options'    => array(
764
-                    array('id' => 0, 'text' => ''),
765
-                    array('id' => 1, 'text' => ''),
766
-                    array('id' => 2, 'text' => ''),
767
-                    array('id' => 3, 'text' => ''),
768
-                ),
769
-                'disabled'   => $CNT_cur_disabled,
770
-            ),
771
-            'CNT_cur_dec_mrk' => array(
772
-                'type'             => 'RADIO_BTN',
773
-                'input_name'       => 'cntry[' . $CNT_ISO . ']',
774
-                'class'            => '',
775
-                'options'          => array(
776
-                    array(
777
-                        'id'   => ',',
778
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
779
-                    ),
780
-                    array('id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')),
781
-                ),
782
-                'use_desc_4_label' => true,
783
-                'disabled'         => $CNT_cur_disabled,
784
-            ),
785
-            'CNT_cur_thsnds'  => array(
786
-                'type'             => 'RADIO_BTN',
787
-                'input_name'       => 'cntry[' . $CNT_ISO . ']',
788
-                'class'            => '',
789
-                'options'          => array(
790
-                    array(
791
-                        'id'   => ',',
792
-                        'text' => esc_html__(', (comma)', 'event_espresso'),
793
-                    ),
794
-                    array(
795
-                        'id' => '.',
796
-                        'text' => esc_html__('. (decimal)', 'event_espresso')
797
-                    ),
798
-                    array(
799
-                        'id' => '&nbsp;',
800
-                        'text' => esc_html__('(space)', 'event_espresso')
801
-                    )
802
-                ),
803
-                'use_desc_4_label' => true,
804
-                'disabled'         => $CNT_cur_disabled,
805
-            ),
806
-            'CNT_tel_code'    => array(
807
-                'type'       => 'TEXT',
808
-                'input_name' => 'cntry[' . $CNT_ISO . ']',
809
-                'class'      => 'small-text',
810
-            ),
811
-            'CNT_is_EU'       => array(
812
-                'type'             => 'RADIO_BTN',
813
-                'input_name'       => 'cntry[' . $CNT_ISO . ']',
814
-                'class'            => '',
815
-                'options'          => $this->_yes_no_values,
816
-                'use_desc_4_label' => true,
817
-            ),
818
-        );
819
-        $this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
820
-            $country,
821
-            $country_input_types
822
-        );
823
-        $country_details_settings = EEH_Template::display_template(
824
-            GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
825
-            $this->_template_args,
826
-            true
827
-        );
828
-
829
-        if (defined('DOING_AJAX')) {
830
-            $notices = EE_Error::get_notices(false, false, false);
831
-            echo wp_json_encode(
832
-                array(
833
-                    'return_data' => $country_details_settings,
834
-                    'success'     => $notices['success'],
835
-                    'errors'      => $notices['errors'],
836
-                )
837
-            );
838
-            die();
839
-        } else {
840
-            return $country_details_settings;
841
-        }
842
-    }
843
-
844
-
845
-    /**
846
-     * @param string          $CNT_ISO
847
-     * @param EE_Country|null $country
848
-     * @return string
849
-     * @throws DomainException
850
-     * @throws EE_Error
851
-     * @throws InvalidArgumentException
852
-     * @throws InvalidDataTypeException
853
-     * @throws InvalidInterfaceException
854
-     * @throws ReflectionException
855
-     */
856
-    public function display_country_states($CNT_ISO = '', EE_Country $country = null)
857
-    {
858
-
859
-        $CNT_ISO = isset($this->_req_data['country'])
860
-            ? sanitize_text_field($this->_req_data['country'])
861
-            : $CNT_ISO;
862
-        if (! $CNT_ISO) {
863
-            return '';
864
-        }
865
-        // for ajax
866
-        remove_all_filters('FHEE__EEH_Form_Fields__label_html');
867
-        remove_all_filters('FHEE__EEH_Form_Fields__input_html');
868
-        add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'state_form_field_label_wrap'), 10, 2);
869
-        add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'state_form_field_input__wrap'), 10, 2);
870
-        $states = EEM_State::instance()->get_all_states_for_these_countries(array($CNT_ISO => $CNT_ISO));
871
-        if (empty($states)) {
872
-            /** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
873
-            $countrySubRegionDao = $this->loader->getShared(
874
-                'EventEspresso\core\services\address\CountrySubRegionDao'
875
-            );
876
-            if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
877
-                $country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
878
-                if ($countrySubRegionDao->saveCountrySubRegions($country)) {
879
-                    $states = EEM_State::instance()->get_all_states_for_these_countries(
880
-                        array($CNT_ISO => $CNT_ISO)
881
-                    );
882
-                }
883
-            }
884
-        }
885
-        if (is_array($states)) {
886
-            foreach ($states as $STA_ID => $state) {
887
-                if ($state instanceof EE_State) {
888
-                    // STA_abbrev    STA_name    STA_active
889
-                    $state_input_types = array(
890
-                        'STA_abbrev' => array(
891
-                            'type'       => 'TEXT',
892
-                            'input_name' => 'states[' . $STA_ID . ']',
893
-                            'class'      => 'mid-text',
894
-                        ),
895
-                        'STA_name'   => array(
896
-                            'type'       => 'TEXT',
897
-                            'input_name' => 'states[' . $STA_ID . ']',
898
-                            'class'      => 'regular-text',
899
-                        ),
900
-                        'STA_active' => array(
901
-                            'type'             => 'RADIO_BTN',
902
-                            'input_name'       => 'states[' . $STA_ID . ']',
903
-                            'options'          => $this->_yes_no_values,
904
-                            'use_desc_4_label' => true,
905
-                        ),
906
-                    );
907
-                    $this->_template_args['states'][ $STA_ID ]['inputs'] =
908
-                        EE_Question_Form_Input::generate_question_form_inputs_for_object(
909
-                            $state,
910
-                            $state_input_types
911
-                        );
912
-                    $query_args = array(
913
-                        'action'     => 'delete_state',
914
-                        'STA_ID'     => $STA_ID,
915
-                        'CNT_ISO'    => $CNT_ISO,
916
-                        'STA_abbrev' => $state->abbrev(),
917
-                    );
918
-                    $this->_template_args['states'][ $STA_ID ]['delete_state_url'] =
919
-                        EE_Admin_Page::add_query_args_and_nonce(
920
-                            $query_args,
921
-                            GEN_SET_ADMIN_URL
922
-                        );
923
-                }
924
-            }
925
-        } else {
926
-            $this->_template_args['states'] = false;
927
-        }
928
-
929
-        $this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
930
-            array('action' => 'add_new_state'),
931
-            GEN_SET_ADMIN_URL
932
-        );
933
-
934
-        $state_details_settings = EEH_Template::display_template(
935
-            GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
936
-            $this->_template_args,
937
-            true
938
-        );
939
-
940
-        if (defined('DOING_AJAX')) {
941
-            $notices = EE_Error::get_notices(false, false, false);
942
-            echo wp_json_encode(
943
-                array(
944
-                    'return_data' => $state_details_settings,
945
-                    'success'     => $notices['success'],
946
-                    'errors'      => $notices['errors'],
947
-                )
948
-            );
949
-            die();
950
-        } else {
951
-            return $state_details_settings;
952
-        }
953
-    }
954
-
955
-
956
-    /**
957
-     *        add_new_state
958
-     *
959
-     * @access    public
960
-     * @return void
961
-     * @throws EE_Error
962
-     * @throws InvalidArgumentException
963
-     * @throws InvalidDataTypeException
964
-     * @throws InvalidInterfaceException
965
-     */
966
-    public function add_new_state()
967
-    {
968
-
969
-        $success = true;
970
-
971
-        $CNT_ISO = isset($this->_req_data['CNT_ISO'])
972
-            ? strtoupper(sanitize_text_field($this->_req_data['CNT_ISO']))
973
-            : false;
974
-        if (! $CNT_ISO) {
975
-            EE_Error::add_error(
976
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
977
-                __FILE__,
978
-                __FUNCTION__,
979
-                __LINE__
980
-            );
981
-            $success = false;
982
-        }
983
-        $STA_abbrev = isset($this->_req_data['STA_abbrev'])
984
-            ? sanitize_text_field($this->_req_data['STA_abbrev'])
985
-            : false;
986
-        if (! $STA_abbrev) {
987
-            EE_Error::add_error(
988
-                esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
989
-                __FILE__,
990
-                __FUNCTION__,
991
-                __LINE__
992
-            );
993
-            $success = false;
994
-        }
995
-        $STA_name = isset($this->_req_data['STA_name'])
996
-            ? sanitize_text_field($this->_req_data['STA_name'])
997
-            : false;
998
-        if (! $STA_name) {
999
-            EE_Error::add_error(
1000
-                esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1001
-                __FILE__,
1002
-                __FUNCTION__,
1003
-                __LINE__
1004
-            );
1005
-            $success = false;
1006
-        }
1007
-
1008
-        if ($success) {
1009
-            $cols_n_values = array(
1010
-                'CNT_ISO'    => $CNT_ISO,
1011
-                'STA_abbrev' => $STA_abbrev,
1012
-                'STA_name'   => $STA_name,
1013
-                'STA_active' => true,
1014
-            );
1015
-            $success = EEM_State::instance()->insert($cols_n_values);
1016
-            EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1017
-        }
1018
-
1019
-        if (defined('DOING_AJAX')) {
1020
-            $notices = EE_Error::get_notices(false, false, false);
1021
-            echo wp_json_encode(array_merge($notices, array('return_data' => $CNT_ISO)));
1022
-            die();
1023
-        } else {
1024
-            $this->_redirect_after_action($success, 'State', 'added', array('action' => 'country_settings'));
1025
-        }
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     *        delete_state
1031
-     *
1032
-     * @access    public
1033
-     * @return        boolean
1034
-     * @throws EE_Error
1035
-     * @throws InvalidArgumentException
1036
-     * @throws InvalidDataTypeException
1037
-     * @throws InvalidInterfaceException
1038
-     */
1039
-    public function delete_state()
1040
-    {
1041
-        $CNT_ISO = isset($this->_req_data['CNT_ISO'])
1042
-            ? strtoupper(sanitize_text_field($this->_req_data['CNT_ISO']))
1043
-            : false;
1044
-        $STA_ID = isset($this->_req_data['STA_ID'])
1045
-            ? sanitize_text_field($this->_req_data['STA_ID'])
1046
-            : false;
1047
-        $STA_abbrev = isset($this->_req_data['STA_abbrev'])
1048
-            ? sanitize_text_field($this->_req_data['STA_abbrev'])
1049
-            : false;
1050
-        if (! $STA_ID) {
1051
-            EE_Error::add_error(
1052
-                esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1053
-                __FILE__,
1054
-                __FUNCTION__,
1055
-                __LINE__
1056
-            );
1057
-            return false;
1058
-        }
1059
-
1060
-        $success = EEM_State::instance()->delete_by_ID($STA_ID);
1061
-        if ($success !== false) {
1062
-            do_action(
1063
-                'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1064
-                $CNT_ISO,
1065
-                $STA_ID,
1066
-                array('STA_abbrev' => $STA_abbrev)
1067
-            );
1068
-            EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1069
-        }
1070
-        if (defined('DOING_AJAX')) {
1071
-            $notices = EE_Error::get_notices(false, false);
1072
-            $notices['return_data'] = true;
1073
-            echo wp_json_encode($notices);
1074
-            die();
1075
-        } else {
1076
-            $this->_redirect_after_action(
1077
-                $success,
1078
-                'State',
1079
-                'deleted',
1080
-                array('action' => 'country_settings')
1081
-            );
1082
-        }
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     *        _update_country_settings
1088
-     *
1089
-     * @access    protected
1090
-     * @return void
1091
-     * @throws EE_Error
1092
-     * @throws InvalidArgumentException
1093
-     * @throws InvalidDataTypeException
1094
-     * @throws InvalidInterfaceException
1095
-     */
1096
-    protected function _update_country_settings()
1097
-    {
1098
-        // grab the country ISO code
1099
-        $CNT_ISO = isset($this->_req_data['country'])
1100
-            ? strtoupper(sanitize_text_field($this->_req_data['country']))
1101
-            : false;
1102
-        if (! $CNT_ISO) {
1103
-            EE_Error::add_error(
1104
-                esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1105
-                __FILE__,
1106
-                __FUNCTION__,
1107
-                __LINE__
1108
-            );
1109
-
1110
-            return;
1111
-        }
1112
-        $cols_n_values = array();
1113
-        $cols_n_values['CNT_ISO3'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_ISO3'])
1114
-            ? strtoupper(sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_ISO3']))
1115
-            : false;
1116
-        $cols_n_values['RGN_ID'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['RGN_ID'])
1117
-            ? absint($this->_req_data['cntry'][ $CNT_ISO ]['RGN_ID'])
1118
-            : null;
1119
-        $cols_n_values['CNT_name'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_name'])
1120
-            ? sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_name'])
1121
-            : null;
1122
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_code'])) {
1123
-            $cols_n_values['CNT_cur_code'] = strtoupper(
1124
-                sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_code'])
1125
-            );
1126
-        }
1127
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_single'])) {
1128
-            $cols_n_values['CNT_cur_single'] = sanitize_text_field(
1129
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_single']
1130
-            );
1131
-        }
1132
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_plural'])) {
1133
-            $cols_n_values['CNT_cur_plural'] = sanitize_text_field(
1134
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_plural']
1135
-            );
1136
-        }
1137
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign'])) {
1138
-            $cols_n_values['CNT_cur_sign'] = sanitize_text_field(
1139
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign']
1140
-            );
1141
-        }
1142
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign_b4'])) {
1143
-            $cols_n_values['CNT_cur_sign_b4'] = absint(
1144
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign_b4']
1145
-            );
1146
-        }
1147
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_plc'])) {
1148
-            $cols_n_values['CNT_cur_dec_plc'] = absint(
1149
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_plc']
1150
-            );
1151
-        }
1152
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_mrk'])) {
1153
-            $cols_n_values['CNT_cur_dec_mrk'] = sanitize_text_field(
1154
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_mrk']
1155
-            );
1156
-        }
1157
-        if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_thsnds'])) {
1158
-            $cols_n_values['CNT_cur_thsnds'] = sanitize_text_field(
1159
-                $this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_thsnds']
1160
-            );
1161
-        }
1162
-        $cols_n_values['CNT_tel_code'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_tel_code'])
1163
-            ? sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_tel_code'])
1164
-            : null;
1165
-        $cols_n_values['CNT_is_EU'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_is_EU'])
1166
-            ? absint($this->_req_data['cntry'][ $CNT_ISO ]['CNT_is_EU'])
1167
-            : false;
1168
-        $cols_n_values['CNT_active'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_active'])
1169
-            ? absint($this->_req_data['cntry'][ $CNT_ISO ]['CNT_active'])
1170
-            : false;
1171
-        // allow filtering of country data
1172
-        $cols_n_values = apply_filters(
1173
-            'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1174
-            $cols_n_values
1175
-        );
1176
-
1177
-        // where values
1178
-        $where_cols_n_values = array(array('CNT_ISO' => $CNT_ISO));
1179
-        // run the update
1180
-        $success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1181
-
1182
-        if (isset($this->_req_data['states']) && is_array($this->_req_data['states']) && $success !== false) {
1183
-            // allow filtering of states data
1184
-            $states = apply_filters(
1185
-                'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1186
-                $this->_req_data['states']
1187
-            );
1188
-
1189
-            // loop thru state data ( looks like : states[75][STA_name] )
1190
-            foreach ($states as $STA_ID => $state) {
1191
-                $cols_n_values = array(
1192
-                    'CNT_ISO'    => $CNT_ISO,
1193
-                    'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1194
-                    'STA_name'   => sanitize_text_field($state['STA_name']),
1195
-                    'STA_active' => (bool) absint($state['STA_active']),
1196
-                );
1197
-                // where values
1198
-                $where_cols_n_values = array(array('STA_ID' => $STA_ID));
1199
-                // run the update
1200
-                $success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1201
-                if ($success !== false) {
1202
-                    do_action(
1203
-                        'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1204
-                        $CNT_ISO,
1205
-                        $STA_ID,
1206
-                        $cols_n_values
1207
-                    );
1208
-                }
1209
-            }
1210
-        }
1211
-        // check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1212
-        if (isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1213
-            && $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1214
-        ) {
1215
-            EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1216
-            EE_Registry::instance()->CFG->update_espresso_config();
1217
-        }
1218
-
1219
-        if ($success !== false) {
1220
-            EE_Error::add_success(
1221
-                esc_html__('Country Settings updated successfully.', 'event_espresso')
1222
-            );
1223
-        }
1224
-        $this->_redirect_after_action(
1225
-            $success,
1226
-            '',
1227
-            '',
1228
-            array('action' => 'country_settings', 'country' => $CNT_ISO),
1229
-            true
1230
-        );
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     *        form_form_field_label_wrap
1236
-     *
1237
-     * @access        public
1238
-     * @param        string $label
1239
-     * @return        string
1240
-     */
1241
-    public function country_form_field_label_wrap($label, $required_text)
1242
-    {
1243
-        return '
23
+	/**
24
+	 * _question_group
25
+	 * holds the specific question group object for the question group details screen
26
+	 *
27
+	 * @var object
28
+	 */
29
+	protected $_question_group;
30
+
31
+
32
+	/**
33
+	 * Initialize basic properties.
34
+	 */
35
+	protected function _init_page_props()
36
+	{
37
+		$this->page_slug = GEN_SET_PG_SLUG;
38
+		$this->page_label = GEN_SET_LABEL;
39
+		$this->_admin_base_url = GEN_SET_ADMIN_URL;
40
+		$this->_admin_base_path = GEN_SET_ADMIN;
41
+	}
42
+
43
+
44
+	/**
45
+	 * Set ajax hooks
46
+	 */
47
+	protected function _ajax_hooks()
48
+	{
49
+		add_action('wp_ajax_espresso_display_country_settings', array($this, 'display_country_settings'));
50
+		add_action('wp_ajax_espresso_display_country_states', array($this, 'display_country_states'));
51
+		add_action('wp_ajax_espresso_delete_state', array($this, 'delete_state'), 10, 3);
52
+		add_action('wp_ajax_espresso_add_new_state', array($this, 'add_new_state'));
53
+	}
54
+
55
+
56
+	/**
57
+	 * More page properties initialization.
58
+	 */
59
+	protected function _define_page_props()
60
+	{
61
+		$this->_admin_page_title = GEN_SET_LABEL;
62
+		$this->_labels = array(
63
+			'publishbox' => esc_html__('Update Settings', 'event_espresso'),
64
+		);
65
+	}
66
+
67
+
68
+	/**
69
+	 * Set page routes property.
70
+	 */
71
+	protected function _set_page_routes()
72
+	{
73
+		$this->_page_routes = array(
74
+
75
+			'critical_pages'                => array(
76
+				'func'       => '_espresso_page_settings',
77
+				'capability' => 'manage_options',
78
+			),
79
+			'update_espresso_page_settings' => array(
80
+				'func'       => '_update_espresso_page_settings',
81
+				'capability' => 'manage_options',
82
+				'noheader'   => true,
83
+			),
84
+			'default'                       => array(
85
+				'func'       => '_your_organization_settings',
86
+				'capability' => 'manage_options',
87
+			),
88
+
89
+			'update_your_organization_settings' => array(
90
+				'func'       => '_update_your_organization_settings',
91
+				'capability' => 'manage_options',
92
+				'noheader'   => true,
93
+			),
94
+
95
+			'admin_option_settings' => array(
96
+				'func'       => '_admin_option_settings',
97
+				'capability' => 'manage_options',
98
+			),
99
+
100
+			'update_admin_option_settings' => array(
101
+				'func'       => '_update_admin_option_settings',
102
+				'capability' => 'manage_options',
103
+				'noheader'   => true,
104
+			),
105
+
106
+			'country_settings' => array(
107
+				'func'       => '_country_settings',
108
+				'capability' => 'manage_options',
109
+			),
110
+
111
+			'update_country_settings' => array(
112
+				'func'       => '_update_country_settings',
113
+				'capability' => 'manage_options',
114
+				'noheader'   => true,
115
+			),
116
+
117
+			'display_country_settings' => array(
118
+				'func'       => 'display_country_settings',
119
+				'capability' => 'manage_options',
120
+				'noheader'   => true,
121
+			),
122
+
123
+			'add_new_state' => array(
124
+				'func'       => 'add_new_state',
125
+				'capability' => 'manage_options',
126
+				'noheader'   => true,
127
+			),
128
+
129
+			'delete_state'            => array(
130
+				'func'       => 'delete_state',
131
+				'capability' => 'manage_options',
132
+				'noheader'   => true,
133
+			),
134
+			'privacy_settings'        => array(
135
+				'func'       => 'privacySettings',
136
+				'capability' => 'manage_options',
137
+			),
138
+			'update_privacy_settings' => array(
139
+				'func'               => 'updatePrivacySettings',
140
+				'capability'         => 'manage_options',
141
+				'noheader'           => true,
142
+				'headers_sent_route' => 'privacy_settings',
143
+			),
144
+		);
145
+	}
146
+
147
+
148
+	/**
149
+	 * Set page configuration property
150
+	 */
151
+	protected function _set_page_config()
152
+	{
153
+		$this->_page_config = array(
154
+			'critical_pages'        => array(
155
+				'nav'           => array(
156
+					'label' => esc_html__('Critical Pages', 'event_espresso'),
157
+					'order' => 50,
158
+				),
159
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
160
+				'help_tabs'     => array(
161
+					'general_settings_critical_pages_help_tab' => array(
162
+						'title'    => esc_html__('Critical Pages', 'event_espresso'),
163
+						'filename' => 'general_settings_critical_pages',
164
+					),
165
+				),
166
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
167
+				// 'help_tour'     => array('Critical_Pages_Help_Tour'),
168
+				'require_nonce' => false,
169
+			),
170
+			'default'               => array(
171
+				'nav'           => array(
172
+					'label' => esc_html__('Your Organization', 'event_espresso'),
173
+					'order' => 20,
174
+				),
175
+				'help_tabs'     => array(
176
+					'general_settings_your_organization_help_tab' => array(
177
+						'title'    => esc_html__('Your Organization', 'event_espresso'),
178
+						'filename' => 'general_settings_your_organization',
179
+					),
180
+				),
181
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
182
+				// 'help_tour'     => array('Your_Organization_Help_Tour'),
183
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
184
+				'require_nonce' => false,
185
+			),
186
+			'admin_option_settings' => array(
187
+				'nav'           => array(
188
+					'label' => esc_html__('Admin Options', 'event_espresso'),
189
+					'order' => 60,
190
+				),
191
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
192
+				'help_tabs'     => array(
193
+					'general_settings_admin_options_help_tab' => array(
194
+						'title'    => esc_html__('Admin Options', 'event_espresso'),
195
+						'filename' => 'general_settings_admin_options',
196
+					),
197
+				),
198
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
199
+				// 'help_tour'     => array('Admin_Options_Help_Tour'),
200
+				'require_nonce' => false,
201
+			),
202
+			'country_settings'      => array(
203
+				'nav'           => array(
204
+					'label' => esc_html__('Countries', 'event_espresso'),
205
+					'order' => 70,
206
+				),
207
+				'help_tabs'     => array(
208
+					'general_settings_countries_help_tab' => array(
209
+						'title'    => esc_html__('Countries', 'event_espresso'),
210
+						'filename' => 'general_settings_countries',
211
+					),
212
+				),
213
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
214
+				// 'help_tour'     => array('Countries_Help_Tour'),
215
+				'require_nonce' => false,
216
+			),
217
+			'privacy_settings'      => array(
218
+				'nav'           => array(
219
+					'label' => esc_html__('Privacy', 'event_espresso'),
220
+					'order' => 80,
221
+				),
222
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
223
+				'require_nonce' => false,
224
+			),
225
+		);
226
+	}
227
+
228
+
229
+	protected function _add_screen_options()
230
+	{
231
+	}
232
+
233
+
234
+	protected function _add_feature_pointers()
235
+	{
236
+	}
237
+
238
+
239
+	/**
240
+	 * Enqueue global scripts and styles for all routes in the General Settings Admin Pages.
241
+	 */
242
+	public function load_scripts_styles()
243
+	{
244
+		// styles
245
+		wp_enqueue_style('espresso-ui-theme');
246
+		// scripts
247
+		wp_enqueue_script('ee_admin_js');
248
+	}
249
+
250
+
251
+	/**
252
+	 * Execute logic running on `admin_init`
253
+	 */
254
+	public function admin_init()
255
+	{
256
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = wp_strip_all_tags(__(
257
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
258
+			'event_espresso'
259
+		));
260
+		EE_Registry::$i18n_js_strings['error_occurred'] = wp_strip_all_tags(__(
261
+			'An error occurred! Please refresh the page and try again.',
262
+			'event_espresso'
263
+		));
264
+		EE_Registry::$i18n_js_strings['confirm_delete_state'] = wp_strip_all_tags(__(
265
+			'Are you sure you want to delete this State / Province?',
266
+			'event_espresso'
267
+		));
268
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
269
+		EE_Registry::$i18n_js_strings['ajax_url'] = admin_url(
270
+			'admin-ajax.php?page=espresso_general_settings',
271
+			$protocol
272
+		);
273
+	}
274
+
275
+
276
+	public function admin_notices()
277
+	{
278
+	}
279
+
280
+
281
+	public function admin_footer_scripts()
282
+	{
283
+	}
284
+
285
+
286
+	/**
287
+	 * Enqueue scripts and styles for the default route.
288
+	 */
289
+	public function load_scripts_styles_default()
290
+	{
291
+		// styles
292
+		wp_enqueue_style('thickbox');
293
+		// scripts
294
+		wp_enqueue_script('media-upload');
295
+		wp_enqueue_script('thickbox');
296
+		wp_register_script(
297
+			'organization_settings',
298
+			GEN_SET_ASSETS_URL . 'your_organization_settings.js',
299
+			array('jquery', 'media-upload', 'thickbox'),
300
+			EVENT_ESPRESSO_VERSION,
301
+			true
302
+		);
303
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', array(), EVENT_ESPRESSO_VERSION);
304
+		wp_enqueue_script('organization_settings');
305
+		wp_enqueue_style('organization-css');
306
+		$confirm_image_delete = array(
307
+			'text' => wp_strip_all_tags(
308
+				__(
309
+					'Do you really want to delete this image? Please remember to save your settings to complete the removal.',
310
+					'event_espresso'
311
+				)
312
+			),
313
+		);
314
+		wp_localize_script('organization_settings', 'confirm_image_delete', $confirm_image_delete);
315
+	}
316
+
317
+
318
+	/**
319
+	 * Enqueue scripts and styles for the country settings route.
320
+	 */
321
+	public function load_scripts_styles_country_settings()
322
+	{
323
+		// scripts
324
+		wp_register_script(
325
+			'gen_settings_countries',
326
+			GEN_SET_ASSETS_URL . 'gen_settings_countries.js',
327
+			array('ee_admin_js'),
328
+			EVENT_ESPRESSO_VERSION,
329
+			true
330
+		);
331
+		wp_register_style('organization-css', GEN_SET_ASSETS_URL . 'organization.css', array(), EVENT_ESPRESSO_VERSION);
332
+		wp_enqueue_script('gen_settings_countries');
333
+		wp_enqueue_style('organization-css');
334
+	}
335
+
336
+
337
+	/*************        Espresso Pages        *************/
338
+	/**
339
+	 * _espresso_page_settings
340
+	 *
341
+	 * @throws \EE_Error
342
+	 * @throws DomainException
343
+	 * @throws DomainException
344
+	 * @throws InvalidDataTypeException
345
+	 * @throws InvalidArgumentException
346
+	 */
347
+	protected function _espresso_page_settings()
348
+	{
349
+		// Check to make sure all of the main pages are setup properly,
350
+		// if not create the default pages and display an admin notice
351
+		EEH_Activation::verify_default_pages_exist();
352
+		$this->_transient_garbage_collection();
353
+		$this->_template_args['values'] = $this->_yes_no_values;
354
+		$this->_template_args['reg_page_id'] = isset(EE_Registry::instance()->CFG->core->reg_page_id)
355
+			? EE_Registry::instance()->CFG->core->reg_page_id
356
+			: null;
357
+		$this->_template_args['reg_page_obj'] = isset(EE_Registry::instance()->CFG->core->reg_page_id)
358
+			? get_page(EE_Registry::instance()->CFG->core->reg_page_id)
359
+			: false;
360
+		$this->_template_args['txn_page_id'] = isset(EE_Registry::instance()->CFG->core->txn_page_id)
361
+			? EE_Registry::instance()->CFG->core->txn_page_id
362
+			: null;
363
+		$this->_template_args['txn_page_obj'] = isset(EE_Registry::instance()->CFG->core->txn_page_id)
364
+			? get_page(EE_Registry::instance()->CFG->core->txn_page_id)
365
+			: false;
366
+		$this->_template_args['thank_you_page_id'] = isset(EE_Registry::instance()->CFG->core->thank_you_page_id)
367
+			? EE_Registry::instance()->CFG->core->thank_you_page_id
368
+			: null;
369
+		$this->_template_args['thank_you_page_obj'] = isset(EE_Registry::instance()->CFG->core->thank_you_page_id)
370
+			? get_page(EE_Registry::instance()->CFG->core->thank_you_page_id)
371
+			: false;
372
+		$this->_template_args['cancel_page_id'] = isset(EE_Registry::instance()->CFG->core->cancel_page_id)
373
+			? EE_Registry::instance()->CFG->core->cancel_page_id
374
+			: null;
375
+		$this->_template_args['cancel_page_obj'] = isset(EE_Registry::instance()->CFG->core->cancel_page_id)
376
+			? get_page(EE_Registry::instance()->CFG->core->cancel_page_id)
377
+			: false;
378
+		$this->_set_add_edit_form_tags('update_espresso_page_settings');
379
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
380
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
381
+			GEN_SET_TEMPLATE_PATH . 'espresso_page_settings.template.php',
382
+			$this->_template_args,
383
+			true
384
+		);
385
+		$this->display_admin_page_with_sidebar();
386
+	}
387
+
388
+
389
+	/**
390
+	 * Handler for updating espresso page settings.
391
+	 *
392
+	 * @throws EE_Error
393
+	 */
394
+	protected function _update_espresso_page_settings()
395
+	{
396
+		// capture incoming request data && set page IDs
397
+		EE_Registry::instance()->CFG->core->reg_page_id = isset($this->_req_data['reg_page_id'])
398
+			? absint($this->_req_data['reg_page_id'])
399
+			: EE_Registry::instance()->CFG->core->reg_page_id;
400
+		EE_Registry::instance()->CFG->core->txn_page_id = isset($this->_req_data['txn_page_id'])
401
+			? absint($this->_req_data['txn_page_id'])
402
+			: EE_Registry::instance()->CFG->core->txn_page_id;
403
+		EE_Registry::instance()->CFG->core->thank_you_page_id = isset($this->_req_data['thank_you_page_id'])
404
+			? absint($this->_req_data['thank_you_page_id'])
405
+			: EE_Registry::instance()->CFG->core->thank_you_page_id;
406
+		EE_Registry::instance()->CFG->core->cancel_page_id = isset($this->_req_data['cancel_page_id'])
407
+			? absint($this->_req_data['cancel_page_id'])
408
+			: EE_Registry::instance()->CFG->core->cancel_page_id;
409
+
410
+		EE_Registry::instance()->CFG->core = apply_filters(
411
+			'FHEE__General_Settings_Admin_Page___update_espresso_page_settings__CFG_core',
412
+			EE_Registry::instance()->CFG->core,
413
+			$this->_req_data
414
+		);
415
+		$what = esc_html__('Critical Pages & Shortcodes', 'event_espresso');
416
+		$this->_redirect_after_action(
417
+			$this->_update_espresso_configuration(
418
+				$what,
419
+				EE_Registry::instance()->CFG->core,
420
+				__FILE__,
421
+				__FUNCTION__,
422
+				__LINE__
423
+			),
424
+			$what,
425
+			'',
426
+			array(
427
+				'action' => 'critical_pages',
428
+			),
429
+			true
430
+		);
431
+	}
432
+
433
+
434
+	/*************        Your Organization        *************/
435
+
436
+
437
+	/**
438
+	 * @throws DomainException
439
+	 * @throws EE_Error
440
+	 * @throws InvalidArgumentException
441
+	 * @throws InvalidDataTypeException
442
+	 * @throws InvalidInterfaceException
443
+	 */
444
+	protected function _your_organization_settings()
445
+	{
446
+		$this->_template_args['admin_page_content'] = '';
447
+		try {
448
+			/** @var EventEspresso\admin_pages\general_settings\OrganizationSettings $organization_settings_form */
449
+			$organization_settings_form = $this->loader->getShared(
450
+				'EventEspresso\admin_pages\general_settings\OrganizationSettings'
451
+			);
452
+			$this->_template_args['admin_page_content'] = $organization_settings_form->display();
453
+		} catch (Exception $e) {
454
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
455
+		}
456
+		$this->_set_add_edit_form_tags('update_your_organization_settings');
457
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
458
+		$this->display_admin_page_with_sidebar();
459
+	}
460
+
461
+
462
+	/**
463
+	 * Handler for updating organization settings.
464
+	 *
465
+	 * @throws EE_Error
466
+	 */
467
+	protected function _update_your_organization_settings()
468
+	{
469
+		try {
470
+			/** @var EventEspresso\admin_pages\general_settings\OrganizationSettings $organization_settings_form */
471
+			$organization_settings_form = $this->loader->getShared(
472
+				'EventEspresso\admin_pages\general_settings\OrganizationSettings'
473
+			);
474
+			$success = $organization_settings_form->process($this->_req_data);
475
+			EE_Registry::instance()->CFG = apply_filters(
476
+				'FHEE__General_Settings_Admin_Page___update_your_organization_settings__CFG',
477
+				EE_Registry::instance()->CFG
478
+			);
479
+		} catch (Exception $e) {
480
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
481
+			$success = false;
482
+		}
483
+
484
+		if ($success) {
485
+			$success = $this->_update_espresso_configuration(
486
+				esc_html__('Your Organization Settings', 'event_espresso'),
487
+				EE_Registry::instance()->CFG,
488
+				__FILE__,
489
+				__FUNCTION__,
490
+				__LINE__
491
+			);
492
+		}
493
+
494
+		$this->_redirect_after_action($success, '', '', array('action' => 'default'), true);
495
+	}
496
+
497
+
498
+
499
+	/*************        Admin Options        *************/
500
+
501
+
502
+	/**
503
+	 * _admin_option_settings
504
+	 *
505
+	 * @throws \EE_Error
506
+	 * @throws \LogicException
507
+	 */
508
+	protected function _admin_option_settings()
509
+	{
510
+		$this->_template_args['admin_page_content'] = '';
511
+		try {
512
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
513
+			// still need this for the old school form in Extend_General_Settings_Admin_Page
514
+			$this->_template_args['values'] = $this->_yes_no_values;
515
+			// also need to account for the do_action that was in the old template
516
+			$admin_options_settings_form->setTemplateArgs($this->_template_args);
517
+			$this->_template_args['admin_page_content'] = $admin_options_settings_form->display();
518
+		} catch (Exception $e) {
519
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
+		}
521
+		$this->_set_add_edit_form_tags('update_admin_option_settings');
522
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
523
+		$this->display_admin_page_with_sidebar();
524
+	}
525
+
526
+
527
+	/**
528
+	 * _update_admin_option_settings
529
+	 *
530
+	 * @throws \EE_Error
531
+	 * @throws InvalidDataTypeException
532
+	 * @throws \EventEspresso\core\exceptions\InvalidFormSubmissionException
533
+	 * @throws \InvalidArgumentException
534
+	 * @throws \LogicException
535
+	 */
536
+	protected function _update_admin_option_settings()
537
+	{
538
+		try {
539
+			$admin_options_settings_form = new AdminOptionsSettings(EE_Registry::instance());
540
+			$admin_options_settings_form->process($this->_req_data[ $admin_options_settings_form->slug() ]);
541
+			EE_Registry::instance()->CFG->admin = apply_filters(
542
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__CFG_admin',
543
+				EE_Registry::instance()->CFG->admin
544
+			);
545
+		} catch (Exception $e) {
546
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
547
+		}
548
+		$this->_redirect_after_action(
549
+			apply_filters(
550
+				'FHEE__General_Settings_Admin_Page___update_admin_option_settings__success',
551
+				$this->_update_espresso_configuration(
552
+					'Admin Options',
553
+					EE_Registry::instance()->CFG->admin,
554
+					__FILE__,
555
+					__FUNCTION__,
556
+					__LINE__
557
+				)
558
+			),
559
+			'Admin Options',
560
+			'updated',
561
+			array('action' => 'admin_option_settings')
562
+		);
563
+	}
564
+
565
+
566
+	/*************        Countries        *************/
567
+
568
+
569
+	/**
570
+	 * @return string
571
+	 */
572
+	protected function getCountryIsoForSite()
573
+	{
574
+		return ! empty(EE_Registry::instance()->CFG->organization->CNT_ISO)
575
+			? EE_Registry::instance()->CFG->organization->CNT_ISO
576
+			: 'US';
577
+	}
578
+
579
+
580
+	/**
581
+	 * @param string          $CNT_ISO
582
+	 * @param EE_Country|null $country
583
+	 * @return EE_Base_Class|EE_Country
584
+	 * @throws EE_Error
585
+	 * @throws InvalidArgumentException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws InvalidInterfaceException
588
+	 * @throws ReflectionException
589
+	 */
590
+	protected function verifyOrGetCountryFromIso($CNT_ISO, EE_Country $country = null)
591
+	{
592
+		/** @var EE_Country $country */
593
+		return $country instanceof EE_Country && $country->ID() === $CNT_ISO
594
+			? $country
595
+			: EEM_Country::instance()->get_one_by_ID($CNT_ISO);
596
+	}
597
+
598
+
599
+	/**
600
+	 * Output Country Settings view.
601
+	 *
602
+	 * @throws DomainException
603
+	 * @throws EE_Error
604
+	 * @throws InvalidArgumentException
605
+	 * @throws InvalidDataTypeException
606
+	 * @throws InvalidInterfaceException
607
+	 * @throws ReflectionException
608
+	 */
609
+	protected function _country_settings()
610
+	{
611
+		$CNT_ISO_for_site = $this->getCountryIsoForSite();
612
+		$CNT_ISO = isset($this->_req_data['country'])
613
+			? strtoupper(sanitize_text_field($this->_req_data['country']))
614
+			: $CNT_ISO_for_site;
615
+
616
+		// load field generator helper
617
+
618
+		$this->_template_args['values'] = $this->_yes_no_values;
619
+
620
+		$this->_template_args['countries'] = new EE_Question_Form_Input(
621
+			EE_Question::new_instance(
622
+				array(
623
+					'QST_ID'           => 0,
624
+					'QST_display_text' => esc_html__('Select Country', 'event_espresso'),
625
+					'QST_system'       => 'admin-country',
626
+				)
627
+			),
628
+			EE_Answer::new_instance(
629
+				array(
630
+					'ANS_ID'    => 0,
631
+					'ANS_value' => $CNT_ISO,
632
+				)
633
+			),
634
+			array(
635
+				'input_id'       => 'country',
636
+				'input_name'     => 'country',
637
+				'input_prefix'   => '',
638
+				'append_qstn_id' => false,
639
+			)
640
+		);
641
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO_for_site);
642
+		add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'country_form_field_label_wrap'), 10, 2);
643
+		add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'country_form_field_input__wrap'), 10, 2);
644
+		$this->_template_args['country_details_settings'] = $this->display_country_settings(
645
+			$country->ID(),
646
+			$country
647
+		);
648
+		$this->_template_args['country_states_settings'] = $this->display_country_states(
649
+			$country->ID(),
650
+			$country
651
+		);
652
+		$this->_template_args['CNT_name_for_site'] = $country->name();
653
+
654
+		$this->_set_add_edit_form_tags('update_country_settings');
655
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
656
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
657
+			GEN_SET_TEMPLATE_PATH . 'countries_settings.template.php',
658
+			$this->_template_args,
659
+			true
660
+		);
661
+		$this->display_admin_page_with_no_sidebar();
662
+	}
663
+
664
+
665
+	/**
666
+	 *        display_country_settings
667
+	 *
668
+	 * @param string          $CNT_ISO
669
+	 * @param EE_Country|null $country
670
+	 * @return mixed string | array$country
671
+	 * @throws DomainException
672
+	 * @throws EE_Error
673
+	 * @throws InvalidArgumentException
674
+	 * @throws InvalidDataTypeException
675
+	 * @throws InvalidInterfaceException
676
+	 * @throws ReflectionException
677
+	 */
678
+	public function display_country_settings($CNT_ISO = '', EE_Country $country = null)
679
+	{
680
+		$CNT_ISO_for_site = $this->getCountryIsoForSite();
681
+
682
+		$CNT_ISO = isset($this->_req_data['country'])
683
+			? strtoupper(sanitize_text_field($this->_req_data['country']))
684
+			: $CNT_ISO;
685
+		if (! $CNT_ISO) {
686
+			return '';
687
+		}
688
+
689
+		// for ajax
690
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
691
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
692
+		add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'country_form_field_label_wrap'), 10, 2);
693
+		add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'country_form_field_input__wrap'), 10, 2);
694
+		$country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
695
+		$CNT_cur_disabled = $CNT_ISO !== $CNT_ISO_for_site;
696
+		$this->_template_args['CNT_cur_disabled'] = $CNT_cur_disabled;
697
+
698
+		$country_input_types = array(
699
+			'CNT_active'      => array(
700
+				'type'             => 'RADIO_BTN',
701
+				'input_name'       => 'cntry[' . $CNT_ISO . ']',
702
+				'class'            => '',
703
+				'options'          => $this->_yes_no_values,
704
+				'use_desc_4_label' => true,
705
+			),
706
+			'CNT_ISO'         => array(
707
+				'type'       => 'TEXT',
708
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
709
+				'class'      => 'small-text',
710
+			),
711
+			'CNT_ISO3'        => array(
712
+				'type'       => 'TEXT',
713
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
714
+				'class'      => 'small-text',
715
+			),
716
+			'RGN_ID'          => array(
717
+				'type'       => 'TEXT',
718
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
719
+				'class'      => 'small-text',
720
+			),
721
+			'CNT_name'        => array(
722
+				'type'       => 'TEXT',
723
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
724
+				'class'      => 'regular-text',
725
+			),
726
+			'CNT_cur_code'    => array(
727
+				'type'       => 'TEXT',
728
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
729
+				'class'      => 'small-text',
730
+				'disabled'   => $CNT_cur_disabled,
731
+			),
732
+			'CNT_cur_single'  => array(
733
+				'type'       => 'TEXT',
734
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
735
+				'class'      => 'medium-text',
736
+				'disabled'   => $CNT_cur_disabled,
737
+			),
738
+			'CNT_cur_plural'  => array(
739
+				'type'       => 'TEXT',
740
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
741
+				'class'      => 'medium-text',
742
+				'disabled'   => $CNT_cur_disabled,
743
+			),
744
+			'CNT_cur_sign'    => array(
745
+				'type'         => 'TEXT',
746
+				'input_name'   => 'cntry[' . $CNT_ISO . ']',
747
+				'class'        => 'small-text',
748
+				'htmlentities' => false,
749
+				'disabled'     => $CNT_cur_disabled,
750
+			),
751
+			'CNT_cur_sign_b4' => array(
752
+				'type'             => 'RADIO_BTN',
753
+				'input_name'       => 'cntry[' . $CNT_ISO . ']',
754
+				'class'            => '',
755
+				'options'          => $this->_yes_no_values,
756
+				'use_desc_4_label' => true,
757
+				'disabled'         => $CNT_cur_disabled,
758
+			),
759
+			'CNT_cur_dec_plc' => array(
760
+				'type'       => 'RADIO_BTN',
761
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
762
+				'class'      => '',
763
+				'options'    => array(
764
+					array('id' => 0, 'text' => ''),
765
+					array('id' => 1, 'text' => ''),
766
+					array('id' => 2, 'text' => ''),
767
+					array('id' => 3, 'text' => ''),
768
+				),
769
+				'disabled'   => $CNT_cur_disabled,
770
+			),
771
+			'CNT_cur_dec_mrk' => array(
772
+				'type'             => 'RADIO_BTN',
773
+				'input_name'       => 'cntry[' . $CNT_ISO . ']',
774
+				'class'            => '',
775
+				'options'          => array(
776
+					array(
777
+						'id'   => ',',
778
+						'text' => esc_html__(', (comma)', 'event_espresso'),
779
+					),
780
+					array('id' => '.', 'text' => esc_html__('. (decimal)', 'event_espresso')),
781
+				),
782
+				'use_desc_4_label' => true,
783
+				'disabled'         => $CNT_cur_disabled,
784
+			),
785
+			'CNT_cur_thsnds'  => array(
786
+				'type'             => 'RADIO_BTN',
787
+				'input_name'       => 'cntry[' . $CNT_ISO . ']',
788
+				'class'            => '',
789
+				'options'          => array(
790
+					array(
791
+						'id'   => ',',
792
+						'text' => esc_html__(', (comma)', 'event_espresso'),
793
+					),
794
+					array(
795
+						'id' => '.',
796
+						'text' => esc_html__('. (decimal)', 'event_espresso')
797
+					),
798
+					array(
799
+						'id' => '&nbsp;',
800
+						'text' => esc_html__('(space)', 'event_espresso')
801
+					)
802
+				),
803
+				'use_desc_4_label' => true,
804
+				'disabled'         => $CNT_cur_disabled,
805
+			),
806
+			'CNT_tel_code'    => array(
807
+				'type'       => 'TEXT',
808
+				'input_name' => 'cntry[' . $CNT_ISO . ']',
809
+				'class'      => 'small-text',
810
+			),
811
+			'CNT_is_EU'       => array(
812
+				'type'             => 'RADIO_BTN',
813
+				'input_name'       => 'cntry[' . $CNT_ISO . ']',
814
+				'class'            => '',
815
+				'options'          => $this->_yes_no_values,
816
+				'use_desc_4_label' => true,
817
+			),
818
+		);
819
+		$this->_template_args['inputs'] = EE_Question_Form_Input::generate_question_form_inputs_for_object(
820
+			$country,
821
+			$country_input_types
822
+		);
823
+		$country_details_settings = EEH_Template::display_template(
824
+			GEN_SET_TEMPLATE_PATH . 'country_details_settings.template.php',
825
+			$this->_template_args,
826
+			true
827
+		);
828
+
829
+		if (defined('DOING_AJAX')) {
830
+			$notices = EE_Error::get_notices(false, false, false);
831
+			echo wp_json_encode(
832
+				array(
833
+					'return_data' => $country_details_settings,
834
+					'success'     => $notices['success'],
835
+					'errors'      => $notices['errors'],
836
+				)
837
+			);
838
+			die();
839
+		} else {
840
+			return $country_details_settings;
841
+		}
842
+	}
843
+
844
+
845
+	/**
846
+	 * @param string          $CNT_ISO
847
+	 * @param EE_Country|null $country
848
+	 * @return string
849
+	 * @throws DomainException
850
+	 * @throws EE_Error
851
+	 * @throws InvalidArgumentException
852
+	 * @throws InvalidDataTypeException
853
+	 * @throws InvalidInterfaceException
854
+	 * @throws ReflectionException
855
+	 */
856
+	public function display_country_states($CNT_ISO = '', EE_Country $country = null)
857
+	{
858
+
859
+		$CNT_ISO = isset($this->_req_data['country'])
860
+			? sanitize_text_field($this->_req_data['country'])
861
+			: $CNT_ISO;
862
+		if (! $CNT_ISO) {
863
+			return '';
864
+		}
865
+		// for ajax
866
+		remove_all_filters('FHEE__EEH_Form_Fields__label_html');
867
+		remove_all_filters('FHEE__EEH_Form_Fields__input_html');
868
+		add_filter('FHEE__EEH_Form_Fields__label_html', array($this, 'state_form_field_label_wrap'), 10, 2);
869
+		add_filter('FHEE__EEH_Form_Fields__input_html', array($this, 'state_form_field_input__wrap'), 10, 2);
870
+		$states = EEM_State::instance()->get_all_states_for_these_countries(array($CNT_ISO => $CNT_ISO));
871
+		if (empty($states)) {
872
+			/** @var EventEspresso\core\services\address\CountrySubRegionDao $countrySubRegionDao */
873
+			$countrySubRegionDao = $this->loader->getShared(
874
+				'EventEspresso\core\services\address\CountrySubRegionDao'
875
+			);
876
+			if ($countrySubRegionDao instanceof EventEspresso\core\services\address\CountrySubRegionDao) {
877
+				$country = $this->verifyOrGetCountryFromIso($CNT_ISO, $country);
878
+				if ($countrySubRegionDao->saveCountrySubRegions($country)) {
879
+					$states = EEM_State::instance()->get_all_states_for_these_countries(
880
+						array($CNT_ISO => $CNT_ISO)
881
+					);
882
+				}
883
+			}
884
+		}
885
+		if (is_array($states)) {
886
+			foreach ($states as $STA_ID => $state) {
887
+				if ($state instanceof EE_State) {
888
+					// STA_abbrev    STA_name    STA_active
889
+					$state_input_types = array(
890
+						'STA_abbrev' => array(
891
+							'type'       => 'TEXT',
892
+							'input_name' => 'states[' . $STA_ID . ']',
893
+							'class'      => 'mid-text',
894
+						),
895
+						'STA_name'   => array(
896
+							'type'       => 'TEXT',
897
+							'input_name' => 'states[' . $STA_ID . ']',
898
+							'class'      => 'regular-text',
899
+						),
900
+						'STA_active' => array(
901
+							'type'             => 'RADIO_BTN',
902
+							'input_name'       => 'states[' . $STA_ID . ']',
903
+							'options'          => $this->_yes_no_values,
904
+							'use_desc_4_label' => true,
905
+						),
906
+					);
907
+					$this->_template_args['states'][ $STA_ID ]['inputs'] =
908
+						EE_Question_Form_Input::generate_question_form_inputs_for_object(
909
+							$state,
910
+							$state_input_types
911
+						);
912
+					$query_args = array(
913
+						'action'     => 'delete_state',
914
+						'STA_ID'     => $STA_ID,
915
+						'CNT_ISO'    => $CNT_ISO,
916
+						'STA_abbrev' => $state->abbrev(),
917
+					);
918
+					$this->_template_args['states'][ $STA_ID ]['delete_state_url'] =
919
+						EE_Admin_Page::add_query_args_and_nonce(
920
+							$query_args,
921
+							GEN_SET_ADMIN_URL
922
+						);
923
+				}
924
+			}
925
+		} else {
926
+			$this->_template_args['states'] = false;
927
+		}
928
+
929
+		$this->_template_args['add_new_state_url'] = EE_Admin_Page::add_query_args_and_nonce(
930
+			array('action' => 'add_new_state'),
931
+			GEN_SET_ADMIN_URL
932
+		);
933
+
934
+		$state_details_settings = EEH_Template::display_template(
935
+			GEN_SET_TEMPLATE_PATH . 'state_details_settings.template.php',
936
+			$this->_template_args,
937
+			true
938
+		);
939
+
940
+		if (defined('DOING_AJAX')) {
941
+			$notices = EE_Error::get_notices(false, false, false);
942
+			echo wp_json_encode(
943
+				array(
944
+					'return_data' => $state_details_settings,
945
+					'success'     => $notices['success'],
946
+					'errors'      => $notices['errors'],
947
+				)
948
+			);
949
+			die();
950
+		} else {
951
+			return $state_details_settings;
952
+		}
953
+	}
954
+
955
+
956
+	/**
957
+	 *        add_new_state
958
+	 *
959
+	 * @access    public
960
+	 * @return void
961
+	 * @throws EE_Error
962
+	 * @throws InvalidArgumentException
963
+	 * @throws InvalidDataTypeException
964
+	 * @throws InvalidInterfaceException
965
+	 */
966
+	public function add_new_state()
967
+	{
968
+
969
+		$success = true;
970
+
971
+		$CNT_ISO = isset($this->_req_data['CNT_ISO'])
972
+			? strtoupper(sanitize_text_field($this->_req_data['CNT_ISO']))
973
+			: false;
974
+		if (! $CNT_ISO) {
975
+			EE_Error::add_error(
976
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
977
+				__FILE__,
978
+				__FUNCTION__,
979
+				__LINE__
980
+			);
981
+			$success = false;
982
+		}
983
+		$STA_abbrev = isset($this->_req_data['STA_abbrev'])
984
+			? sanitize_text_field($this->_req_data['STA_abbrev'])
985
+			: false;
986
+		if (! $STA_abbrev) {
987
+			EE_Error::add_error(
988
+				esc_html__('No State ISO code or an invalid State ISO code was received.', 'event_espresso'),
989
+				__FILE__,
990
+				__FUNCTION__,
991
+				__LINE__
992
+			);
993
+			$success = false;
994
+		}
995
+		$STA_name = isset($this->_req_data['STA_name'])
996
+			? sanitize_text_field($this->_req_data['STA_name'])
997
+			: false;
998
+		if (! $STA_name) {
999
+			EE_Error::add_error(
1000
+				esc_html__('No State name or an invalid State name was received.', 'event_espresso'),
1001
+				__FILE__,
1002
+				__FUNCTION__,
1003
+				__LINE__
1004
+			);
1005
+			$success = false;
1006
+		}
1007
+
1008
+		if ($success) {
1009
+			$cols_n_values = array(
1010
+				'CNT_ISO'    => $CNT_ISO,
1011
+				'STA_abbrev' => $STA_abbrev,
1012
+				'STA_name'   => $STA_name,
1013
+				'STA_active' => true,
1014
+			);
1015
+			$success = EEM_State::instance()->insert($cols_n_values);
1016
+			EE_Error::add_success(esc_html__('The State was added successfully.', 'event_espresso'));
1017
+		}
1018
+
1019
+		if (defined('DOING_AJAX')) {
1020
+			$notices = EE_Error::get_notices(false, false, false);
1021
+			echo wp_json_encode(array_merge($notices, array('return_data' => $CNT_ISO)));
1022
+			die();
1023
+		} else {
1024
+			$this->_redirect_after_action($success, 'State', 'added', array('action' => 'country_settings'));
1025
+		}
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 *        delete_state
1031
+	 *
1032
+	 * @access    public
1033
+	 * @return        boolean
1034
+	 * @throws EE_Error
1035
+	 * @throws InvalidArgumentException
1036
+	 * @throws InvalidDataTypeException
1037
+	 * @throws InvalidInterfaceException
1038
+	 */
1039
+	public function delete_state()
1040
+	{
1041
+		$CNT_ISO = isset($this->_req_data['CNT_ISO'])
1042
+			? strtoupper(sanitize_text_field($this->_req_data['CNT_ISO']))
1043
+			: false;
1044
+		$STA_ID = isset($this->_req_data['STA_ID'])
1045
+			? sanitize_text_field($this->_req_data['STA_ID'])
1046
+			: false;
1047
+		$STA_abbrev = isset($this->_req_data['STA_abbrev'])
1048
+			? sanitize_text_field($this->_req_data['STA_abbrev'])
1049
+			: false;
1050
+		if (! $STA_ID) {
1051
+			EE_Error::add_error(
1052
+				esc_html__('No State ID or an invalid State ID was received.', 'event_espresso'),
1053
+				__FILE__,
1054
+				__FUNCTION__,
1055
+				__LINE__
1056
+			);
1057
+			return false;
1058
+		}
1059
+
1060
+		$success = EEM_State::instance()->delete_by_ID($STA_ID);
1061
+		if ($success !== false) {
1062
+			do_action(
1063
+				'AHEE__General_Settings_Admin_Page__delete_state__state_deleted',
1064
+				$CNT_ISO,
1065
+				$STA_ID,
1066
+				array('STA_abbrev' => $STA_abbrev)
1067
+			);
1068
+			EE_Error::add_success(esc_html__('The State was deleted successfully.', 'event_espresso'));
1069
+		}
1070
+		if (defined('DOING_AJAX')) {
1071
+			$notices = EE_Error::get_notices(false, false);
1072
+			$notices['return_data'] = true;
1073
+			echo wp_json_encode($notices);
1074
+			die();
1075
+		} else {
1076
+			$this->_redirect_after_action(
1077
+				$success,
1078
+				'State',
1079
+				'deleted',
1080
+				array('action' => 'country_settings')
1081
+			);
1082
+		}
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 *        _update_country_settings
1088
+	 *
1089
+	 * @access    protected
1090
+	 * @return void
1091
+	 * @throws EE_Error
1092
+	 * @throws InvalidArgumentException
1093
+	 * @throws InvalidDataTypeException
1094
+	 * @throws InvalidInterfaceException
1095
+	 */
1096
+	protected function _update_country_settings()
1097
+	{
1098
+		// grab the country ISO code
1099
+		$CNT_ISO = isset($this->_req_data['country'])
1100
+			? strtoupper(sanitize_text_field($this->_req_data['country']))
1101
+			: false;
1102
+		if (! $CNT_ISO) {
1103
+			EE_Error::add_error(
1104
+				esc_html__('No Country ISO code or an invalid Country ISO code was received.', 'event_espresso'),
1105
+				__FILE__,
1106
+				__FUNCTION__,
1107
+				__LINE__
1108
+			);
1109
+
1110
+			return;
1111
+		}
1112
+		$cols_n_values = array();
1113
+		$cols_n_values['CNT_ISO3'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_ISO3'])
1114
+			? strtoupper(sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_ISO3']))
1115
+			: false;
1116
+		$cols_n_values['RGN_ID'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['RGN_ID'])
1117
+			? absint($this->_req_data['cntry'][ $CNT_ISO ]['RGN_ID'])
1118
+			: null;
1119
+		$cols_n_values['CNT_name'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_name'])
1120
+			? sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_name'])
1121
+			: null;
1122
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_code'])) {
1123
+			$cols_n_values['CNT_cur_code'] = strtoupper(
1124
+				sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_code'])
1125
+			);
1126
+		}
1127
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_single'])) {
1128
+			$cols_n_values['CNT_cur_single'] = sanitize_text_field(
1129
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_single']
1130
+			);
1131
+		}
1132
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_plural'])) {
1133
+			$cols_n_values['CNT_cur_plural'] = sanitize_text_field(
1134
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_plural']
1135
+			);
1136
+		}
1137
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign'])) {
1138
+			$cols_n_values['CNT_cur_sign'] = sanitize_text_field(
1139
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign']
1140
+			);
1141
+		}
1142
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign_b4'])) {
1143
+			$cols_n_values['CNT_cur_sign_b4'] = absint(
1144
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_sign_b4']
1145
+			);
1146
+		}
1147
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_plc'])) {
1148
+			$cols_n_values['CNT_cur_dec_plc'] = absint(
1149
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_plc']
1150
+			);
1151
+		}
1152
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_mrk'])) {
1153
+			$cols_n_values['CNT_cur_dec_mrk'] = sanitize_text_field(
1154
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_dec_mrk']
1155
+			);
1156
+		}
1157
+		if (isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_thsnds'])) {
1158
+			$cols_n_values['CNT_cur_thsnds'] = sanitize_text_field(
1159
+				$this->_req_data['cntry'][ $CNT_ISO ]['CNT_cur_thsnds']
1160
+			);
1161
+		}
1162
+		$cols_n_values['CNT_tel_code'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_tel_code'])
1163
+			? sanitize_text_field($this->_req_data['cntry'][ $CNT_ISO ]['CNT_tel_code'])
1164
+			: null;
1165
+		$cols_n_values['CNT_is_EU'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_is_EU'])
1166
+			? absint($this->_req_data['cntry'][ $CNT_ISO ]['CNT_is_EU'])
1167
+			: false;
1168
+		$cols_n_values['CNT_active'] = isset($this->_req_data['cntry'][ $CNT_ISO ]['CNT_active'])
1169
+			? absint($this->_req_data['cntry'][ $CNT_ISO ]['CNT_active'])
1170
+			: false;
1171
+		// allow filtering of country data
1172
+		$cols_n_values = apply_filters(
1173
+			'FHEE__General_Settings_Admin_Page___update_country_settings__cols_n_values',
1174
+			$cols_n_values
1175
+		);
1176
+
1177
+		// where values
1178
+		$where_cols_n_values = array(array('CNT_ISO' => $CNT_ISO));
1179
+		// run the update
1180
+		$success = EEM_Country::instance()->update($cols_n_values, $where_cols_n_values);
1181
+
1182
+		if (isset($this->_req_data['states']) && is_array($this->_req_data['states']) && $success !== false) {
1183
+			// allow filtering of states data
1184
+			$states = apply_filters(
1185
+				'FHEE__General_Settings_Admin_Page___update_country_settings__states',
1186
+				$this->_req_data['states']
1187
+			);
1188
+
1189
+			// loop thru state data ( looks like : states[75][STA_name] )
1190
+			foreach ($states as $STA_ID => $state) {
1191
+				$cols_n_values = array(
1192
+					'CNT_ISO'    => $CNT_ISO,
1193
+					'STA_abbrev' => sanitize_text_field($state['STA_abbrev']),
1194
+					'STA_name'   => sanitize_text_field($state['STA_name']),
1195
+					'STA_active' => (bool) absint($state['STA_active']),
1196
+				);
1197
+				// where values
1198
+				$where_cols_n_values = array(array('STA_ID' => $STA_ID));
1199
+				// run the update
1200
+				$success = EEM_State::instance()->update($cols_n_values, $where_cols_n_values);
1201
+				if ($success !== false) {
1202
+					do_action(
1203
+						'AHEE__General_Settings_Admin_Page__update_country_settings__state_saved',
1204
+						$CNT_ISO,
1205
+						$STA_ID,
1206
+						$cols_n_values
1207
+					);
1208
+				}
1209
+			}
1210
+		}
1211
+		// check if country being edited matches org option country, and if so, then  update EE_Config with new settings
1212
+		if (isset(EE_Registry::instance()->CFG->organization->CNT_ISO)
1213
+			&& $CNT_ISO == EE_Registry::instance()->CFG->organization->CNT_ISO
1214
+		) {
1215
+			EE_Registry::instance()->CFG->currency = new EE_Currency_Config($CNT_ISO);
1216
+			EE_Registry::instance()->CFG->update_espresso_config();
1217
+		}
1218
+
1219
+		if ($success !== false) {
1220
+			EE_Error::add_success(
1221
+				esc_html__('Country Settings updated successfully.', 'event_espresso')
1222
+			);
1223
+		}
1224
+		$this->_redirect_after_action(
1225
+			$success,
1226
+			'',
1227
+			'',
1228
+			array('action' => 'country_settings', 'country' => $CNT_ISO),
1229
+			true
1230
+		);
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 *        form_form_field_label_wrap
1236
+	 *
1237
+	 * @access        public
1238
+	 * @param        string $label
1239
+	 * @return        string
1240
+	 */
1241
+	public function country_form_field_label_wrap($label, $required_text)
1242
+	{
1243
+		return '
1244 1244
 			<tr>
1245 1245
 				<th>
1246 1246
 					' . $label . '
1247 1247
 				</th>';
1248
-    }
1249
-
1250
-
1251
-    /**
1252
-     *        form_form_field_input__wrap
1253
-     *
1254
-     * @access        public
1255
-     * @param        string $label
1256
-     * @return        string
1257
-     */
1258
-    public function country_form_field_input__wrap($input, $label)
1259
-    {
1260
-        return '
1248
+	}
1249
+
1250
+
1251
+	/**
1252
+	 *        form_form_field_input__wrap
1253
+	 *
1254
+	 * @access        public
1255
+	 * @param        string $label
1256
+	 * @return        string
1257
+	 */
1258
+	public function country_form_field_input__wrap($input, $label)
1259
+	{
1260
+		return '
1261 1261
 				<td class="general-settings-country-input-td">
1262 1262
 					' . $input . '
1263 1263
 				</td>
1264 1264
 			</tr>';
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     *        form_form_field_label_wrap
1270
-     *
1271
-     * @access        public
1272
-     * @param        string $label
1273
-     * @param        string $required_text
1274
-     * @return        string
1275
-     */
1276
-    public function state_form_field_label_wrap($label, $required_text)
1277
-    {
1278
-        return $required_text;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     *        form_form_field_input__wrap
1284
-     *
1285
-     * @access        public
1286
-     * @param        string $label
1287
-     * @return        string
1288
-     */
1289
-    public function state_form_field_input__wrap($input, $label)
1290
-    {
1291
-        return '
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 *        form_form_field_label_wrap
1270
+	 *
1271
+	 * @access        public
1272
+	 * @param        string $label
1273
+	 * @param        string $required_text
1274
+	 * @return        string
1275
+	 */
1276
+	public function state_form_field_label_wrap($label, $required_text)
1277
+	{
1278
+		return $required_text;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 *        form_form_field_input__wrap
1284
+	 *
1285
+	 * @access        public
1286
+	 * @param        string $label
1287
+	 * @return        string
1288
+	 */
1289
+	public function state_form_field_input__wrap($input, $label)
1290
+	{
1291
+		return '
1292 1292
 				<td class="general-settings-country-state-input-td">
1293 1293
 					' . $input . '
1294 1294
 				</td>';
1295
-    }
1296
-
1297
-
1298
-    /***********/
1299
-
1300
-
1301
-    /**
1302
-     * displays edit and view links for critical EE pages
1303
-     *
1304
-     * @access public
1305
-     * @param int $ee_page_id
1306
-     * @return string
1307
-     */
1308
-    public static function edit_view_links($ee_page_id)
1309
-    {
1310
-        $links = '<a href="'
1311
-                 . add_query_arg(
1312
-                     array('post' => $ee_page_id, 'action' => 'edit'),
1313
-                     admin_url('post.php')
1314
-                 )
1315
-                 . '" >'
1316
-                 . esc_html__('Edit', 'event_espresso')
1317
-                 . '</a>';
1318
-        $links .= ' &nbsp;|&nbsp; ';
1319
-        $links .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1320
-
1321
-        return $links;
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * displays page and shortcode status for critical EE pages
1327
-     *
1328
-     * @param WP page object $ee_page
1329
-     * @return string
1330
-     */
1331
-    public static function page_and_shortcode_status($ee_page, $shortcode)
1332
-    {
1333
-
1334
-        // page status
1335
-        if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1336
-            $pg_colour = 'green';
1337
-            $pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1338
-        } else {
1339
-            $pg_colour = 'red';
1340
-            $pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1341
-        }
1342
-
1343
-        // shortcode status
1344
-        if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1345
-            $sc_colour = 'green';
1346
-            $sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1347
-        } else {
1348
-            $sc_colour = 'red';
1349
-            $sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1350
-        }
1351
-
1352
-        return '<span style="color:' . $pg_colour . '; margin-right:2em;"><strong>'
1353
-               . $pg_status
1354
-               . '</strong></span><span style="color:' . $sc_colour . '"><strong>' . $sc_status . '</strong></span>';
1355
-    }
1356
-
1357
-
1358
-    /**
1359
-     * generates a dropdown of all parent pages - copied from WP core
1360
-     *
1361
-     * @param int $default
1362
-     * @param int $parent
1363
-     * @param int $level
1364
-     */
1365
-    public static function page_settings_dropdown($default = 0, $parent = 0, $level = 0)
1366
-    {
1367
-        global $wpdb;
1368
-        $items = $wpdb->get_results(
1369
-            $wpdb->prepare(
1370
-                "SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' AND post_status != 'trash' ORDER BY menu_order",
1371
-                $parent
1372
-            )
1373
-        );
1374
-
1375
-        if ($items) {
1376
-            foreach ($items as $item) {
1377
-                $pad = str_repeat('&nbsp;', $level * 3);
1378
-                if ($item->ID == $default) {
1379
-                    $current = ' selected="selected"';
1380
-                } else {
1381
-                    $current = '';
1382
-                }
1383
-
1384
-                echo "\n\t<option class='level-$level' value='$item->ID'$current>$pad "
1385
-                     . esc_html($item->post_title)
1386
-                     . "</option>";
1387
-                parent_dropdown($default, $item->ID, $level + 1);
1388
-            }
1389
-        }
1390
-    }
1391
-
1392
-
1393
-    /**
1394
-     * Loads the scripts for the privacy settings form
1395
-     */
1396
-    public function load_scripts_styles_privacy_settings()
1397
-    {
1398
-        $form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1399
-        $form_handler->enqueueStylesAndScripts();
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * display the privacy settings form
1405
-     */
1406
-    public function privacySettings()
1407
-    {
1408
-        $this->_set_add_edit_form_tags('update_privacy_settings');
1409
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
1410
-        $form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1411
-        $this->_template_args['admin_page_content'] = $form_handler->display();
1412
-        $this->display_admin_page_with_sidebar();
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * Update the privacy settings from form data
1418
-     *
1419
-     * @throws EE_Error
1420
-     */
1421
-    public function updatePrivacySettings()
1422
-    {
1423
-        $form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1424
-        $success = $form_handler->process($this->get_request_data());
1425
-        $this->_redirect_after_action(
1426
-            $success,
1427
-            esc_html__('Registration Form Options', 'event_espresso'),
1428
-            'updated',
1429
-            array('action' => 'privacy_settings')
1430
-        );
1431
-    }
1295
+	}
1296
+
1297
+
1298
+	/***********/
1299
+
1300
+
1301
+	/**
1302
+	 * displays edit and view links for critical EE pages
1303
+	 *
1304
+	 * @access public
1305
+	 * @param int $ee_page_id
1306
+	 * @return string
1307
+	 */
1308
+	public static function edit_view_links($ee_page_id)
1309
+	{
1310
+		$links = '<a href="'
1311
+				 . add_query_arg(
1312
+					 array('post' => $ee_page_id, 'action' => 'edit'),
1313
+					 admin_url('post.php')
1314
+				 )
1315
+				 . '" >'
1316
+				 . esc_html__('Edit', 'event_espresso')
1317
+				 . '</a>';
1318
+		$links .= ' &nbsp;|&nbsp; ';
1319
+		$links .= '<a href="' . get_permalink($ee_page_id) . '" >' . esc_html__('View', 'event_espresso') . '</a>';
1320
+
1321
+		return $links;
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * displays page and shortcode status for critical EE pages
1327
+	 *
1328
+	 * @param WP page object $ee_page
1329
+	 * @return string
1330
+	 */
1331
+	public static function page_and_shortcode_status($ee_page, $shortcode)
1332
+	{
1333
+
1334
+		// page status
1335
+		if (isset($ee_page->post_status) && $ee_page->post_status == 'publish') {
1336
+			$pg_colour = 'green';
1337
+			$pg_status = sprintf(esc_html__('Page%sStatus%sOK', 'event_espresso'), '&nbsp;', '&nbsp;');
1338
+		} else {
1339
+			$pg_colour = 'red';
1340
+			$pg_status = sprintf(esc_html__('Page%sVisibility%sProblem', 'event_espresso'), '&nbsp;', '&nbsp;');
1341
+		}
1342
+
1343
+		// shortcode status
1344
+		if (isset($ee_page->post_content) && strpos($ee_page->post_content, $shortcode) !== false) {
1345
+			$sc_colour = 'green';
1346
+			$sc_status = sprintf(esc_html__('Shortcode%sOK', 'event_espresso'), '&nbsp;');
1347
+		} else {
1348
+			$sc_colour = 'red';
1349
+			$sc_status = sprintf(esc_html__('Shortcode%sProblem', 'event_espresso'), '&nbsp;');
1350
+		}
1351
+
1352
+		return '<span style="color:' . $pg_colour . '; margin-right:2em;"><strong>'
1353
+			   . $pg_status
1354
+			   . '</strong></span><span style="color:' . $sc_colour . '"><strong>' . $sc_status . '</strong></span>';
1355
+	}
1356
+
1357
+
1358
+	/**
1359
+	 * generates a dropdown of all parent pages - copied from WP core
1360
+	 *
1361
+	 * @param int $default
1362
+	 * @param int $parent
1363
+	 * @param int $level
1364
+	 */
1365
+	public static function page_settings_dropdown($default = 0, $parent = 0, $level = 0)
1366
+	{
1367
+		global $wpdb;
1368
+		$items = $wpdb->get_results(
1369
+			$wpdb->prepare(
1370
+				"SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' AND post_status != 'trash' ORDER BY menu_order",
1371
+				$parent
1372
+			)
1373
+		);
1374
+
1375
+		if ($items) {
1376
+			foreach ($items as $item) {
1377
+				$pad = str_repeat('&nbsp;', $level * 3);
1378
+				if ($item->ID == $default) {
1379
+					$current = ' selected="selected"';
1380
+				} else {
1381
+					$current = '';
1382
+				}
1383
+
1384
+				echo "\n\t<option class='level-$level' value='$item->ID'$current>$pad "
1385
+					 . esc_html($item->post_title)
1386
+					 . "</option>";
1387
+				parent_dropdown($default, $item->ID, $level + 1);
1388
+			}
1389
+		}
1390
+	}
1391
+
1392
+
1393
+	/**
1394
+	 * Loads the scripts for the privacy settings form
1395
+	 */
1396
+	public function load_scripts_styles_privacy_settings()
1397
+	{
1398
+		$form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1399
+		$form_handler->enqueueStylesAndScripts();
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * display the privacy settings form
1405
+	 */
1406
+	public function privacySettings()
1407
+	{
1408
+		$this->_set_add_edit_form_tags('update_privacy_settings');
1409
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
1410
+		$form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1411
+		$this->_template_args['admin_page_content'] = $form_handler->display();
1412
+		$this->display_admin_page_with_sidebar();
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * Update the privacy settings from form data
1418
+	 *
1419
+	 * @throws EE_Error
1420
+	 */
1421
+	public function updatePrivacySettings()
1422
+	{
1423
+		$form_handler = $this->loader->getShared('EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler');
1424
+		$success = $form_handler->process($this->get_request_data());
1425
+		$this->_redirect_after_action(
1426
+			$success,
1427
+			esc_html__('Registration Form Options', 'event_espresso'),
1428
+			'updated',
1429
+			array('action' => 'privacy_settings')
1430
+		);
1431
+	}
1432 1432
 }
Please login to merge, or discard this patch.