Completed
Branch FET-10857-model-field-factory (adac96)
by
unknown
140:18 queued 129:14
created
admin_pages/transactions/EE_Admin_Transactions_List_Table.class.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      *
103 103
      * @abstract
104 104
      * @access protected
105
-     * @return array
105
+     * @return string[]
106 106
      */
107 107
     protected function _get_table_filters()
108 108
     {
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
      *    column_TXN_paid
266 266
      *
267 267
      * @param \EE_Transaction $transaction
268
-     * @return mixed|string
268
+     * @return string
269 269
      * @throws \EE_Error
270 270
      */
271 271
     public function column_TXN_paid(EE_Transaction $transaction)
Please login to merge, or discard this patch.
Indentation   +606 added lines, -606 removed lines patch added patch discarded remove patch
@@ -13,114 +13,114 @@  discard block
 block discarded – undo
13 13
 class EE_Admin_Transactions_List_Table extends EE_Admin_List_Table
14 14
 {
15 15
 
16
-    private $_status;
17
-
18
-
19
-    /**
20
-     * @param \Transactions_Admin_Page $admin_page
21
-     */
22
-    public function __construct(\Transactions_Admin_Page $admin_page)
23
-    {
24
-        parent::__construct($admin_page);
25
-        $this->_status = $this->_admin_page->get_transaction_status_array();
26
-    }
27
-
28
-
29
-    /**
30
-     *_setup_data
31
-     */
32
-    protected function _setup_data()
33
-    {
34
-        $this->_data           = $this->_admin_page->get_transactions($this->_per_page);
35
-        $status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
36
-        $this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
37
-    }
38
-
39
-
40
-    /**
41
-     *_set_properties
42
-     */
43
-    protected function _set_properties()
44
-    {
45
-        $this->_wp_list_args = array(
46
-            'singular' => __('transaction', 'event_espresso'),
47
-            'plural'   => __('transactions', 'event_espresso'),
48
-            'ajax'     => true,
49
-            'screen'   => $this->_admin_page->get_current_screen()->id,
50
-        );
51
-        $ID_column_name      = __('ID', 'event_espresso');
52
-        $ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53
-        $ID_column_name      .= __('Transaction Date', 'event_espresso');
54
-        $ID_column_name      .= '</span> ';
55
-        $this->_columns      = array(
56
-            'TXN_ID'        => $ID_column_name,
57
-            'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58
-            'TXN_total'     => __('Total', 'event_espresso'),
59
-            'TXN_paid'      => __('Paid', 'event_espresso'),
60
-            'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
61
-            'event_name'    => __('Event', 'event_espresso'),
62
-            'actions'       => __('Actions', 'event_espresso'),
63
-        );
64
-
65
-        $this->_sortable_columns = array(
66
-            'TXN_ID'        => array('TXN_ID' => false),
67
-            'event_name'    => array('event_name' => false),
68
-            'ATT_fname'     => array('ATT_fname' => false),
69
-            'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
70
-        );
71
-
72
-        $this->_primary_column = 'TXN_ID';
73
-
74
-        $this->_hidden_columns = array();
75
-    }
76
-
77
-
78
-    /**
79
-     * This simply sets up the row class for the table rows.
80
-     * Allows for easier overriding of child methods for setting up sorting.
81
-     *
82
-     * @param  EE_Transaction $transaction the current item
83
-     * @return string
84
-     * @throws \EE_Error
85
-     */
86
-    protected function _get_row_class($transaction)
87
-    {
88
-        $class = parent::_get_row_class($transaction);
89
-        //add status class
90
-        $class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
91
-        if ($this->_has_checkbox_column) {
92
-            $class .= ' has-checkbox-column';
93
-        }
94
-        return $class;
95
-    }
96
-
97
-
98
-    /**
99
-     * _get_table_filters
100
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
101
-     * get's shown in the table.
102
-     *
103
-     * @abstract
104
-     * @access protected
105
-     * @return array
106
-     */
107
-    protected function _get_table_filters()
108
-    {
109
-        $filters    = array();
110
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
111
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
112
-            : date(
113
-                'm/d/Y',
114
-                strtotime('-10 year')
115
-            );
116
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
117
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118
-            : date(
119
-                'm/d/Y',
120
-                current_time('timestamp')
121
-            );
122
-        ob_start();
123
-        ?>
16
+	private $_status;
17
+
18
+
19
+	/**
20
+	 * @param \Transactions_Admin_Page $admin_page
21
+	 */
22
+	public function __construct(\Transactions_Admin_Page $admin_page)
23
+	{
24
+		parent::__construct($admin_page);
25
+		$this->_status = $this->_admin_page->get_transaction_status_array();
26
+	}
27
+
28
+
29
+	/**
30
+	 *_setup_data
31
+	 */
32
+	protected function _setup_data()
33
+	{
34
+		$this->_data           = $this->_admin_page->get_transactions($this->_per_page);
35
+		$status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
36
+		$this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
37
+	}
38
+
39
+
40
+	/**
41
+	 *_set_properties
42
+	 */
43
+	protected function _set_properties()
44
+	{
45
+		$this->_wp_list_args = array(
46
+			'singular' => __('transaction', 'event_espresso'),
47
+			'plural'   => __('transactions', 'event_espresso'),
48
+			'ajax'     => true,
49
+			'screen'   => $this->_admin_page->get_current_screen()->id,
50
+		);
51
+		$ID_column_name      = __('ID', 'event_espresso');
52
+		$ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53
+		$ID_column_name      .= __('Transaction Date', 'event_espresso');
54
+		$ID_column_name      .= '</span> ';
55
+		$this->_columns      = array(
56
+			'TXN_ID'        => $ID_column_name,
57
+			'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58
+			'TXN_total'     => __('Total', 'event_espresso'),
59
+			'TXN_paid'      => __('Paid', 'event_espresso'),
60
+			'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
61
+			'event_name'    => __('Event', 'event_espresso'),
62
+			'actions'       => __('Actions', 'event_espresso'),
63
+		);
64
+
65
+		$this->_sortable_columns = array(
66
+			'TXN_ID'        => array('TXN_ID' => false),
67
+			'event_name'    => array('event_name' => false),
68
+			'ATT_fname'     => array('ATT_fname' => false),
69
+			'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
70
+		);
71
+
72
+		$this->_primary_column = 'TXN_ID';
73
+
74
+		$this->_hidden_columns = array();
75
+	}
76
+
77
+
78
+	/**
79
+	 * This simply sets up the row class for the table rows.
80
+	 * Allows for easier overriding of child methods for setting up sorting.
81
+	 *
82
+	 * @param  EE_Transaction $transaction the current item
83
+	 * @return string
84
+	 * @throws \EE_Error
85
+	 */
86
+	protected function _get_row_class($transaction)
87
+	{
88
+		$class = parent::_get_row_class($transaction);
89
+		//add status class
90
+		$class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
91
+		if ($this->_has_checkbox_column) {
92
+			$class .= ' has-checkbox-column';
93
+		}
94
+		return $class;
95
+	}
96
+
97
+
98
+	/**
99
+	 * _get_table_filters
100
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
101
+	 * get's shown in the table.
102
+	 *
103
+	 * @abstract
104
+	 * @access protected
105
+	 * @return array
106
+	 */
107
+	protected function _get_table_filters()
108
+	{
109
+		$filters    = array();
110
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
111
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
112
+			: date(
113
+				'm/d/Y',
114
+				strtotime('-10 year')
115
+			);
116
+		$end_date   = isset($this->_req_data['txn-filter-end-date'])
117
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118
+			: date(
119
+				'm/d/Y',
120
+				current_time('timestamp')
121
+			);
122
+		ob_start();
123
+		?>
124 124
         <label for="txn-filter-start-date">Display Transactions from </label>
125 125
         <input id="txn-filter-start-date" class="datepicker" type="text" value="<?php echo $start_date; ?>"
126 126
                name="txn-filter-start-date" size="15"/>
@@ -128,534 +128,534 @@  discard block
 block discarded – undo
128 128
         <input id="txn-filter-end-date" class="datepicker" type="text" value="<?php echo $end_date; ?>"
129 129
                name="txn-filter-end-date" size="15"/>
130 130
         <?php
131
-        $filters[] = ob_get_contents();
132
-        ob_end_clean();
133
-        return $filters;
134
-    }
135
-
136
-
137
-    /**
138
-     *_add_view_counts
139
-     */
140
-    protected function _add_view_counts()
141
-    {
142
-        $this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
143
-        $this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
144
-        $this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
145
-    }
146
-
147
-
148
-    /**
149
-     *    column TXN_ID
150
-     *
151
-     * @param \EE_Transaction $transaction
152
-     * @return string
153
-     * @throws \EE_Error
154
-     */
155
-    public function column_TXN_ID(EE_Transaction $transaction)
156
-    {
157
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
158
-            'action' => 'view_transaction',
159
-            'TXN_ID' => $transaction->ID(),
160
-        ), TXN_ADMIN_URL);
161
-        $content      = '<a href="' . $view_lnk_url . '"'
162
-                        . ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
163
-                        . $transaction->ID()
164
-                        . '</a>';
165
-
166
-        //txn timestamp
167
-        $content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
168
-        return $content;
169
-    }
170
-
171
-
172
-    /**
173
-     * @param \EE_Transaction $transaction
174
-     * @return string
175
-     * @throws \EE_Error
176
-     */
177
-    protected function _get_txn_timestamp(EE_Transaction $transaction)
178
-    {
179
-        //txn timestamp
180
-        // is TXN less than 2 hours old ?
181
-        if (($transaction->failed() || $transaction->is_abandoned())
182
-            && (
183
-                (time() - EE_Registry::instance()->SSN->lifespan()) < $transaction->datetime(false, true)
184
-            )
185
-        ) {
186
-            $timestamp = esc_html__('TXN in progress...', 'event_espresso');
187
-        } else {
188
-            $timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
189
-        }
190
-        return $timestamp;
191
-    }
192
-
193
-
194
-    /**
195
-     *    column_cb
196
-     *
197
-     * @param \EE_Transaction $transaction
198
-     * @return string
199
-     * @throws \EE_Error
200
-     */
201
-    public function column_cb($transaction)
202
-    {
203
-        return sprintf(
204
-            '<input type="checkbox" name="%1$s[]" value="%2$s" />',
205
-            $this->_wp_list_args['singular'],
206
-            $transaction->ID()
207
-        );
208
-    }
209
-
210
-
211
-    /**
212
-     *    column_TXN_timestamp
213
-     *
214
-     * @param \EE_Transaction $transaction
215
-     * @return string
216
-     * @throws \EE_Error
217
-     */
218
-    public function column_TXN_timestamp(EE_Transaction $transaction)
219
-    {
220
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
221
-            'action' => 'view_transaction',
222
-            'TXN_ID' => $transaction->ID(),
223
-        ), TXN_ADMIN_URL);
224
-        $txn_date     = '<a href="' . $view_lnk_url . '"'
225
-                        . ' title="'
226
-                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
227
-                        . $this->_get_txn_timestamp($transaction)
228
-                        . '</a>';
229
-        //status
230
-        $txn_date .= '<br><span class="ee-status-text-small">'
231
-                     . EEH_Template::pretty_status(
232
-                         $transaction->status_ID(),
233
-                         false,
234
-                         'sentence'
235
-                     )
236
-                     . '</span>';
237
-        return $txn_date;
238
-    }
239
-
240
-
241
-    /**
242
-     *    column_TXN_total
243
-     *
244
-     * @param \EE_Transaction $transaction
245
-     * @return string
246
-     * @throws \EE_Error
247
-     */
248
-    public function column_TXN_total(EE_Transaction $transaction)
249
-    {
250
-        if ($transaction->get('TXN_total') > 0) {
251
-            return '<span class="txn-pad-rght">'
252
-                   . apply_filters(
253
-                       'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
254
-                       $transaction->get_pretty('TXN_total'),
255
-                       $transaction
256
-                   )
257
-                   . '</span>';
258
-        } else {
259
-            return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
260
-        }
261
-    }
262
-
263
-
264
-    /**
265
-     *    column_TXN_paid
266
-     *
267
-     * @param \EE_Transaction $transaction
268
-     * @return mixed|string
269
-     * @throws \EE_Error
270
-     */
271
-    public function column_TXN_paid(EE_Transaction $transaction)
272
-    {
273
-        $transaction_total = $transaction->get('TXN_total');
274
-        $transaction_paid  = $transaction->get('TXN_paid');
275
-
276
-        if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
277
-            // monies owing
278
-            $span_class = 'txn-overview-part-payment-spn';
279
-            if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
280
-                // paid in full
281
-                $span_class = 'txn-overview-full-payment-spn';
282
-            } elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
283
-                // no payments made
284
-                $span_class = 'txn-overview-no-payment-spn';
285
-            }
286
-        } else {
287
-            $span_class       = 'txn-overview-free-event-spn';
288
-            $transaction_paid = 0;
289
-        }
290
-
291
-        $payment_method      = $transaction->payment_method();
292
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
293
-            ? $payment_method->admin_name()
294
-            : esc_html__('Unknown', 'event_espresso');
295
-        $transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296
-
297
-        $content = '<span class="' . $span_class . ' txn-pad-rght">'
298
-                   . $transaction_paid_content
299
-                   . '</span>';
300
-        if ($transaction_paid > 0) {
301
-            $content .= '<br><span class="ee-status-text-small">'
302
-                        . sprintf(
303
-                            esc_html__('...via %s', 'event_espresso'),
304
-                            $payment_method_name
305
-                        )
306
-                        . '</span>';
307
-        }
308
-        return $content;
309
-    }
310
-
311
-
312
-    /**
313
-     *    column_ATT_fname
314
-     *
315
-     * @param \EE_Transaction $transaction
316
-     * @return string
317
-     * @throws \EE_Error
318
-     */
319
-    public function column_ATT_fname(EE_Transaction $transaction)
320
-    {
321
-        $primary_reg = $transaction->primary_registration();
322
-        $attendee    = $primary_reg->get_first_related('Attendee');
323
-        if ($attendee instanceof EE_Attendee) {
324
-            $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
325
-                'action'  => 'view_registration',
326
-                '_REG_ID' => $primary_reg->ID(),
327
-            ), REG_ADMIN_URL);
328
-            $content      = EE_Registry::instance()->CAP->current_user_can(
329
-                'ee_read_registration',
330
-                'espresso_registrations_view_registration',
331
-                $primary_reg->ID()
332
-            )
333
-                ? '<a href="' . $edit_lnk_url . '"'
334
-                    . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
335
-                    . $attendee->full_name()
336
-                    . '</a>'
337
-                : $attendee->full_name();
338
-            $content      .= '<br>' . $attendee->email();
339
-            return $content;
340
-        }
341
-        return $transaction->failed() || $transaction->is_abandoned()
342
-            ? esc_html__('no contact record.', 'event_espresso')
343
-            : esc_html__(
344
-                'No contact record, because the transaction was abandoned or the registration process failed.',
345
-                'event_espresso'
346
-            );
347
-    }
348
-
349
-
350
-    /**
351
-     *    column_ATT_email
352
-     *
353
-     * @param \EE_Transaction $transaction
354
-     * @return string
355
-     * @throws \EE_Error
356
-     */
357
-    public function column_ATT_email(EE_Transaction $transaction)
358
-    {
359
-        $attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
-        if (! empty($attendee)) {
361
-            return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
362
-                   . $attendee->get('ATT_email')
363
-                   . '</a>';
364
-        } else {
365
-            return $transaction->failed() || $transaction->is_abandoned()
366
-                ? esc_html__('no contact record.', 'event_espresso')
367
-                : esc_html__(
368
-                    'No contact record, because the transaction was abandoned or the registration process failed.',
369
-                    'event_espresso'
370
-                );
371
-        }
372
-    }
373
-
374
-
375
-    /**
376
-     *    column_event_name
377
-     *
378
-     * @param \EE_Transaction $transaction
379
-     * @return string
380
-     * @throws \EE_Error
381
-     */
382
-    public function column_event_name(EE_Transaction $transaction)
383
-    {
384
-        $actions = array();
385
-        $event   = $transaction->primary_registration()->get_first_related('Event');
386
-        if (! empty($event)) {
387
-            $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388
-                array('action' => 'edit', 'post' => $event->ID()),
389
-                EVENTS_ADMIN_URL
390
-            );
391
-            $event_name     = $event->get('EVT_name');
392
-
393
-            //filter this view by transactions for this event
394
-            $txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
395
-                'action' => 'default',
396
-                'EVT_ID' => $event->ID(),
397
-            ));
398
-            if (EE_Registry::instance()->CAP->current_user_can(
399
-                'ee_edit_event',
400
-                'espresso_events_edit',
401
-                $event->ID()
402
-            )) {
403
-                $actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
-                        . ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
405
-                        . esc_html__('View Transactions for this event', 'event_espresso')
406
-                        . '</a>';
407
-            }
408
-
409
-            return sprintf(
410
-                '%1$s %2$s',
411
-                EE_Registry::instance()->CAP->current_user_can(
412
-                    'ee_edit_event',
413
-                    'espresso_events_edit',
414
-                    $event->ID()
415
-                )
416
-                    ? '<a href="' . $edit_event_url . '"'
417
-                        . ' title="'
418
-                        . sprintf(
419
-                            esc_attr__('Edit Event: %s', 'event_espresso'),
420
-                            $event->get('EVT_name')
421
-                        )
422
-                        . '">'
423
-                        . wp_trim_words(
424
-                            $event_name,
425
-                            30,
426
-                            '...'
427
-                        )
428
-                        . '</a>'
429
-                        : wp_trim_words($event_name, 30, '...'),
430
-                $this->row_actions($actions)
431
-            );
432
-        } else {
433
-            return esc_html__(
434
-                'The event associated with this transaction via the primary registration cannot be retrieved.',
435
-                'event_espresso'
436
-            );
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     *    column_actions
443
-     *
444
-     * @param \EE_Transaction $transaction
445
-     * @return string
446
-     * @throws \EE_Error
447
-     */
448
-    public function column_actions(EE_Transaction $transaction)
449
-    {
450
-        return $this->_action_string(
451
-            $this->get_transaction_details_link($transaction)
452
-            . $this->get_invoice_link($transaction)
453
-            . $this->get_receipt_link($transaction)
454
-            . $this->get_primary_registration_details_link($transaction)
455
-            . $this->get_send_payment_reminder_trigger_link($transaction)
456
-            . $this->get_payment_overview_link($transaction)
457
-            . $this->get_related_messages_link($transaction),
458
-            $transaction,
459
-            'ul',
460
-            'txn-overview-actions-ul'
461
-        );
462
-    }
463
-
464
-
465
-    /**
466
-     * Get the transaction details link.
467
-     * @param EE_Transaction $transaction
468
-     * @return string
469
-     * @throws EE_Error
470
-     */
471
-    protected function get_transaction_details_link(EE_Transaction $transaction)
472
-    {
473
-        $url          = EE_Admin_Page::add_query_args_and_nonce(array(
474
-            'action' => 'view_transaction',
475
-            'TXN_ID' => $transaction->ID(),
476
-        ), TXN_ADMIN_URL);
477
-        return '
131
+		$filters[] = ob_get_contents();
132
+		ob_end_clean();
133
+		return $filters;
134
+	}
135
+
136
+
137
+	/**
138
+	 *_add_view_counts
139
+	 */
140
+	protected function _add_view_counts()
141
+	{
142
+		$this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
143
+		$this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
144
+		$this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
145
+	}
146
+
147
+
148
+	/**
149
+	 *    column TXN_ID
150
+	 *
151
+	 * @param \EE_Transaction $transaction
152
+	 * @return string
153
+	 * @throws \EE_Error
154
+	 */
155
+	public function column_TXN_ID(EE_Transaction $transaction)
156
+	{
157
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
158
+			'action' => 'view_transaction',
159
+			'TXN_ID' => $transaction->ID(),
160
+		), TXN_ADMIN_URL);
161
+		$content      = '<a href="' . $view_lnk_url . '"'
162
+						. ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
163
+						. $transaction->ID()
164
+						. '</a>';
165
+
166
+		//txn timestamp
167
+		$content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
168
+		return $content;
169
+	}
170
+
171
+
172
+	/**
173
+	 * @param \EE_Transaction $transaction
174
+	 * @return string
175
+	 * @throws \EE_Error
176
+	 */
177
+	protected function _get_txn_timestamp(EE_Transaction $transaction)
178
+	{
179
+		//txn timestamp
180
+		// is TXN less than 2 hours old ?
181
+		if (($transaction->failed() || $transaction->is_abandoned())
182
+			&& (
183
+				(time() - EE_Registry::instance()->SSN->lifespan()) < $transaction->datetime(false, true)
184
+			)
185
+		) {
186
+			$timestamp = esc_html__('TXN in progress...', 'event_espresso');
187
+		} else {
188
+			$timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
189
+		}
190
+		return $timestamp;
191
+	}
192
+
193
+
194
+	/**
195
+	 *    column_cb
196
+	 *
197
+	 * @param \EE_Transaction $transaction
198
+	 * @return string
199
+	 * @throws \EE_Error
200
+	 */
201
+	public function column_cb($transaction)
202
+	{
203
+		return sprintf(
204
+			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
205
+			$this->_wp_list_args['singular'],
206
+			$transaction->ID()
207
+		);
208
+	}
209
+
210
+
211
+	/**
212
+	 *    column_TXN_timestamp
213
+	 *
214
+	 * @param \EE_Transaction $transaction
215
+	 * @return string
216
+	 * @throws \EE_Error
217
+	 */
218
+	public function column_TXN_timestamp(EE_Transaction $transaction)
219
+	{
220
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
221
+			'action' => 'view_transaction',
222
+			'TXN_ID' => $transaction->ID(),
223
+		), TXN_ADMIN_URL);
224
+		$txn_date     = '<a href="' . $view_lnk_url . '"'
225
+						. ' title="'
226
+						. esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
227
+						. $this->_get_txn_timestamp($transaction)
228
+						. '</a>';
229
+		//status
230
+		$txn_date .= '<br><span class="ee-status-text-small">'
231
+					 . EEH_Template::pretty_status(
232
+						 $transaction->status_ID(),
233
+						 false,
234
+						 'sentence'
235
+					 )
236
+					 . '</span>';
237
+		return $txn_date;
238
+	}
239
+
240
+
241
+	/**
242
+	 *    column_TXN_total
243
+	 *
244
+	 * @param \EE_Transaction $transaction
245
+	 * @return string
246
+	 * @throws \EE_Error
247
+	 */
248
+	public function column_TXN_total(EE_Transaction $transaction)
249
+	{
250
+		if ($transaction->get('TXN_total') > 0) {
251
+			return '<span class="txn-pad-rght">'
252
+				   . apply_filters(
253
+					   'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
254
+					   $transaction->get_pretty('TXN_total'),
255
+					   $transaction
256
+				   )
257
+				   . '</span>';
258
+		} else {
259
+			return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
260
+		}
261
+	}
262
+
263
+
264
+	/**
265
+	 *    column_TXN_paid
266
+	 *
267
+	 * @param \EE_Transaction $transaction
268
+	 * @return mixed|string
269
+	 * @throws \EE_Error
270
+	 */
271
+	public function column_TXN_paid(EE_Transaction $transaction)
272
+	{
273
+		$transaction_total = $transaction->get('TXN_total');
274
+		$transaction_paid  = $transaction->get('TXN_paid');
275
+
276
+		if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
277
+			// monies owing
278
+			$span_class = 'txn-overview-part-payment-spn';
279
+			if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
280
+				// paid in full
281
+				$span_class = 'txn-overview-full-payment-spn';
282
+			} elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
283
+				// no payments made
284
+				$span_class = 'txn-overview-no-payment-spn';
285
+			}
286
+		} else {
287
+			$span_class       = 'txn-overview-free-event-spn';
288
+			$transaction_paid = 0;
289
+		}
290
+
291
+		$payment_method      = $transaction->payment_method();
292
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
293
+			? $payment_method->admin_name()
294
+			: esc_html__('Unknown', 'event_espresso');
295
+		$transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296
+
297
+		$content = '<span class="' . $span_class . ' txn-pad-rght">'
298
+				   . $transaction_paid_content
299
+				   . '</span>';
300
+		if ($transaction_paid > 0) {
301
+			$content .= '<br><span class="ee-status-text-small">'
302
+						. sprintf(
303
+							esc_html__('...via %s', 'event_espresso'),
304
+							$payment_method_name
305
+						)
306
+						. '</span>';
307
+		}
308
+		return $content;
309
+	}
310
+
311
+
312
+	/**
313
+	 *    column_ATT_fname
314
+	 *
315
+	 * @param \EE_Transaction $transaction
316
+	 * @return string
317
+	 * @throws \EE_Error
318
+	 */
319
+	public function column_ATT_fname(EE_Transaction $transaction)
320
+	{
321
+		$primary_reg = $transaction->primary_registration();
322
+		$attendee    = $primary_reg->get_first_related('Attendee');
323
+		if ($attendee instanceof EE_Attendee) {
324
+			$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
325
+				'action'  => 'view_registration',
326
+				'_REG_ID' => $primary_reg->ID(),
327
+			), REG_ADMIN_URL);
328
+			$content      = EE_Registry::instance()->CAP->current_user_can(
329
+				'ee_read_registration',
330
+				'espresso_registrations_view_registration',
331
+				$primary_reg->ID()
332
+			)
333
+				? '<a href="' . $edit_lnk_url . '"'
334
+					. ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
335
+					. $attendee->full_name()
336
+					. '</a>'
337
+				: $attendee->full_name();
338
+			$content      .= '<br>' . $attendee->email();
339
+			return $content;
340
+		}
341
+		return $transaction->failed() || $transaction->is_abandoned()
342
+			? esc_html__('no contact record.', 'event_espresso')
343
+			: esc_html__(
344
+				'No contact record, because the transaction was abandoned or the registration process failed.',
345
+				'event_espresso'
346
+			);
347
+	}
348
+
349
+
350
+	/**
351
+	 *    column_ATT_email
352
+	 *
353
+	 * @param \EE_Transaction $transaction
354
+	 * @return string
355
+	 * @throws \EE_Error
356
+	 */
357
+	public function column_ATT_email(EE_Transaction $transaction)
358
+	{
359
+		$attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
+		if (! empty($attendee)) {
361
+			return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
362
+				   . $attendee->get('ATT_email')
363
+				   . '</a>';
364
+		} else {
365
+			return $transaction->failed() || $transaction->is_abandoned()
366
+				? esc_html__('no contact record.', 'event_espresso')
367
+				: esc_html__(
368
+					'No contact record, because the transaction was abandoned or the registration process failed.',
369
+					'event_espresso'
370
+				);
371
+		}
372
+	}
373
+
374
+
375
+	/**
376
+	 *    column_event_name
377
+	 *
378
+	 * @param \EE_Transaction $transaction
379
+	 * @return string
380
+	 * @throws \EE_Error
381
+	 */
382
+	public function column_event_name(EE_Transaction $transaction)
383
+	{
384
+		$actions = array();
385
+		$event   = $transaction->primary_registration()->get_first_related('Event');
386
+		if (! empty($event)) {
387
+			$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388
+				array('action' => 'edit', 'post' => $event->ID()),
389
+				EVENTS_ADMIN_URL
390
+			);
391
+			$event_name     = $event->get('EVT_name');
392
+
393
+			//filter this view by transactions for this event
394
+			$txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
395
+				'action' => 'default',
396
+				'EVT_ID' => $event->ID(),
397
+			));
398
+			if (EE_Registry::instance()->CAP->current_user_can(
399
+				'ee_edit_event',
400
+				'espresso_events_edit',
401
+				$event->ID()
402
+			)) {
403
+				$actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
+						. ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
405
+						. esc_html__('View Transactions for this event', 'event_espresso')
406
+						. '</a>';
407
+			}
408
+
409
+			return sprintf(
410
+				'%1$s %2$s',
411
+				EE_Registry::instance()->CAP->current_user_can(
412
+					'ee_edit_event',
413
+					'espresso_events_edit',
414
+					$event->ID()
415
+				)
416
+					? '<a href="' . $edit_event_url . '"'
417
+						. ' title="'
418
+						. sprintf(
419
+							esc_attr__('Edit Event: %s', 'event_espresso'),
420
+							$event->get('EVT_name')
421
+						)
422
+						. '">'
423
+						. wp_trim_words(
424
+							$event_name,
425
+							30,
426
+							'...'
427
+						)
428
+						. '</a>'
429
+						: wp_trim_words($event_name, 30, '...'),
430
+				$this->row_actions($actions)
431
+			);
432
+		} else {
433
+			return esc_html__(
434
+				'The event associated with this transaction via the primary registration cannot be retrieved.',
435
+				'event_espresso'
436
+			);
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 *    column_actions
443
+	 *
444
+	 * @param \EE_Transaction $transaction
445
+	 * @return string
446
+	 * @throws \EE_Error
447
+	 */
448
+	public function column_actions(EE_Transaction $transaction)
449
+	{
450
+		return $this->_action_string(
451
+			$this->get_transaction_details_link($transaction)
452
+			. $this->get_invoice_link($transaction)
453
+			. $this->get_receipt_link($transaction)
454
+			. $this->get_primary_registration_details_link($transaction)
455
+			. $this->get_send_payment_reminder_trigger_link($transaction)
456
+			. $this->get_payment_overview_link($transaction)
457
+			. $this->get_related_messages_link($transaction),
458
+			$transaction,
459
+			'ul',
460
+			'txn-overview-actions-ul'
461
+		);
462
+	}
463
+
464
+
465
+	/**
466
+	 * Get the transaction details link.
467
+	 * @param EE_Transaction $transaction
468
+	 * @return string
469
+	 * @throws EE_Error
470
+	 */
471
+	protected function get_transaction_details_link(EE_Transaction $transaction)
472
+	{
473
+		$url          = EE_Admin_Page::add_query_args_and_nonce(array(
474
+			'action' => 'view_transaction',
475
+			'TXN_ID' => $transaction->ID(),
476
+		), TXN_ADMIN_URL);
477
+		return '
478 478
 			<li>
479 479
 				<a href="' . $url . '"'
480
-                    . ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
480
+					. ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
481 481
 					<span class="dashicons dashicons-cart"></span>
482 482
 				</a>
483 483
 			</li>';
484
-    }
485
-
486
-
487
-    /**
488
-     * Get the invoice link for the given registration.
489
-     * @param EE_Transaction $transaction
490
-     * @return string
491
-     * @throws EE_Error
492
-     */
493
-    protected function get_invoice_link(EE_Transaction $transaction)
494
-    {
495
-        $registration = $transaction->primary_registration();
496
-        if ($registration instanceof EE_Registration) {
497
-            $url = $registration->invoice_url();
498
-            //only show invoice link if message type is active.
499
-            if ($registration->attendee() instanceof EE_Attendee
500
-                && EEH_MSG_Template::is_mt_active('invoice')
501
-            ) {
502
-                return '
484
+	}
485
+
486
+
487
+	/**
488
+	 * Get the invoice link for the given registration.
489
+	 * @param EE_Transaction $transaction
490
+	 * @return string
491
+	 * @throws EE_Error
492
+	 */
493
+	protected function get_invoice_link(EE_Transaction $transaction)
494
+	{
495
+		$registration = $transaction->primary_registration();
496
+		if ($registration instanceof EE_Registration) {
497
+			$url = $registration->invoice_url();
498
+			//only show invoice link if message type is active.
499
+			if ($registration->attendee() instanceof EE_Attendee
500
+				&& EEH_MSG_Template::is_mt_active('invoice')
501
+			) {
502
+				return '
503 503
                 <li>
504 504
                     <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso') . '"'
505
-                       . ' target="_blank" href="' . $url . '" class="tiny-text">
505
+					   . ' target="_blank" href="' . $url . '" class="tiny-text">
506 506
                         <span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
507 507
                     </a>
508 508
                 </li>';
509
-            }
510
-        }
511
-        return '';
512
-    }
513
-
514
-
515
-    /**
516
-     * Get the receipt link for the transaction.
517
-     * @param EE_Transaction $transaction
518
-     * @return string
519
-     * @throws EE_Error
520
-     */
521
-    protected function get_receipt_link(EE_Transaction $transaction)
522
-    {
523
-        $registration = $transaction->primary_registration();
524
-        if ($registration instanceof EE_Registration) {
525
-            $url = $registration->receipt_url();
526
-            //only show receipt link if message type is active.
527
-            if ($registration->attendee() instanceof EE_Attendee
528
-                && EEH_MSG_Template::is_mt_active('receipt')) {
529
-                return '
509
+			}
510
+		}
511
+		return '';
512
+	}
513
+
514
+
515
+	/**
516
+	 * Get the receipt link for the transaction.
517
+	 * @param EE_Transaction $transaction
518
+	 * @return string
519
+	 * @throws EE_Error
520
+	 */
521
+	protected function get_receipt_link(EE_Transaction $transaction)
522
+	{
523
+		$registration = $transaction->primary_registration();
524
+		if ($registration instanceof EE_Registration) {
525
+			$url = $registration->receipt_url();
526
+			//only show receipt link if message type is active.
527
+			if ($registration->attendee() instanceof EE_Attendee
528
+				&& EEH_MSG_Template::is_mt_active('receipt')) {
529
+				return '
530 530
 			<li>
531 531
 				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso') . '"'
532
-                                  . ' target="_blank" href="' . $url . '" class="tiny-text">
532
+								  . ' target="_blank" href="' . $url . '" class="tiny-text">
533 533
 					<span class="dashicons dashicons-media-default ee-icon-size-18"></span>
534 534
 				</a>
535 535
 			</li>';
536
-            }
537
-        }
538
-        return '';
539
-    }
540
-
541
-
542
-    /**
543
-     * Get the link to view the details for the primary registration.
544
-     * @param EE_Transaction $transaction
545
-     * @return string
546
-     * @throws EE_Error
547
-     */
548
-    protected function get_primary_registration_details_link(EE_Transaction $transaction)
549
-    {
550
-        $registration = $transaction->primary_registration();
551
-        if ($registration instanceof EE_Registration) {
552
-            $url      = EE_Admin_Page::add_query_args_and_nonce(array(
553
-                'action'  => 'view_registration',
554
-                '_REG_ID' => $registration->ID(),
555
-            ), REG_ADMIN_URL);
556
-            return EE_Registry::instance()->CAP->current_user_can(
557
-                'ee_read_registration',
558
-                'espresso_registrations_view_registration',
559
-                $registration->ID()
560
-            )
561
-                ? '
536
+			}
537
+		}
538
+		return '';
539
+	}
540
+
541
+
542
+	/**
543
+	 * Get the link to view the details for the primary registration.
544
+	 * @param EE_Transaction $transaction
545
+	 * @return string
546
+	 * @throws EE_Error
547
+	 */
548
+	protected function get_primary_registration_details_link(EE_Transaction $transaction)
549
+	{
550
+		$registration = $transaction->primary_registration();
551
+		if ($registration instanceof EE_Registration) {
552
+			$url      = EE_Admin_Page::add_query_args_and_nonce(array(
553
+				'action'  => 'view_registration',
554
+				'_REG_ID' => $registration->ID(),
555
+			), REG_ADMIN_URL);
556
+			return EE_Registry::instance()->CAP->current_user_can(
557
+				'ee_read_registration',
558
+				'espresso_registrations_view_registration',
559
+				$registration->ID()
560
+			)
561
+				? '
562 562
 				<li>
563 563
 					<a href="' . $url . '"'
564
-                  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
564
+				  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
565 565
 						<span class="dashicons dashicons-clipboard"></span>
566 566
 					</a>
567 567
 				</li>'
568
-                : '';
569
-        }
570
-        return '';
571
-    }
572
-
573
-
574
-    /**
575
-     * Get send payment reminder trigger link
576
-     * @param EE_Transaction $transaction
577
-     * @return string
578
-     * @throws EE_Error
579
-     */
580
-    protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
581
-    {
582
-        $registration = $transaction->primary_registration();
583
-        if ($registration instanceof EE_Registration
584
-            && $registration->attendee() instanceof EE_Attendee
585
-            && EEH_MSG_Template::is_mt_active('payment_reminder')
586
-            && ! in_array(
587
-                $transaction->status_ID(),
588
-                array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
589
-                true
590
-            )
591
-            && EE_Registry::instance()->CAP->current_user_can(
592
-                'ee_send_message',
593
-                'espresso_transactions_send_payment_reminder'
594
-            )
595
-        ) {
596
-            $url = EE_Admin_Page::add_query_args_and_nonce(array(
597
-                'action' => 'send_payment_reminder',
598
-                'TXN_ID' => $transaction->ID(),
599
-            ), TXN_ADMIN_URL);
600
-            return  '
568
+				: '';
569
+		}
570
+		return '';
571
+	}
572
+
573
+
574
+	/**
575
+	 * Get send payment reminder trigger link
576
+	 * @param EE_Transaction $transaction
577
+	 * @return string
578
+	 * @throws EE_Error
579
+	 */
580
+	protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
581
+	{
582
+		$registration = $transaction->primary_registration();
583
+		if ($registration instanceof EE_Registration
584
+			&& $registration->attendee() instanceof EE_Attendee
585
+			&& EEH_MSG_Template::is_mt_active('payment_reminder')
586
+			&& ! in_array(
587
+				$transaction->status_ID(),
588
+				array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
589
+				true
590
+			)
591
+			&& EE_Registry::instance()->CAP->current_user_can(
592
+				'ee_send_message',
593
+				'espresso_transactions_send_payment_reminder'
594
+			)
595
+		) {
596
+			$url = EE_Admin_Page::add_query_args_and_nonce(array(
597
+				'action' => 'send_payment_reminder',
598
+				'TXN_ID' => $transaction->ID(),
599
+			), TXN_ADMIN_URL);
600
+			return  '
601 601
             <li>
602 602
                 <a href="' . $url . '"'
603
-                  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
603
+				  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
604 604
                     <span class="dashicons dashicons-email-alt"></span>
605 605
                 </a>
606 606
             </li>';
607
-        }
608
-        return '';
609
-    }
610
-
611
-
612
-
613
-    /**
614
-     * Get link to filtered view in the message activity list table of messages for this transaction.
615
-     * @param EE_Transaction $transaction
616
-     * @return string
617
-     * @throws EE_Error
618
-     */
619
-    protected function get_related_messages_link(EE_Transaction $transaction)
620
-    {
621
-        $url = EEH_MSG_Template::get_message_action_link(
622
-            'see_notifications_for',
623
-            null,
624
-            array('TXN_ID' => $transaction->ID())
625
-        );
626
-        return EE_Registry::instance()->CAP->current_user_can(
627
-            'ee_read_global_messages',
628
-            'view_filtered_messages'
629
-        )
630
-            ? '<li>' . $url . '</li>'
631
-            : '';
632
-    }
633
-
634
-
635
-    /**
636
-     * Return the link to make a payment on the frontend
637
-     * @param EE_Transaction $transaction
638
-     * @return string
639
-     * @throws EE_Error
640
-     */
641
-    protected function get_payment_overview_link(EE_Transaction $transaction)
642
-    {
643
-        $registration = $transaction->primary_registration();
644
-        if ($registration instanceof EE_Registration
645
-            && $transaction->status_ID() !== EEM_Transaction::complete_status_code
646
-            && $registration->owes_monies_and_can_pay()
647
-        ) {
648
-            return '
607
+		}
608
+		return '';
609
+	}
610
+
611
+
612
+
613
+	/**
614
+	 * Get link to filtered view in the message activity list table of messages for this transaction.
615
+	 * @param EE_Transaction $transaction
616
+	 * @return string
617
+	 * @throws EE_Error
618
+	 */
619
+	protected function get_related_messages_link(EE_Transaction $transaction)
620
+	{
621
+		$url = EEH_MSG_Template::get_message_action_link(
622
+			'see_notifications_for',
623
+			null,
624
+			array('TXN_ID' => $transaction->ID())
625
+		);
626
+		return EE_Registry::instance()->CAP->current_user_can(
627
+			'ee_read_global_messages',
628
+			'view_filtered_messages'
629
+		)
630
+			? '<li>' . $url . '</li>'
631
+			: '';
632
+	}
633
+
634
+
635
+	/**
636
+	 * Return the link to make a payment on the frontend
637
+	 * @param EE_Transaction $transaction
638
+	 * @return string
639
+	 * @throws EE_Error
640
+	 */
641
+	protected function get_payment_overview_link(EE_Transaction $transaction)
642
+	{
643
+		$registration = $transaction->primary_registration();
644
+		if ($registration instanceof EE_Registration
645
+			&& $transaction->status_ID() !== EEM_Transaction::complete_status_code
646
+			&& $registration->owes_monies_and_can_pay()
647
+		) {
648
+			return '
649 649
             <li>
650 650
                 <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso') . '"'
651
-                    . ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
652
-                    . ' class="tiny-text">
651
+					. ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
652
+					. ' class="tiny-text">
653 653
                     <span class="dashicons dashicons-money ee-icon-size-18"></span>
654 654
                 </a>
655 655
             </li>
656 656
             ';
657 657
 
658
-        }
659
-        return '';
660
-    }
658
+		}
659
+		return '';
660
+	}
661 661
 }
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -48,11 +48,11 @@  discard block
 block discarded – undo
48 48
             'ajax'     => true,
49 49
             'screen'   => $this->_admin_page->get_current_screen()->id,
50 50
         );
51
-        $ID_column_name      = __('ID', 'event_espresso');
51
+        $ID_column_name = __('ID', 'event_espresso');
52 52
         $ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
53 53
         $ID_column_name      .= __('Transaction Date', 'event_espresso');
54 54
         $ID_column_name      .= '</span> ';
55
-        $this->_columns      = array(
55
+        $this->_columns = array(
56 56
             'TXN_ID'        => $ID_column_name,
57 57
             'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
58 58
             'TXN_total'     => __('Total', 'event_espresso'),
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
     {
88 88
         $class = parent::_get_row_class($transaction);
89 89
         //add status class
90
-        $class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
90
+        $class .= ' ee-status-strip txn-status-'.$transaction->status_ID();
91 91
         if ($this->_has_checkbox_column) {
92 92
             $class .= ' has-checkbox-column';
93 93
         }
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
                 'm/d/Y',
114 114
                 strtotime('-10 year')
115 115
             );
116
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
116
+        $end_date = isset($this->_req_data['txn-filter-end-date'])
117 117
             ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
118 118
             : date(
119 119
                 'm/d/Y',
@@ -158,13 +158,13 @@  discard block
 block discarded – undo
158 158
             'action' => 'view_transaction',
159 159
             'TXN_ID' => $transaction->ID(),
160 160
         ), TXN_ADMIN_URL);
161
-        $content      = '<a href="' . $view_lnk_url . '"'
162
-                        . ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
161
+        $content = '<a href="'.$view_lnk_url.'"'
162
+                        . ' title="'.esc_attr__('Go to Transaction Details', 'event_espresso').'">'
163 163
                         . $transaction->ID()
164 164
                         . '</a>';
165 165
 
166 166
         //txn timestamp
167
-        $content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
167
+        $content .= '  <span class="show-on-mobile-view-only">'.$this->_get_txn_timestamp($transaction).'</span>';
168 168
         return $content;
169 169
     }
170 170
 
@@ -221,9 +221,9 @@  discard block
 block discarded – undo
221 221
             'action' => 'view_transaction',
222 222
             'TXN_ID' => $transaction->ID(),
223 223
         ), TXN_ADMIN_URL);
224
-        $txn_date     = '<a href="' . $view_lnk_url . '"'
224
+        $txn_date = '<a href="'.$view_lnk_url.'"'
225 225
                         . ' title="'
226
-                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
226
+                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso').$transaction->ID().'">'
227 227
                         . $this->_get_txn_timestamp($transaction)
228 228
                         . '</a>';
229 229
         //status
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
                    )
257 257
                    . '</span>';
258 258
         } else {
259
-            return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
259
+            return '<span class="txn-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
260 260
         }
261 261
     }
262 262
 
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
             : esc_html__('Unknown', 'event_espresso');
295 295
         $transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
296 296
 
297
-        $content = '<span class="' . $span_class . ' txn-pad-rght">'
297
+        $content = '<span class="'.$span_class.' txn-pad-rght">'
298 298
                    . $transaction_paid_content
299 299
                    . '</span>';
300 300
         if ($transaction_paid > 0) {
@@ -325,17 +325,17 @@  discard block
 block discarded – undo
325 325
                 'action'  => 'view_registration',
326 326
                 '_REG_ID' => $primary_reg->ID(),
327 327
             ), REG_ADMIN_URL);
328
-            $content      = EE_Registry::instance()->CAP->current_user_can(
328
+            $content = EE_Registry::instance()->CAP->current_user_can(
329 329
                 'ee_read_registration',
330 330
                 'espresso_registrations_view_registration',
331 331
                 $primary_reg->ID()
332 332
             )
333
-                ? '<a href="' . $edit_lnk_url . '"'
334
-                    . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
333
+                ? '<a href="'.$edit_lnk_url.'"'
334
+                    . ' title="'.esc_attr__('View Registration Details', 'event_espresso').'">'
335 335
                     . $attendee->full_name()
336 336
                     . '</a>'
337 337
                 : $attendee->full_name();
338
-            $content      .= '<br>' . $attendee->email();
338
+            $content .= '<br>'.$attendee->email();
339 339
             return $content;
340 340
         }
341 341
         return $transaction->failed() || $transaction->is_abandoned()
@@ -357,8 +357,8 @@  discard block
 block discarded – undo
357 357
     public function column_ATT_email(EE_Transaction $transaction)
358 358
     {
359 359
         $attendee = $transaction->primary_registration()->get_first_related('Attendee');
360
-        if (! empty($attendee)) {
361
-            return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
360
+        if ( ! empty($attendee)) {
361
+            return '<a href="mailto:'.$attendee->get('ATT_email').'">'
362 362
                    . $attendee->get('ATT_email')
363 363
                    . '</a>';
364 364
         } else {
@@ -383,12 +383,12 @@  discard block
 block discarded – undo
383 383
     {
384 384
         $actions = array();
385 385
         $event   = $transaction->primary_registration()->get_first_related('Event');
386
-        if (! empty($event)) {
386
+        if ( ! empty($event)) {
387 387
             $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
388 388
                 array('action' => 'edit', 'post' => $event->ID()),
389 389
                 EVENTS_ADMIN_URL
390 390
             );
391
-            $event_name     = $event->get('EVT_name');
391
+            $event_name = $event->get('EVT_name');
392 392
 
393 393
             //filter this view by transactions for this event
394 394
             $txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
@@ -400,8 +400,8 @@  discard block
 block discarded – undo
400 400
                 'espresso_events_edit',
401 401
                 $event->ID()
402 402
             )) {
403
-                $actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
404
-                        . ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
403
+                $actions['filter_by_event'] = '<a href="'.$txn_by_event_lnk.'"'
404
+                        . ' title="'.esc_attr__('Filter transactions by this event', 'event_espresso').'">'
405 405
                         . esc_html__('View Transactions for this event', 'event_espresso')
406 406
                         . '</a>';
407 407
             }
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
                     'espresso_events_edit',
414 414
                     $event->ID()
415 415
                 )
416
-                    ? '<a href="' . $edit_event_url . '"'
416
+                    ? '<a href="'.$edit_event_url.'"'
417 417
                         . ' title="'
418 418
                         . sprintf(
419 419
                             esc_attr__('Edit Event: %s', 'event_espresso'),
@@ -470,14 +470,14 @@  discard block
 block discarded – undo
470 470
      */
471 471
     protected function get_transaction_details_link(EE_Transaction $transaction)
472 472
     {
473
-        $url          = EE_Admin_Page::add_query_args_and_nonce(array(
473
+        $url = EE_Admin_Page::add_query_args_and_nonce(array(
474 474
             'action' => 'view_transaction',
475 475
             'TXN_ID' => $transaction->ID(),
476 476
         ), TXN_ADMIN_URL);
477 477
         return '
478 478
 			<li>
479
-				<a href="' . $url . '"'
480
-                    . ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
479
+				<a href="' . $url.'"'
480
+                    . ' title="'.esc_attr__('View Transaction Details', 'event_espresso').'" class="tiny-text">
481 481
 					<span class="dashicons dashicons-cart"></span>
482 482
 				</a>
483 483
 			</li>';
@@ -501,8 +501,8 @@  discard block
 block discarded – undo
501 501
             ) {
502 502
                 return '
503 503
                 <li>
504
-                    <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso') . '"'
505
-                       . ' target="_blank" href="' . $url . '" class="tiny-text">
504
+                    <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso').'"'
505
+                       . ' target="_blank" href="'.$url.'" class="tiny-text">
506 506
                         <span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
507 507
                     </a>
508 508
                 </li>';
@@ -528,8 +528,8 @@  discard block
 block discarded – undo
528 528
                 && EEH_MSG_Template::is_mt_active('receipt')) {
529 529
                 return '
530 530
 			<li>
531
-				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso') . '"'
532
-                                  . ' target="_blank" href="' . $url . '" class="tiny-text">
531
+				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso').'"'
532
+                                  . ' target="_blank" href="'.$url.'" class="tiny-text">
533 533
 					<span class="dashicons dashicons-media-default ee-icon-size-18"></span>
534 534
 				</a>
535 535
 			</li>';
@@ -560,8 +560,8 @@  discard block
 block discarded – undo
560 560
             )
561 561
                 ? '
562 562
 				<li>
563
-					<a href="' . $url . '"'
564
-                  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
563
+					<a href="' . $url.'"'
564
+                  . ' title="'.esc_attr__('View Registration Details', 'event_espresso').'" class="tiny-text">
565 565
 						<span class="dashicons dashicons-clipboard"></span>
566 566
 					</a>
567 567
 				</li>'
@@ -599,8 +599,8 @@  discard block
 block discarded – undo
599 599
             ), TXN_ADMIN_URL);
600 600
             return  '
601 601
             <li>
602
-                <a href="' . $url . '"'
603
-                  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
602
+                <a href="' . $url.'"'
603
+                  . ' title="'.esc_attr__('Send Payment Reminder', 'event_espresso').'" class="tiny-text">
604 604
                     <span class="dashicons dashicons-email-alt"></span>
605 605
                 </a>
606 606
             </li>';
@@ -627,7 +627,7 @@  discard block
 block discarded – undo
627 627
             'ee_read_global_messages',
628 628
             'view_filtered_messages'
629 629
         )
630
-            ? '<li>' . $url . '</li>'
630
+            ? '<li>'.$url.'</li>'
631 631
             : '';
632 632
     }
633 633
 
@@ -647,8 +647,8 @@  discard block
 block discarded – undo
647 647
         ) {
648 648
             return '
649 649
             <li>
650
-                <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso') . '"'
651
-                    . ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
650
+                <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso').'"'
651
+                    . ' target="_blank" href="'.$registration->payment_overview_url(true).'"'
652 652
                     . ' class="tiny-text">
653 653
                     <span class="dashicons dashicons-money ee-icon-size-18"></span>
654 654
                 </a>
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 3 patches
Doc Comments   +4 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1159,7 +1159,7 @@  discard block
 block discarded – undo
1159 1159
      * Sets deleted
1160 1160
      *
1161 1161
      * @param boolean $deleted
1162
-     * @return bool
1162
+     * @return boolean|null
1163 1163
      * @throws EE_Error
1164 1164
      * @throws RuntimeException
1165 1165
      */
@@ -1217,6 +1217,7 @@  discard block
 block discarded – undo
1217 1217
      * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1218 1218
      * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1219 1219
      *                                          consider registration status as well as datetime access.
1220
+     * @param integer $DTT_OR_ID
1220 1221
      * @return bool
1221 1222
      * @throws EE_Error
1222 1223
      */
@@ -1387,7 +1388,7 @@  discard block
 block discarded – undo
1387 1388
      * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1388 1389
      * "Latest" is defined by the `DTT_EVT_start` column.
1389 1390
      *
1390
-     * @return EE_Datetime|null
1391
+     * @return null|EE_Base_Class
1391 1392
      * @throws \EE_Error
1392 1393
      */
1393 1394
     public function get_latest_related_datetime()
@@ -1680,7 +1681,7 @@  discard block
 block discarded – undo
1680 1681
      * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1681 1682
      * Note: if there are no payments on the registration there will be no payment method returned.
1682 1683
      *
1683
-     * @return EE_Payment_Method|null
1684
+     * @return null|EE_Base_Class
1684 1685
      */
1685 1686
     public function payment_method()
1686 1687
     {
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
     {
110 110
         switch ($field_name) {
111 111
             case 'REG_code':
112
-                if (! empty($field_value) && $this->reg_code() === null) {
112
+                if ( ! empty($field_value) && $this->reg_code() === null) {
113 113
                     $this->set_reg_code($field_value, $use_default);
114 114
                 }
115 115
                 break;
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
     public function event()
285 285
     {
286 286
         $event = $this->get_first_related('Event');
287
-        if (! $event instanceof \EE_Event) {
287
+        if ( ! $event instanceof \EE_Event) {
288 288
             throw new EntityNotFoundException('Event ID', $this->event_ID());
289 289
         }
290 290
         return $event;
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             false,
974 974
             'sentence'
975 975
         );
976
-        $icon   = '';
976
+        $icon = '';
977 977
         switch ($this->status_ID()) {
978 978
             case EEM_Registration::status_id_approved:
979 979
                 $icon = $show_icons
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
                     : '';
1012 1012
                 break;
1013 1013
         }
1014
-        return $icon . $status[$this->status_ID()];
1014
+        return $icon.$status[$this->status_ID()];
1015 1015
     }
1016 1016
 
1017 1017
 
@@ -1229,7 +1229,7 @@  discard block
 block discarded – undo
1229 1229
             return false;
1230 1230
         }
1231 1231
         //is there a datetime ticket that matches this dtt_ID?
1232
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(array(
1233 1233
             array(
1234 1234
                 'TKT_ID' => $this->get('TKT_ID'),
1235 1235
                 'DTT_ID' => $DTT_ID,
@@ -1258,7 +1258,7 @@  discard block
 block discarded – undo
1258 1258
     {
1259 1259
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1260 1260
 
1261
-        if (! $DTT_ID) {
1261
+        if ( ! $DTT_ID) {
1262 1262
             return false;
1263 1263
         }
1264 1264
 
@@ -1266,7 +1266,7 @@  discard block
 block discarded – undo
1266 1266
 
1267 1267
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1268 1268
         // check-in or not.
1269
-        if (! $max_uses || $max_uses === EE_INF) {
1269
+        if ( ! $max_uses || $max_uses === EE_INF) {
1270 1270
             return true;
1271 1271
         }
1272 1272
 
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
             $datetime = $this->get_latest_related_datetime();
1323 1323
             $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1324 1324
             // verify the registration can checkin for the given DTT_ID
1325
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1326 1326
             EE_Error::add_error(
1327 1327
                 sprintf(
1328 1328
                     esc_html__(
@@ -1505,7 +1505,7 @@  discard block
 block discarded – undo
1505 1505
     public function transaction()
1506 1506
     {
1507 1507
         $transaction = $this->get_first_related('Transaction');
1508
-        if (! $transaction instanceof \EE_Transaction) {
1508
+        if ( ! $transaction instanceof \EE_Transaction) {
1509 1509
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1510 1510
         }
1511 1511
         return $transaction;
@@ -1559,11 +1559,11 @@  discard block
 block discarded – undo
1559 1559
             );
1560 1560
             return;
1561 1561
         }
1562
-        if (! $this->reg_code()) {
1562
+        if ( ! $this->reg_code()) {
1563 1563
             parent::set('REG_code', $REG_code, $use_default);
1564 1564
         } else {
1565 1565
             EE_Error::doing_it_wrong(
1566
-                __CLASS__ . '::' . __FUNCTION__,
1566
+                __CLASS__.'::'.__FUNCTION__,
1567 1567
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1568 1568
                 '4.6.0'
1569 1569
             );
@@ -1713,7 +1713,7 @@  discard block
 block discarded – undo
1713 1713
                 break;
1714 1714
             }
1715 1715
         }
1716
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1717 1717
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1718 1718
         }
1719 1719
         return $line_item;
Please login to merge, or discard this patch.
Indentation   +1812 added lines, -1812 removed lines patch added patch discarded remove patch
@@ -15,1818 +15,1818 @@
 block discarded – undo
15 15
 {
16 16
 
17 17
 
18
-    /**
19
-     * Used to reference when a registration has never been checked in.
20
-     *
21
-     * @type int
22
-     */
23
-    const checkin_status_never = 2;
24
-
25
-    /**
26
-     * Used to reference when a registration has been checked in.
27
-     *
28
-     * @type int
29
-     */
30
-    const checkin_status_in = 1;
31
-
32
-
33
-    /**
34
-     * Used to reference when a registration has been checked out.
35
-     *
36
-     * @type int
37
-     */
38
-    const checkin_status_out = 0;
39
-
40
-
41
-    /**
42
-     * extra meta key for tracking reg status os trashed registrations
43
-     *
44
-     * @type string
45
-     */
46
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
47
-
48
-
49
-    /**
50
-     * extra meta key for tracking if registration has reserved ticket
51
-     *
52
-     * @type string
53
-     */
54
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
55
-
56
-
57
-    /**
58
-     * @param array  $props_n_values          incoming values
59
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
-     *                                        used.)
61
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
-     *                                        date_format and the second value is the time format
63
-     * @return EE_Registration
64
-     * @throws EE_Error
65
-     */
66
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
67
-    {
68
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
-    }
71
-
72
-
73
-    /**
74
-     * @param array  $props_n_values  incoming values from the database
75
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
-     *                                the website will be used.
77
-     * @return EE_Registration
78
-     */
79
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
80
-    {
81
-        return new self($props_n_values, true, $timezone);
82
-    }
83
-
84
-
85
-    /**
86
-     *        Set Event ID
87
-     *
88
-     * @param        int $EVT_ID Event ID
89
-     * @throws EE_Error
90
-     * @throws RuntimeException
91
-     */
92
-    public function set_event($EVT_ID = 0)
93
-    {
94
-        $this->set('EVT_ID', $EVT_ID);
95
-    }
96
-
97
-
98
-    /**
99
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
100
-     * be routed to internal methods
101
-     *
102
-     * @param string $field_name
103
-     * @param mixed  $field_value
104
-     * @param bool   $use_default
105
-     * @throws \EE_Error
106
-     * @throws \RuntimeException
107
-     */
108
-    public function set($field_name, $field_value, $use_default = false)
109
-    {
110
-        switch ($field_name) {
111
-            case 'REG_code':
112
-                if (! empty($field_value) && $this->reg_code() === null) {
113
-                    $this->set_reg_code($field_value, $use_default);
114
-                }
115
-                break;
116
-            case 'STS_ID':
117
-                $this->set_status($field_value, $use_default);
118
-                break;
119
-            default:
120
-                parent::set($field_name, $field_value, $use_default);
121
-        }
122
-    }
123
-
124
-
125
-    /**
126
-     * Set Status ID
127
-     * updates the registration status and ALSO...
128
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
129
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
130
-     *
131
-     * @param string  $new_STS_ID
132
-     * @param boolean $use_default
133
-     * @return bool
134
-     * @throws \RuntimeException
135
-     * @throws \EE_Error
136
-     */
137
-    public function set_status($new_STS_ID = null, $use_default = false)
138
-    {
139
-        // get current REG_Status
140
-        $old_STS_ID = $this->status_ID();
141
-        // if status has changed
142
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
143
-            && ! empty($old_STS_ID) // and that old status is actually set
144
-            && ! empty($new_STS_ID) // as well as the new status
145
-            && $this->ID() // ensure registration is in the db
146
-        ) {
147
-            // TO approved
148
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
149
-                // reserve a space by incrementing ticket and datetime sold values
150
-                $this->_reserve_registration_space();
151
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID);
152
-                // OR FROM  approved
153
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
154
-                // release a space by decrementing ticket and datetime sold values
155
-                $this->_release_registration_space();
156
-                do_action('AHEE__EE_Registration__set_status__from_approved', $this, $old_STS_ID, $new_STS_ID);
157
-            }
158
-            // update status
159
-            parent::set('STS_ID', $new_STS_ID, $use_default);
160
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID);
161
-            /** @type EE_Transaction_Payments $transaction_payments */
162
-            $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
163
-            $transaction_payments->recalculate_transaction_total($this->transaction(), false);
164
-            $this->transaction()->update_status_based_on_total_paid(true);
165
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID);
166
-            return true;
167
-        }
168
-        //even though the old value matches the new value, it's still good to
169
-        //allow the parent set method to have a say
170
-        parent::set('STS_ID', $new_STS_ID, $use_default);
171
-        return true;
172
-    }
173
-
174
-
175
-    /**
176
-     * update REGs and TXN when cancelled or declined registrations involved
177
-     *
178
-     * @param string $new_STS_ID
179
-     * @param string $old_STS_ID
180
-     * @throws \EE_Error
181
-     */
182
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID)
183
-    {
184
-        // these reg statuses should not be considered in any calculations involving monies owing
185
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
186
-        // true if registration has been cancelled or declined
187
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
188
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
189
-        ) {
190
-            /** @type EE_Registration_Processor $registration_processor */
191
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
192
-            /** @type EE_Transaction_Processor $transaction_processor */
193
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
194
-            // cancelled or declined registration
195
-            $registration_processor->update_registration_after_being_canceled_or_declined(
196
-                $this,
197
-                $closed_reg_statuses
198
-            );
199
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
200
-                $this,
201
-                $closed_reg_statuses,
202
-                false
203
-            );
204
-            do_action('AHEE__EE_Registration__set_status__canceled_or_declined', $this, $old_STS_ID, $new_STS_ID);
205
-            return;
206
-        }
207
-        // true if reinstating cancelled or declined registration
208
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
209
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
210
-        ) {
211
-            /** @type EE_Registration_Processor $registration_processor */
212
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
213
-            /** @type EE_Transaction_Processor $transaction_processor */
214
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
215
-            // reinstating cancelled or declined registration
216
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
217
-                $this,
218
-                $closed_reg_statuses
219
-            );
220
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
221
-                $this,
222
-                $closed_reg_statuses,
223
-                false
224
-            );
225
-            do_action('AHEE__EE_Registration__set_status__after_reinstated', $this, $old_STS_ID, $new_STS_ID);
226
-        }
227
-    }
228
-
229
-
230
-    /**
231
-     *        get Status ID
232
-     */
233
-    public function status_ID()
234
-    {
235
-        return $this->get('STS_ID');
236
-    }
237
-
238
-
239
-    /**
240
-     * increments this registration's related ticket sold and corresponding datetime sold values
241
-     *
242
-     * @return void
243
-     * @throws EE_Error
244
-     * @throws EntityNotFoundException
245
-     */
246
-    private function _reserve_registration_space()
247
-    {
248
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
249
-        // so stop tracking that this reg has a ticket reserved
250
-        $this->release_reserved_ticket();
251
-        $ticket = $this->ticket();
252
-        $ticket->increase_sold();
253
-        $ticket->save();
254
-        // possibly set event status to sold out
255
-        $this->event()->perform_sold_out_status_check();
256
-    }
257
-
258
-
259
-    /**
260
-     * Gets the ticket this registration is for
261
-     *
262
-     * @param boolean $include_archived whether to include archived tickets or not.
263
-     * @return EE_Ticket|EE_Base_Class
264
-     * @throws \EE_Error
265
-     */
266
-    public function ticket($include_archived = true)
267
-    {
268
-        $query_params = array();
269
-        if ($include_archived) {
270
-            $query_params['default_where_conditions'] = 'none';
271
-        }
272
-        return $this->get_first_related('Ticket', $query_params);
273
-    }
274
-
275
-
276
-    /**
277
-     * Gets the event this registration is for
278
-     *
279
-     * @return EE_Event
280
-     * @throws EE_Error
281
-     * @throws EntityNotFoundException
282
-     */
283
-    public function event()
284
-    {
285
-        $event = $this->get_first_related('Event');
286
-        if (! $event instanceof \EE_Event) {
287
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
288
-        }
289
-        return $event;
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
295
-     * with the author of the event this registration is for.
296
-     *
297
-     * @since 4.5.0
298
-     * @return int
299
-     * @throws EE_Error
300
-     * @throws EntityNotFoundException
301
-     */
302
-    public function wp_user()
303
-    {
304
-        $event = $this->event();
305
-        if ($event instanceof EE_Event) {
306
-            return $event->wp_user();
307
-        }
308
-        return 0;
309
-    }
310
-
311
-
312
-    /**
313
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
314
-     *
315
-     * @return void
316
-     * @throws \EE_Error
317
-     */
318
-    private function _release_registration_space()
319
-    {
320
-        $ticket = $this->ticket();
321
-        $ticket->decrease_sold();
322
-        $ticket->save();
323
-    }
324
-
325
-
326
-    /**
327
-     * tracks this registration's ticket reservation in extra meta
328
-     * and can increment related ticket reserved and corresponding datetime reserved values
329
-     *
330
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
331
-     * @return void
332
-     * @throws \EE_Error
333
-     */
334
-    public function reserve_ticket($update_ticket = false)
335
-    {
336
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
337
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
338
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
339
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
340
-                $ticket = $this->ticket();
341
-                $ticket->increase_reserved();
342
-                $ticket->save();
343
-            }
344
-        }
345
-    }
346
-
347
-
348
-    /**
349
-     * stops tracking this registration's ticket reservation in extra meta
350
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
351
-     *
352
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
353
-     * @return void
354
-     * @throws \EE_Error
355
-     */
356
-    public function release_reserved_ticket($update_ticket = false)
357
-    {
358
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
359
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
360
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
361
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
362
-                $ticket = $this->ticket();
363
-                $ticket->decrease_reserved();
364
-                $ticket->save();
365
-            }
366
-        }
367
-    }
368
-
369
-
370
-    /**
371
-     * Set Attendee ID
372
-     *
373
-     * @param        int $ATT_ID Attendee ID
374
-     * @throws EE_Error
375
-     * @throws RuntimeException
376
-     */
377
-    public function set_attendee_id($ATT_ID = 0)
378
-    {
379
-        $this->set('ATT_ID', $ATT_ID);
380
-    }
381
-
382
-
383
-    /**
384
-     *        Set Transaction ID
385
-     *
386
-     * @param        int $TXN_ID Transaction ID
387
-     * @throws EE_Error
388
-     * @throws RuntimeException
389
-     */
390
-    public function set_transaction_id($TXN_ID = 0)
391
-    {
392
-        $this->set('TXN_ID', $TXN_ID);
393
-    }
394
-
395
-
396
-    /**
397
-     *        Set Session
398
-     *
399
-     * @param    string $REG_session PHP Session ID
400
-     * @throws EE_Error
401
-     * @throws RuntimeException
402
-     */
403
-    public function set_session($REG_session = '')
404
-    {
405
-        $this->set('REG_session', $REG_session);
406
-    }
407
-
408
-
409
-    /**
410
-     *        Set Registration URL Link
411
-     *
412
-     * @param    string $REG_url_link Registration URL Link
413
-     * @throws EE_Error
414
-     * @throws RuntimeException
415
-     */
416
-    public function set_reg_url_link($REG_url_link = '')
417
-    {
418
-        $this->set('REG_url_link', $REG_url_link);
419
-    }
420
-
421
-
422
-    /**
423
-     *        Set Attendee Counter
424
-     *
425
-     * @param        int $REG_count Primary Attendee
426
-     * @throws EE_Error
427
-     * @throws RuntimeException
428
-     */
429
-    public function set_count($REG_count = 1)
430
-    {
431
-        $this->set('REG_count', $REG_count);
432
-    }
433
-
434
-
435
-    /**
436
-     *        Set Group Size
437
-     *
438
-     * @param        boolean $REG_group_size Group Registration
439
-     * @throws EE_Error
440
-     * @throws RuntimeException
441
-     */
442
-    public function set_group_size($REG_group_size = false)
443
-    {
444
-        $this->set('REG_group_size', $REG_group_size);
445
-    }
446
-
447
-
448
-    /**
449
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
450
-     *    EEM_Registration::status_id_not_approved
451
-     *
452
-     * @return        boolean
453
-     */
454
-    public function is_not_approved()
455
-    {
456
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
457
-    }
458
-
459
-
460
-    /**
461
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
462
-     *    EEM_Registration::status_id_pending_payment
463
-     *
464
-     * @return        boolean
465
-     */
466
-    public function is_pending_payment()
467
-    {
468
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
469
-    }
470
-
471
-
472
-    /**
473
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
474
-     *
475
-     * @return        boolean
476
-     */
477
-    public function is_approved()
478
-    {
479
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
480
-    }
481
-
482
-
483
-    /**
484
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
485
-     *
486
-     * @return        boolean
487
-     */
488
-    public function is_cancelled()
489
-    {
490
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
491
-    }
492
-
493
-
494
-    /**
495
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
496
-     *
497
-     * @return        boolean
498
-     */
499
-    public function is_declined()
500
-    {
501
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
502
-    }
503
-
504
-
505
-    /**
506
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
507
-     *    EEM_Registration::status_id_incomplete
508
-     *
509
-     * @return        boolean
510
-     */
511
-    public function is_incomplete()
512
-    {
513
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
514
-    }
515
-
516
-
517
-    /**
518
-     *        Set Registration Date
519
-     *
520
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
521
-     *                                                 Date
522
-     * @throws EE_Error
523
-     * @throws RuntimeException
524
-     */
525
-    public function set_reg_date($REG_date = false)
526
-    {
527
-        $this->set('REG_date', $REG_date);
528
-    }
529
-
530
-
531
-    /**
532
-     *    Set final price owing for this registration after all ticket/price modifications
533
-     *
534
-     * @access    public
535
-     * @param    float $REG_final_price
536
-     * @throws EE_Error
537
-     * @throws RuntimeException
538
-     */
539
-    public function set_final_price($REG_final_price = 0.00)
540
-    {
541
-        $this->set('REG_final_price', $REG_final_price);
542
-    }
543
-
544
-
545
-    /**
546
-     *    Set amount paid towards this registration's final price
547
-     *
548
-     * @access    public
549
-     * @param    float $REG_paid
550
-     * @throws EE_Error
551
-     * @throws RuntimeException
552
-     */
553
-    public function set_paid($REG_paid = 0.00)
554
-    {
555
-        $this->set('REG_paid', $REG_paid);
556
-    }
557
-
558
-
559
-    /**
560
-     *        Attendee Is Going
561
-     *
562
-     * @param        boolean $REG_att_is_going Attendee Is Going
563
-     * @throws EE_Error
564
-     * @throws RuntimeException
565
-     */
566
-    public function set_att_is_going($REG_att_is_going = false)
567
-    {
568
-        $this->set('REG_att_is_going', $REG_att_is_going);
569
-    }
570
-
571
-
572
-    /**
573
-     * Gets the related attendee
574
-     *
575
-     * @return EE_Attendee
576
-     * @throws EE_Error
577
-     */
578
-    public function attendee()
579
-    {
580
-        return $this->get_first_related('Attendee');
581
-    }
582
-
583
-
584
-    /**
585
-     *        get Event ID
586
-     */
587
-    public function event_ID()
588
-    {
589
-        return $this->get('EVT_ID');
590
-    }
591
-
592
-
593
-    /**
594
-     *        get Event ID
595
-     */
596
-    public function event_name()
597
-    {
598
-        $event = $this->event_obj();
599
-        if ($event) {
600
-            return $event->name();
601
-        } else {
602
-            return null;
603
-        }
604
-    }
605
-
606
-
607
-    /**
608
-     * Fetches the event this registration is for
609
-     *
610
-     * @return EE_Event
611
-     * @throws EE_Error
612
-     */
613
-    public function event_obj()
614
-    {
615
-        return $this->get_first_related('Event');
616
-    }
617
-
618
-
619
-    /**
620
-     *        get Attendee ID
621
-     */
622
-    public function attendee_ID()
623
-    {
624
-        return $this->get('ATT_ID');
625
-    }
626
-
627
-
628
-    /**
629
-     *        get PHP Session ID
630
-     */
631
-    public function session_ID()
632
-    {
633
-        return $this->get('REG_session');
634
-    }
635
-
636
-
637
-    /**
638
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
639
-     *
640
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
641
-     * @return string
642
-     */
643
-    public function receipt_url($messenger = 'html')
644
-    {
645
-
646
-        /**
647
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
648
-         * already in use on old system.  If there is then we just return the standard url for it.
649
-         *
650
-         * @since 4.5.0
651
-         */
652
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
653
-        $has_custom             = EEH_Template::locate_template(
654
-            $template_relative_path,
655
-            array(),
656
-            true,
657
-            true,
658
-            true
659
-        );
660
-
661
-        if ($has_custom) {
662
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
663
-        }
664
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
665
-    }
666
-
667
-
668
-    /**
669
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
670
-     *
671
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
672
-     * @return string
673
-     * @throws EE_Error
674
-     */
675
-    public function invoice_url($messenger = 'html')
676
-    {
677
-        /**
678
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
679
-         * already in use on old system.  If there is then we just return the standard url for it.
680
-         *
681
-         * @since 4.5.0
682
-         */
683
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
684
-        $has_custom             = EEH_Template::locate_template(
685
-            $template_relative_path,
686
-            array(),
687
-            true,
688
-            true,
689
-            true
690
-        );
691
-
692
-        if ($has_custom) {
693
-            if ($messenger == 'html') {
694
-                return $this->invoice_url('launch');
695
-            }
696
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
697
-
698
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
699
-            if ($messenger == 'html') {
700
-                $query_args['html'] = true;
701
-            }
702
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
703
-        }
704
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
705
-    }
706
-
707
-
708
-    /**
709
-     * get Registration URL Link
710
-     *
711
-     * @access public
712
-     * @return string
713
-     * @throws \EE_Error
714
-     */
715
-    public function reg_url_link()
716
-    {
717
-        return (string) $this->get('REG_url_link');
718
-    }
719
-
720
-
721
-    /**
722
-     * Echoes out invoice_url()
723
-     *
724
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
725
-     * @return void
726
-     * @throws EE_Error
727
-     */
728
-    public function e_invoice_url($type = 'launch')
729
-    {
730
-        echo $this->invoice_url($type);
731
-    }
732
-
733
-
734
-    /**
735
-     * Echoes out payment_overview_url
736
-     */
737
-    public function e_payment_overview_url()
738
-    {
739
-        echo $this->payment_overview_url();
740
-    }
741
-
742
-
743
-    /**
744
-     * Gets the URL of the thank you page with this registration REG_url_link added as
745
-     * a query parameter
746
-     *
747
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
748
-     *                            payment overview url.
749
-     * @return string
750
-     * @throws EE_Error
751
-     */
752
-    public function payment_overview_url($clear_session = false)
753
-    {
754
-        return add_query_arg(array(
755
-            'e_reg_url_link' => $this->reg_url_link(),
756
-            'step'           => 'payment_options',
757
-            'revisit'        => true,
758
-            'clear_session' => (bool) $clear_session
759
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
760
-    }
761
-
762
-
763
-    /**
764
-     * Gets the URL of the thank you page with this registration REG_url_link added as
765
-     * a query parameter
766
-     *
767
-     * @return string
768
-     * @throws EE_Error
769
-     */
770
-    public function edit_attendee_information_url()
771
-    {
772
-        return add_query_arg(array(
773
-            'e_reg_url_link' => $this->reg_url_link(),
774
-            'step'           => 'attendee_information',
775
-            'revisit'        => true,
776
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
777
-    }
778
-
779
-
780
-    /**
781
-     * Simply generates and returns the appropriate admin_url link to edit this registration
782
-     *
783
-     * @return string
784
-     * @throws EE_Error
785
-     */
786
-    public function get_admin_edit_url()
787
-    {
788
-        return EEH_URL::add_query_args_and_nonce(array(
789
-            'page'    => 'espresso_registrations',
790
-            'action'  => 'view_registration',
791
-            '_REG_ID' => $this->ID(),
792
-        ), admin_url('admin.php'));
793
-    }
794
-
795
-
796
-    /**
797
-     *    is_primary_registrant?
798
-     */
799
-    public function is_primary_registrant()
800
-    {
801
-        return $this->get('REG_count') == 1 ? true : false;
802
-    }
803
-
804
-
805
-    /**
806
-     * This returns the primary registration object for this registration group (which may be this object).
807
-     *
808
-     * @return EE_Registration
809
-     * @throws EE_Error
810
-     */
811
-    public function get_primary_registration()
812
-    {
813
-        if ($this->is_primary_registrant()) {
814
-            return $this;
815
-        }
816
-
817
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
818
-        /** @var EE_Registration $primary_registrant */
819
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
820
-            array(
821
-                'TXN_ID'    => $this->transaction_ID(),
822
-                'REG_count' => 1,
823
-            ),
824
-        ));
825
-        return $primary_registrant;
826
-    }
827
-
828
-
829
-    /**
830
-     *        get  Attendee Number
831
-     *
832
-     * @access        public
833
-     */
834
-    public function count()
835
-    {
836
-        return $this->get('REG_count');
837
-    }
838
-
839
-
840
-    /**
841
-     *        get Group Size
842
-     */
843
-    public function group_size()
844
-    {
845
-        return $this->get('REG_group_size');
846
-    }
847
-
848
-
849
-    /**
850
-     *        get Registration Date
851
-     */
852
-    public function date()
853
-    {
854
-        return $this->get('REG_date');
855
-    }
856
-
857
-
858
-    /**
859
-     * gets a pretty date
860
-     *
861
-     * @param string $date_format
862
-     * @param string $time_format
863
-     * @return string
864
-     * @throws EE_Error
865
-     */
866
-    public function pretty_date($date_format = null, $time_format = null)
867
-    {
868
-        return $this->get_datetime('REG_date', $date_format, $time_format);
869
-    }
870
-
871
-
872
-    /**
873
-     * final_price
874
-     * the registration's share of the transaction total, so that the
875
-     * sum of all the transaction's REG_final_prices equal the transaction's total
876
-     *
877
-     * @return float
878
-     * @throws EE_Error
879
-     */
880
-    public function final_price()
881
-    {
882
-        return $this->get('REG_final_price');
883
-    }
884
-
885
-
886
-    /**
887
-     * pretty_final_price
888
-     *  final price as formatted string, with correct decimal places and currency symbol
889
-     *
890
-     * @return string
891
-     * @throws EE_Error
892
-     */
893
-    public function pretty_final_price()
894
-    {
895
-        return $this->get_pretty('REG_final_price');
896
-    }
897
-
898
-
899
-    /**
900
-     * get paid (yeah)
901
-     *
902
-     * @return float
903
-     * @throws EE_Error
904
-     */
905
-    public function paid()
906
-    {
907
-        return $this->get('REG_paid');
908
-    }
909
-
910
-
911
-    /**
912
-     * pretty_paid
913
-     *
914
-     * @return float
915
-     * @throws EE_Error
916
-     */
917
-    public function pretty_paid()
918
-    {
919
-        return $this->get_pretty('REG_paid');
920
-    }
921
-
922
-
923
-    /**
924
-     * owes_monies_and_can_pay
925
-     * whether or not this registration has monies owing and it's' status allows payment
926
-     *
927
-     * @param array $requires_payment
928
-     * @return bool
929
-     * @throws EE_Error
930
-     */
931
-    public function owes_monies_and_can_pay($requires_payment = array())
932
-    {
933
-        // these reg statuses require payment (if event is not free)
934
-        $requires_payment = ! empty($requires_payment)
935
-            ? $requires_payment
936
-            : EEM_Registration::reg_statuses_that_allow_payment();
937
-        if (in_array($this->status_ID(), $requires_payment) &&
938
-            $this->final_price() != 0 &&
939
-            $this->final_price() != $this->paid()
940
-        ) {
941
-            return true;
942
-        } else {
943
-            return false;
944
-        }
945
-    }
946
-
947
-
948
-    /**
949
-     * Prints out the return value of $this->pretty_status()
950
-     *
951
-     * @param bool $show_icons
952
-     * @return void
953
-     * @throws EE_Error
954
-     */
955
-    public function e_pretty_status($show_icons = false)
956
-    {
957
-        echo $this->pretty_status($show_icons);
958
-    }
959
-
960
-
961
-    /**
962
-     * Returns a nice version of the status for displaying to customers
963
-     *
964
-     * @param bool $show_icons
965
-     * @return string
966
-     * @throws EE_Error
967
-     */
968
-    public function pretty_status($show_icons = false)
969
-    {
970
-        $status = EEM_Status::instance()->localized_status(
971
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
972
-            false,
973
-            'sentence'
974
-        );
975
-        $icon   = '';
976
-        switch ($this->status_ID()) {
977
-            case EEM_Registration::status_id_approved:
978
-                $icon = $show_icons
979
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
980
-                    : '';
981
-                break;
982
-            case EEM_Registration::status_id_pending_payment:
983
-                $icon = $show_icons
984
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
985
-                    : '';
986
-                break;
987
-            case EEM_Registration::status_id_not_approved:
988
-                $icon = $show_icons
989
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
990
-                    : '';
991
-                break;
992
-            case EEM_Registration::status_id_cancelled:
993
-                $icon = $show_icons
994
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
995
-                    : '';
996
-                break;
997
-            case EEM_Registration::status_id_incomplete:
998
-                $icon = $show_icons
999
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1000
-                    : '';
1001
-                break;
1002
-            case EEM_Registration::status_id_declined:
1003
-                $icon = $show_icons
1004
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1005
-                    : '';
1006
-                break;
1007
-            case EEM_Registration::status_id_wait_list:
1008
-                $icon = $show_icons
1009
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1010
-                    : '';
1011
-                break;
1012
-        }
1013
-        return $icon . $status[$this->status_ID()];
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     *        get Attendee Is Going
1019
-     */
1020
-    public function att_is_going()
1021
-    {
1022
-        return $this->get('REG_att_is_going');
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Gets related answers
1028
-     *
1029
-     * @param array $query_params like EEM_Base::get_all
1030
-     * @return EE_Answer[]
1031
-     * @throws EE_Error
1032
-     */
1033
-    public function answers($query_params = null)
1034
-    {
1035
-        return $this->get_many_related('Answer', $query_params);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Gets the registration's answer value to the specified question
1041
-     * (either the question's ID or a question object)
1042
-     *
1043
-     * @param EE_Question|int $question
1044
-     * @param bool            $pretty_value
1045
-     * @return array|string if pretty_value= true, the result will always be a string
1046
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1047
-     * will convert it into some kind of string)
1048
-     * @throws EE_Error
1049
-     */
1050
-    public function answer_value_to_question($question, $pretty_value = true)
1051
-    {
1052
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1053
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     * question_groups
1059
-     * returns an array of EE_Question_Group objects for this registration
1060
-     *
1061
-     * @return EE_Question_Group[]
1062
-     * @throws EE_Error
1063
-     * @throws EntityNotFoundException
1064
-     */
1065
-    public function question_groups()
1066
-    {
1067
-        $question_groups = array();
1068
-        if ($this->event() instanceof EE_Event) {
1069
-            $question_groups = $this->event()->question_groups(
1070
-                array(
1071
-                    array(
1072
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1073
-                    ),
1074
-                    'order_by' => array('QSG_order' => 'ASC'),
1075
-                )
1076
-            );
1077
-        }
1078
-        return $question_groups;
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * count_question_groups
1084
-     * returns a count of the number of EE_Question_Group objects for this registration
1085
-     *
1086
-     * @return int
1087
-     * @throws EE_Error
1088
-     * @throws EntityNotFoundException
1089
-     */
1090
-    public function count_question_groups()
1091
-    {
1092
-        $qg_count = 0;
1093
-        if ($this->event() instanceof EE_Event) {
1094
-            $qg_count = $this->event()->count_related(
1095
-                'Question_Group',
1096
-                array(
1097
-                    array(
1098
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1099
-                    ),
1100
-                )
1101
-            );
1102
-        }
1103
-        return $qg_count;
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * Returns the registration date in the 'standard' string format
1109
-     * (function may be improved in the future to allow for different formats and timezones)
1110
-     *
1111
-     * @return string
1112
-     * @throws EE_Error
1113
-     */
1114
-    public function reg_date()
1115
-    {
1116
-        return $this->get_datetime('REG_date');
1117
-    }
1118
-
1119
-
1120
-    /**
1121
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1122
-     * the ticket this registration purchased, or the datetime they have registered
1123
-     * to attend)
1124
-     *
1125
-     * @return EE_Datetime_Ticket
1126
-     * @throws EE_Error
1127
-     */
1128
-    public function datetime_ticket()
1129
-    {
1130
-        return $this->get_first_related('Datetime_Ticket');
1131
-    }
1132
-
1133
-
1134
-    /**
1135
-     * Sets the registration's datetime_ticket.
1136
-     *
1137
-     * @param EE_Datetime_Ticket $datetime_ticket
1138
-     * @return EE_Datetime_Ticket
1139
-     * @throws EE_Error
1140
-     */
1141
-    public function set_datetime_ticket($datetime_ticket)
1142
-    {
1143
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1144
-    }
1145
-
1146
-    /**
1147
-     * Gets deleted
1148
-     *
1149
-     * @return bool
1150
-     * @throws EE_Error
1151
-     */
1152
-    public function deleted()
1153
-    {
1154
-        return $this->get('REG_deleted');
1155
-    }
1156
-
1157
-    /**
1158
-     * Sets deleted
1159
-     *
1160
-     * @param boolean $deleted
1161
-     * @return bool
1162
-     * @throws EE_Error
1163
-     * @throws RuntimeException
1164
-     */
1165
-    public function set_deleted($deleted)
1166
-    {
1167
-        if ($deleted) {
1168
-            $this->delete();
1169
-        } else {
1170
-            $this->restore();
1171
-        }
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * Get the status object of this object
1177
-     *
1178
-     * @return EE_Status
1179
-     * @throws EE_Error
1180
-     */
1181
-    public function status_obj()
1182
-    {
1183
-        return $this->get_first_related('Status');
1184
-    }
1185
-
1186
-
1187
-    /**
1188
-     * Returns the number of times this registration has checked into any of the datetimes
1189
-     * its available for
1190
-     *
1191
-     * @return int
1192
-     * @throws EE_Error
1193
-     */
1194
-    public function count_checkins()
1195
-    {
1196
-        return $this->get_model()->count_related($this, 'Checkin');
1197
-    }
1198
-
1199
-
1200
-    /**
1201
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1202
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1203
-     *
1204
-     * @return int
1205
-     * @throws EE_Error
1206
-     */
1207
-    public function count_checkins_not_checkedout()
1208
-    {
1209
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1215
-     *
1216
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1217
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1218
-     *                                          consider registration status as well as datetime access.
1219
-     * @return bool
1220
-     * @throws EE_Error
1221
-     */
1222
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1223
-    {
1224
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1225
-
1226
-        //first check registration status
1227
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1228
-            return false;
1229
-        }
1230
-        //is there a datetime ticket that matches this dtt_ID?
1231
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
-            array(
1233
-                'TKT_ID' => $this->get('TKT_ID'),
1234
-                'DTT_ID' => $DTT_ID,
1235
-            ),
1236
-        )))
1237
-        ) {
1238
-            return false;
1239
-        }
1240
-
1241
-        //final check is against TKT_uses
1242
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1248
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1249
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1250
-     * then return false.  Otherwise return true.
1251
-     *
1252
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1253
-     * @return bool true means can checkin.  false means cannot checkin.
1254
-     * @throws EE_Error
1255
-     */
1256
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1257
-    {
1258
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1259
-
1260
-        if (! $DTT_ID) {
1261
-            return false;
1262
-        }
1263
-
1264
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1265
-
1266
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1267
-        // check-in or not.
1268
-        if (! $max_uses || $max_uses === EE_INF) {
1269
-            return true;
1270
-        }
1271
-
1272
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1273
-        //go ahead and toggle.
1274
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1275
-            return true;
1276
-        }
1277
-
1278
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1279
-        //disallows further check-ins.
1280
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1281
-            array(
1282
-                'REG_ID' => $this->ID(),
1283
-                'CHK_in' => true,
1284
-            ),
1285
-        ), 'DTT_ID', true);
1286
-        // checkins have already reached their max number of uses
1287
-        // so registrant can NOT checkin
1288
-        if ($count_unique_dtt_checkins >= $max_uses) {
1289
-            EE_Error::add_error(
1290
-                esc_html__(
1291
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1292
-                    'event_espresso'
1293
-                ),
1294
-                __FILE__,
1295
-                __FUNCTION__,
1296
-                __LINE__
1297
-            );
1298
-            return false;
1299
-        }
1300
-        return true;
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * toggle Check-in status for this registration
1306
-     * Check-ins are toggled in the following order:
1307
-     * never checked in -> checked in
1308
-     * checked in -> checked out
1309
-     * checked out -> checked in
1310
-     *
1311
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1312
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1313
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1314
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1315
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1316
-     * @throws EE_Error
1317
-     */
1318
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1319
-    {
1320
-        if (empty($DTT_ID)) {
1321
-            $datetime = $this->get_latest_related_datetime();
1322
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1323
-            // verify the registration can checkin for the given DTT_ID
1324
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
-            EE_Error::add_error(
1326
-                sprintf(
1327
-                    esc_html__(
1328
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1329
-                        'event_espresso'
1330
-                    ),
1331
-                    $this->ID(),
1332
-                    $DTT_ID
1333
-                ),
1334
-                __FILE__,
1335
-                __FUNCTION__,
1336
-                __LINE__
1337
-            );
1338
-            return false;
1339
-        }
1340
-        $status_paths = array(
1341
-            EE_Registration::checkin_status_never => EE_Registration::checkin_status_in,
1342
-            EE_Registration::checkin_status_in    => EE_Registration::checkin_status_out,
1343
-            EE_Registration::checkin_status_out   => EE_Registration::checkin_status_in,
1344
-        );
1345
-        //start by getting the current status so we know what status we'll be changing to.
1346
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1347
-        $status_to  = $status_paths[$cur_status];
1348
-        // database only records true for checked IN or false for checked OUT
1349
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1350
-        $new_status = $status_to === EE_Registration::checkin_status_in ? true : false;
1351
-        // add relation - note Check-ins are always creating new rows
1352
-        // because we are keeping track of Check-ins over time.
1353
-        // Eventually we'll probably want to show a list table
1354
-        // for the individual Check-ins so that they can be managed.
1355
-        $checkin = EE_Checkin::new_instance(array(
1356
-            'REG_ID' => $this->ID(),
1357
-            'DTT_ID' => $DTT_ID,
1358
-            'CHK_in' => $new_status,
1359
-        ));
1360
-        // if the record could not be saved then return false
1361
-        if ($checkin->save() === 0) {
1362
-            if (WP_DEBUG) {
1363
-                global $wpdb;
1364
-                $error = sprintf(
1365
-                    esc_html__(
1366
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1367
-                        'event_espresso'
1368
-                    ),
1369
-                    '<br />',
1370
-                    $wpdb->last_error
1371
-                );
1372
-            } else {
1373
-                $error = esc_html__(
1374
-                    'Registration check in update failed because of an unknown database error',
1375
-                    'event_espresso'
1376
-                );
1377
-            }
1378
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1379
-            return false;
1380
-        }
1381
-        return $status_to;
1382
-    }
1383
-
1384
-
1385
-    /**
1386
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1387
-     * "Latest" is defined by the `DTT_EVT_start` column.
1388
-     *
1389
-     * @return EE_Datetime|null
1390
-     * @throws \EE_Error
1391
-     */
1392
-    public function get_latest_related_datetime()
1393
-    {
1394
-        return EEM_Datetime::instance()->get_one(
1395
-            array(
1396
-                array(
1397
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1398
-                ),
1399
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1400
-            )
1401
-        );
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1407
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1408
-     *
1409
-     * @throws \EE_Error
1410
-     */
1411
-    public function get_earliest_related_datetime()
1412
-    {
1413
-        return EEM_Datetime::instance()->get_one(
1414
-            array(
1415
-                array(
1416
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1417
-                ),
1418
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1419
-            )
1420
-        );
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * This method simply returns the check-in status for this registration and the given datetime.
1426
-     * If neither the datetime nor the checkin values are provided as arguments,
1427
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1428
-     *
1429
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1430
-     *                            (if empty we'll get the primary datetime for
1431
-     *                            this registration (via event) and use it's ID);
1432
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1433
-     * @return int                Integer representing Check-in status.
1434
-     * @throws \EE_Error
1435
-     */
1436
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1437
-    {
1438
-        $checkin_query_params = array(
1439
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1440
-        );
1441
-
1442
-        if ($DTT_ID > 0) {
1443
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1444
-        }
1445
-
1446
-        //get checkin object (if exists)
1447
-        $checkin = $checkin instanceof EE_Checkin
1448
-            ? $checkin
1449
-            : $this->get_first_related('Checkin', $checkin_query_params);
1450
-        if ($checkin instanceof EE_Checkin) {
1451
-            if ($checkin->get('CHK_in')) {
1452
-                return EE_Registration::checkin_status_in; //checked in
1453
-            }
1454
-            return EE_Registration::checkin_status_out; //had checked in but is now checked out.
1455
-        }
1456
-        return EE_Registration::checkin_status_never; //never been checked in
1457
-    }
1458
-
1459
-
1460
-    /**
1461
-     * This method returns a localized message for the toggled Check-in message.
1462
-     *
1463
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1464
-     *                     then it is assumed Check-in for primary datetime was toggled.
1465
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1466
-     *                     message can be customized with the attendee name.
1467
-     * @return string internationalized message
1468
-     * @throws EE_Error
1469
-     */
1470
-    public function get_checkin_msg($DTT_ID, $error = false)
1471
-    {
1472
-        //let's get the attendee first so we can include the name of the attendee
1473
-        $attendee = $this->get_first_related('Attendee');
1474
-        if ($attendee instanceof EE_Attendee) {
1475
-            if ($error) {
1476
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1477
-            }
1478
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1479
-            //what is the status message going to be?
1480
-            switch ($cur_status) {
1481
-                case EE_Registration::checkin_status_never:
1482
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1483
-                        $attendee->full_name());
1484
-                    break;
1485
-                case EE_Registration::checkin_status_in:
1486
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1487
-                    break;
1488
-                case EE_Registration::checkin_status_out:
1489
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1490
-                    break;
1491
-            }
1492
-        }
1493
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1494
-    }
1495
-
1496
-
1497
-    /**
1498
-     * Returns the related EE_Transaction to this registration
1499
-     *
1500
-     * @return EE_Transaction
1501
-     * @throws EE_Error
1502
-     * @throws EntityNotFoundException
1503
-     */
1504
-    public function transaction()
1505
-    {
1506
-        $transaction = $this->get_first_related('Transaction');
1507
-        if (! $transaction instanceof \EE_Transaction) {
1508
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1509
-        }
1510
-        return $transaction;
1511
-    }
1512
-
1513
-
1514
-    /**
1515
-     *        get Registration Code
1516
-     */
1517
-    public function reg_code()
1518
-    {
1519
-        return $this->get('REG_code');
1520
-    }
1521
-
1522
-
1523
-    /**
1524
-     *        get Transaction ID
1525
-     */
1526
-    public function transaction_ID()
1527
-    {
1528
-        return $this->get('TXN_ID');
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * @return int
1534
-     * @throws EE_Error
1535
-     */
1536
-    public function ticket_ID()
1537
-    {
1538
-        return $this->get('TKT_ID');
1539
-    }
1540
-
1541
-
1542
-    /**
1543
-     *        Set Registration Code
1544
-     *
1545
-     * @access    public
1546
-     * @param    string  $REG_code Registration Code
1547
-     * @param    boolean $use_default
1548
-     * @throws EE_Error
1549
-     */
1550
-    public function set_reg_code($REG_code, $use_default = false)
1551
-    {
1552
-        if (empty($REG_code)) {
1553
-            EE_Error::add_error(
1554
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1555
-                __FILE__,
1556
-                __FUNCTION__,
1557
-                __LINE__
1558
-            );
1559
-            return;
1560
-        }
1561
-        if (! $this->reg_code()) {
1562
-            parent::set('REG_code', $REG_code, $use_default);
1563
-        } else {
1564
-            EE_Error::doing_it_wrong(
1565
-                __CLASS__ . '::' . __FUNCTION__,
1566
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1567
-                '4.6.0'
1568
-            );
1569
-        }
1570
-    }
1571
-
1572
-
1573
-    /**
1574
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1575
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1576
-     *    $registration->transaction()->registrations();
1577
-     *
1578
-     * @since 4.5.0
1579
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1580
-     * @throws EE_Error
1581
-     */
1582
-    public function get_all_other_registrations_in_group()
1583
-    {
1584
-        if ($this->group_size() < 2) {
1585
-            return array();
1586
-        }
1587
-
1588
-        $query[0] = array(
1589
-            'TXN_ID' => $this->transaction_ID(),
1590
-            'REG_ID' => array('!=', $this->ID()),
1591
-            'TKT_ID' => $this->ticket_ID(),
1592
-        );
1593
-        /** @var EE_Registration[] $registrations */
1594
-        $registrations = $this->get_model()->get_all($query);
1595
-        return $registrations;
1596
-    }
1597
-
1598
-    /**
1599
-     * Return the link to the admin details for the object.
1600
-     *
1601
-     * @return string
1602
-     * @throws EE_Error
1603
-     */
1604
-    public function get_admin_details_link()
1605
-    {
1606
-        EE_Registry::instance()->load_helper('URL');
1607
-        return EEH_URL::add_query_args_and_nonce(
1608
-            array(
1609
-                'page'    => 'espresso_registrations',
1610
-                'action'  => 'view_registration',
1611
-                '_REG_ID' => $this->ID(),
1612
-            ),
1613
-            admin_url('admin.php')
1614
-        );
1615
-    }
1616
-
1617
-    /**
1618
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1619
-     *
1620
-     * @return string
1621
-     * @throws EE_Error
1622
-     */
1623
-    public function get_admin_edit_link()
1624
-    {
1625
-        return $this->get_admin_details_link();
1626
-    }
1627
-
1628
-    /**
1629
-     * Returns the link to a settings page for the object.
1630
-     *
1631
-     * @return string
1632
-     * @throws EE_Error
1633
-     */
1634
-    public function get_admin_settings_link()
1635
-    {
1636
-        return $this->get_admin_details_link();
1637
-    }
1638
-
1639
-    /**
1640
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1641
-     *
1642
-     * @return string
1643
-     */
1644
-    public function get_admin_overview_link()
1645
-    {
1646
-        EE_Registry::instance()->load_helper('URL');
1647
-        return EEH_URL::add_query_args_and_nonce(
1648
-            array(
1649
-                'page' => 'espresso_registrations',
1650
-            ),
1651
-            admin_url('admin.php')
1652
-        );
1653
-    }
1654
-
1655
-
1656
-    /**
1657
-     * @param array $query_params
1658
-     * @return \EE_Registration[]
1659
-     * @throws \EE_Error
1660
-     */
1661
-    public function payments($query_params = array())
1662
-    {
1663
-        return $this->get_many_related('Payment', $query_params);
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     * @param array $query_params
1669
-     * @return \EE_Registration_Payment[]
1670
-     * @throws \EE_Error
1671
-     */
1672
-    public function registration_payments($query_params = array())
1673
-    {
1674
-        return $this->get_many_related('Registration_Payment', $query_params);
1675
-    }
1676
-
1677
-
1678
-    /**
1679
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1680
-     * Note: if there are no payments on the registration there will be no payment method returned.
1681
-     *
1682
-     * @return EE_Payment_Method|null
1683
-     */
1684
-    public function payment_method()
1685
-    {
1686
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1687
-    }
1688
-
1689
-
1690
-    /**
1691
-     * @return \EE_Line_Item
1692
-     * @throws EntityNotFoundException
1693
-     * @throws \EE_Error
1694
-     */
1695
-    public function ticket_line_item()
1696
-    {
1697
-        $ticket            = $this->ticket();
1698
-        $transaction       = $this->transaction();
1699
-        $line_item         = null;
1700
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1701
-            $transaction->total_line_item(),
1702
-            'Ticket',
1703
-            array($ticket->ID())
1704
-        );
1705
-        foreach ($ticket_line_items as $ticket_line_item) {
1706
-            if (
1707
-                $ticket_line_item instanceof \EE_Line_Item
1708
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1709
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1710
-            ) {
1711
-                $line_item = $ticket_line_item;
1712
-                break;
1713
-            }
1714
-        }
1715
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1717
-        }
1718
-        return $line_item;
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * Soft Deletes this model object.
1724
-     *
1725
-     * @return boolean | int
1726
-     * @throws \RuntimeException
1727
-     * @throws \EE_Error
1728
-     */
1729
-    public function delete()
1730
-    {
1731
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1732
-            $this->set_status(EEM_Registration::status_id_cancelled);
1733
-        }
1734
-        return parent::delete();
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1740
-     *
1741
-     * @throws \EE_Error
1742
-     * @throws \RuntimeException
1743
-     */
1744
-    public function restore()
1745
-    {
1746
-        $previous_status = $this->get_extra_meta(
1747
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1748
-            true,
1749
-            EEM_Registration::status_id_cancelled
1750
-        );
1751
-        if ($previous_status) {
1752
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1753
-            $this->set_status($previous_status);
1754
-        }
1755
-        return parent::restore();
1756
-    }
1757
-
1758
-
1759
-
1760
-    /*************************** DEPRECATED ***************************/
1761
-
1762
-
1763
-    /**
1764
-     * @deprecated
1765
-     * @since     4.7.0
1766
-     * @access    public
1767
-     */
1768
-    public function price_paid()
1769
-    {
1770
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1771
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1772
-            '4.7.0');
1773
-        return $this->final_price();
1774
-    }
1775
-
1776
-
1777
-    /**
1778
-     * @deprecated
1779
-     * @since     4.7.0
1780
-     * @access    public
1781
-     * @param    float $REG_final_price
1782
-     * @throws EE_Error
1783
-     * @throws RuntimeException
1784
-     */
1785
-    public function set_price_paid($REG_final_price = 0.00)
1786
-    {
1787
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1788
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1789
-            '4.7.0');
1790
-        $this->set_final_price($REG_final_price);
1791
-    }
1792
-
1793
-
1794
-    /**
1795
-     * @deprecated
1796
-     * @since 4.7.0
1797
-     * @return string
1798
-     * @throws EE_Error
1799
-     */
1800
-    public function pretty_price_paid()
1801
-    {
1802
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1803
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1804
-                'event_espresso'), '4.7.0');
1805
-        return $this->pretty_final_price();
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     * Gets the primary datetime related to this registration via the related Event to this registration
1811
-     *
1812
-     * @deprecated 4.9.17
1813
-     * @return EE_Datetime
1814
-     * @throws EE_Error
1815
-     * @throws EntityNotFoundException
1816
-     */
1817
-    public function get_related_primary_datetime()
1818
-    {
1819
-        EE_Error::doing_it_wrong(
1820
-            __METHOD__,
1821
-            esc_html__(
1822
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1823
-                'event_espresso'
1824
-            ),
1825
-            '4.9.17',
1826
-            '5.0.0'
1827
-        );
1828
-        return $this->event()->primary_datetime();
1829
-    }
18
+	/**
19
+	 * Used to reference when a registration has never been checked in.
20
+	 *
21
+	 * @type int
22
+	 */
23
+	const checkin_status_never = 2;
24
+
25
+	/**
26
+	 * Used to reference when a registration has been checked in.
27
+	 *
28
+	 * @type int
29
+	 */
30
+	const checkin_status_in = 1;
31
+
32
+
33
+	/**
34
+	 * Used to reference when a registration has been checked out.
35
+	 *
36
+	 * @type int
37
+	 */
38
+	const checkin_status_out = 0;
39
+
40
+
41
+	/**
42
+	 * extra meta key for tracking reg status os trashed registrations
43
+	 *
44
+	 * @type string
45
+	 */
46
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
47
+
48
+
49
+	/**
50
+	 * extra meta key for tracking if registration has reserved ticket
51
+	 *
52
+	 * @type string
53
+	 */
54
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
55
+
56
+
57
+	/**
58
+	 * @param array  $props_n_values          incoming values
59
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
+	 *                                        used.)
61
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
+	 *                                        date_format and the second value is the time format
63
+	 * @return EE_Registration
64
+	 * @throws EE_Error
65
+	 */
66
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
67
+	{
68
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param array  $props_n_values  incoming values from the database
75
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
+	 *                                the website will be used.
77
+	 * @return EE_Registration
78
+	 */
79
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
80
+	{
81
+		return new self($props_n_values, true, $timezone);
82
+	}
83
+
84
+
85
+	/**
86
+	 *        Set Event ID
87
+	 *
88
+	 * @param        int $EVT_ID Event ID
89
+	 * @throws EE_Error
90
+	 * @throws RuntimeException
91
+	 */
92
+	public function set_event($EVT_ID = 0)
93
+	{
94
+		$this->set('EVT_ID', $EVT_ID);
95
+	}
96
+
97
+
98
+	/**
99
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
100
+	 * be routed to internal methods
101
+	 *
102
+	 * @param string $field_name
103
+	 * @param mixed  $field_value
104
+	 * @param bool   $use_default
105
+	 * @throws \EE_Error
106
+	 * @throws \RuntimeException
107
+	 */
108
+	public function set($field_name, $field_value, $use_default = false)
109
+	{
110
+		switch ($field_name) {
111
+			case 'REG_code':
112
+				if (! empty($field_value) && $this->reg_code() === null) {
113
+					$this->set_reg_code($field_value, $use_default);
114
+				}
115
+				break;
116
+			case 'STS_ID':
117
+				$this->set_status($field_value, $use_default);
118
+				break;
119
+			default:
120
+				parent::set($field_name, $field_value, $use_default);
121
+		}
122
+	}
123
+
124
+
125
+	/**
126
+	 * Set Status ID
127
+	 * updates the registration status and ALSO...
128
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
129
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
130
+	 *
131
+	 * @param string  $new_STS_ID
132
+	 * @param boolean $use_default
133
+	 * @return bool
134
+	 * @throws \RuntimeException
135
+	 * @throws \EE_Error
136
+	 */
137
+	public function set_status($new_STS_ID = null, $use_default = false)
138
+	{
139
+		// get current REG_Status
140
+		$old_STS_ID = $this->status_ID();
141
+		// if status has changed
142
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
143
+			&& ! empty($old_STS_ID) // and that old status is actually set
144
+			&& ! empty($new_STS_ID) // as well as the new status
145
+			&& $this->ID() // ensure registration is in the db
146
+		) {
147
+			// TO approved
148
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
149
+				// reserve a space by incrementing ticket and datetime sold values
150
+				$this->_reserve_registration_space();
151
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID);
152
+				// OR FROM  approved
153
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
154
+				// release a space by decrementing ticket and datetime sold values
155
+				$this->_release_registration_space();
156
+				do_action('AHEE__EE_Registration__set_status__from_approved', $this, $old_STS_ID, $new_STS_ID);
157
+			}
158
+			// update status
159
+			parent::set('STS_ID', $new_STS_ID, $use_default);
160
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID);
161
+			/** @type EE_Transaction_Payments $transaction_payments */
162
+			$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
163
+			$transaction_payments->recalculate_transaction_total($this->transaction(), false);
164
+			$this->transaction()->update_status_based_on_total_paid(true);
165
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID);
166
+			return true;
167
+		}
168
+		//even though the old value matches the new value, it's still good to
169
+		//allow the parent set method to have a say
170
+		parent::set('STS_ID', $new_STS_ID, $use_default);
171
+		return true;
172
+	}
173
+
174
+
175
+	/**
176
+	 * update REGs and TXN when cancelled or declined registrations involved
177
+	 *
178
+	 * @param string $new_STS_ID
179
+	 * @param string $old_STS_ID
180
+	 * @throws \EE_Error
181
+	 */
182
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID)
183
+	{
184
+		// these reg statuses should not be considered in any calculations involving monies owing
185
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
186
+		// true if registration has been cancelled or declined
187
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
188
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
189
+		) {
190
+			/** @type EE_Registration_Processor $registration_processor */
191
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
192
+			/** @type EE_Transaction_Processor $transaction_processor */
193
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
194
+			// cancelled or declined registration
195
+			$registration_processor->update_registration_after_being_canceled_or_declined(
196
+				$this,
197
+				$closed_reg_statuses
198
+			);
199
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
200
+				$this,
201
+				$closed_reg_statuses,
202
+				false
203
+			);
204
+			do_action('AHEE__EE_Registration__set_status__canceled_or_declined', $this, $old_STS_ID, $new_STS_ID);
205
+			return;
206
+		}
207
+		// true if reinstating cancelled or declined registration
208
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
209
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
210
+		) {
211
+			/** @type EE_Registration_Processor $registration_processor */
212
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
213
+			/** @type EE_Transaction_Processor $transaction_processor */
214
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
215
+			// reinstating cancelled or declined registration
216
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
217
+				$this,
218
+				$closed_reg_statuses
219
+			);
220
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
221
+				$this,
222
+				$closed_reg_statuses,
223
+				false
224
+			);
225
+			do_action('AHEE__EE_Registration__set_status__after_reinstated', $this, $old_STS_ID, $new_STS_ID);
226
+		}
227
+	}
228
+
229
+
230
+	/**
231
+	 *        get Status ID
232
+	 */
233
+	public function status_ID()
234
+	{
235
+		return $this->get('STS_ID');
236
+	}
237
+
238
+
239
+	/**
240
+	 * increments this registration's related ticket sold and corresponding datetime sold values
241
+	 *
242
+	 * @return void
243
+	 * @throws EE_Error
244
+	 * @throws EntityNotFoundException
245
+	 */
246
+	private function _reserve_registration_space()
247
+	{
248
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
249
+		// so stop tracking that this reg has a ticket reserved
250
+		$this->release_reserved_ticket();
251
+		$ticket = $this->ticket();
252
+		$ticket->increase_sold();
253
+		$ticket->save();
254
+		// possibly set event status to sold out
255
+		$this->event()->perform_sold_out_status_check();
256
+	}
257
+
258
+
259
+	/**
260
+	 * Gets the ticket this registration is for
261
+	 *
262
+	 * @param boolean $include_archived whether to include archived tickets or not.
263
+	 * @return EE_Ticket|EE_Base_Class
264
+	 * @throws \EE_Error
265
+	 */
266
+	public function ticket($include_archived = true)
267
+	{
268
+		$query_params = array();
269
+		if ($include_archived) {
270
+			$query_params['default_where_conditions'] = 'none';
271
+		}
272
+		return $this->get_first_related('Ticket', $query_params);
273
+	}
274
+
275
+
276
+	/**
277
+	 * Gets the event this registration is for
278
+	 *
279
+	 * @return EE_Event
280
+	 * @throws EE_Error
281
+	 * @throws EntityNotFoundException
282
+	 */
283
+	public function event()
284
+	{
285
+		$event = $this->get_first_related('Event');
286
+		if (! $event instanceof \EE_Event) {
287
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
288
+		}
289
+		return $event;
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
295
+	 * with the author of the event this registration is for.
296
+	 *
297
+	 * @since 4.5.0
298
+	 * @return int
299
+	 * @throws EE_Error
300
+	 * @throws EntityNotFoundException
301
+	 */
302
+	public function wp_user()
303
+	{
304
+		$event = $this->event();
305
+		if ($event instanceof EE_Event) {
306
+			return $event->wp_user();
307
+		}
308
+		return 0;
309
+	}
310
+
311
+
312
+	/**
313
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
314
+	 *
315
+	 * @return void
316
+	 * @throws \EE_Error
317
+	 */
318
+	private function _release_registration_space()
319
+	{
320
+		$ticket = $this->ticket();
321
+		$ticket->decrease_sold();
322
+		$ticket->save();
323
+	}
324
+
325
+
326
+	/**
327
+	 * tracks this registration's ticket reservation in extra meta
328
+	 * and can increment related ticket reserved and corresponding datetime reserved values
329
+	 *
330
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
331
+	 * @return void
332
+	 * @throws \EE_Error
333
+	 */
334
+	public function reserve_ticket($update_ticket = false)
335
+	{
336
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
337
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
338
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
339
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
340
+				$ticket = $this->ticket();
341
+				$ticket->increase_reserved();
342
+				$ticket->save();
343
+			}
344
+		}
345
+	}
346
+
347
+
348
+	/**
349
+	 * stops tracking this registration's ticket reservation in extra meta
350
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
351
+	 *
352
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
353
+	 * @return void
354
+	 * @throws \EE_Error
355
+	 */
356
+	public function release_reserved_ticket($update_ticket = false)
357
+	{
358
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
359
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
360
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
361
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
362
+				$ticket = $this->ticket();
363
+				$ticket->decrease_reserved();
364
+				$ticket->save();
365
+			}
366
+		}
367
+	}
368
+
369
+
370
+	/**
371
+	 * Set Attendee ID
372
+	 *
373
+	 * @param        int $ATT_ID Attendee ID
374
+	 * @throws EE_Error
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function set_attendee_id($ATT_ID = 0)
378
+	{
379
+		$this->set('ATT_ID', $ATT_ID);
380
+	}
381
+
382
+
383
+	/**
384
+	 *        Set Transaction ID
385
+	 *
386
+	 * @param        int $TXN_ID Transaction ID
387
+	 * @throws EE_Error
388
+	 * @throws RuntimeException
389
+	 */
390
+	public function set_transaction_id($TXN_ID = 0)
391
+	{
392
+		$this->set('TXN_ID', $TXN_ID);
393
+	}
394
+
395
+
396
+	/**
397
+	 *        Set Session
398
+	 *
399
+	 * @param    string $REG_session PHP Session ID
400
+	 * @throws EE_Error
401
+	 * @throws RuntimeException
402
+	 */
403
+	public function set_session($REG_session = '')
404
+	{
405
+		$this->set('REG_session', $REG_session);
406
+	}
407
+
408
+
409
+	/**
410
+	 *        Set Registration URL Link
411
+	 *
412
+	 * @param    string $REG_url_link Registration URL Link
413
+	 * @throws EE_Error
414
+	 * @throws RuntimeException
415
+	 */
416
+	public function set_reg_url_link($REG_url_link = '')
417
+	{
418
+		$this->set('REG_url_link', $REG_url_link);
419
+	}
420
+
421
+
422
+	/**
423
+	 *        Set Attendee Counter
424
+	 *
425
+	 * @param        int $REG_count Primary Attendee
426
+	 * @throws EE_Error
427
+	 * @throws RuntimeException
428
+	 */
429
+	public function set_count($REG_count = 1)
430
+	{
431
+		$this->set('REG_count', $REG_count);
432
+	}
433
+
434
+
435
+	/**
436
+	 *        Set Group Size
437
+	 *
438
+	 * @param        boolean $REG_group_size Group Registration
439
+	 * @throws EE_Error
440
+	 * @throws RuntimeException
441
+	 */
442
+	public function set_group_size($REG_group_size = false)
443
+	{
444
+		$this->set('REG_group_size', $REG_group_size);
445
+	}
446
+
447
+
448
+	/**
449
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
450
+	 *    EEM_Registration::status_id_not_approved
451
+	 *
452
+	 * @return        boolean
453
+	 */
454
+	public function is_not_approved()
455
+	{
456
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
457
+	}
458
+
459
+
460
+	/**
461
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
462
+	 *    EEM_Registration::status_id_pending_payment
463
+	 *
464
+	 * @return        boolean
465
+	 */
466
+	public function is_pending_payment()
467
+	{
468
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
469
+	}
470
+
471
+
472
+	/**
473
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
474
+	 *
475
+	 * @return        boolean
476
+	 */
477
+	public function is_approved()
478
+	{
479
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
480
+	}
481
+
482
+
483
+	/**
484
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
485
+	 *
486
+	 * @return        boolean
487
+	 */
488
+	public function is_cancelled()
489
+	{
490
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
491
+	}
492
+
493
+
494
+	/**
495
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
496
+	 *
497
+	 * @return        boolean
498
+	 */
499
+	public function is_declined()
500
+	{
501
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
502
+	}
503
+
504
+
505
+	/**
506
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
507
+	 *    EEM_Registration::status_id_incomplete
508
+	 *
509
+	 * @return        boolean
510
+	 */
511
+	public function is_incomplete()
512
+	{
513
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
514
+	}
515
+
516
+
517
+	/**
518
+	 *        Set Registration Date
519
+	 *
520
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
521
+	 *                                                 Date
522
+	 * @throws EE_Error
523
+	 * @throws RuntimeException
524
+	 */
525
+	public function set_reg_date($REG_date = false)
526
+	{
527
+		$this->set('REG_date', $REG_date);
528
+	}
529
+
530
+
531
+	/**
532
+	 *    Set final price owing for this registration after all ticket/price modifications
533
+	 *
534
+	 * @access    public
535
+	 * @param    float $REG_final_price
536
+	 * @throws EE_Error
537
+	 * @throws RuntimeException
538
+	 */
539
+	public function set_final_price($REG_final_price = 0.00)
540
+	{
541
+		$this->set('REG_final_price', $REG_final_price);
542
+	}
543
+
544
+
545
+	/**
546
+	 *    Set amount paid towards this registration's final price
547
+	 *
548
+	 * @access    public
549
+	 * @param    float $REG_paid
550
+	 * @throws EE_Error
551
+	 * @throws RuntimeException
552
+	 */
553
+	public function set_paid($REG_paid = 0.00)
554
+	{
555
+		$this->set('REG_paid', $REG_paid);
556
+	}
557
+
558
+
559
+	/**
560
+	 *        Attendee Is Going
561
+	 *
562
+	 * @param        boolean $REG_att_is_going Attendee Is Going
563
+	 * @throws EE_Error
564
+	 * @throws RuntimeException
565
+	 */
566
+	public function set_att_is_going($REG_att_is_going = false)
567
+	{
568
+		$this->set('REG_att_is_going', $REG_att_is_going);
569
+	}
570
+
571
+
572
+	/**
573
+	 * Gets the related attendee
574
+	 *
575
+	 * @return EE_Attendee
576
+	 * @throws EE_Error
577
+	 */
578
+	public function attendee()
579
+	{
580
+		return $this->get_first_related('Attendee');
581
+	}
582
+
583
+
584
+	/**
585
+	 *        get Event ID
586
+	 */
587
+	public function event_ID()
588
+	{
589
+		return $this->get('EVT_ID');
590
+	}
591
+
592
+
593
+	/**
594
+	 *        get Event ID
595
+	 */
596
+	public function event_name()
597
+	{
598
+		$event = $this->event_obj();
599
+		if ($event) {
600
+			return $event->name();
601
+		} else {
602
+			return null;
603
+		}
604
+	}
605
+
606
+
607
+	/**
608
+	 * Fetches the event this registration is for
609
+	 *
610
+	 * @return EE_Event
611
+	 * @throws EE_Error
612
+	 */
613
+	public function event_obj()
614
+	{
615
+		return $this->get_first_related('Event');
616
+	}
617
+
618
+
619
+	/**
620
+	 *        get Attendee ID
621
+	 */
622
+	public function attendee_ID()
623
+	{
624
+		return $this->get('ATT_ID');
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get PHP Session ID
630
+	 */
631
+	public function session_ID()
632
+	{
633
+		return $this->get('REG_session');
634
+	}
635
+
636
+
637
+	/**
638
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
639
+	 *
640
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
641
+	 * @return string
642
+	 */
643
+	public function receipt_url($messenger = 'html')
644
+	{
645
+
646
+		/**
647
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
648
+		 * already in use on old system.  If there is then we just return the standard url for it.
649
+		 *
650
+		 * @since 4.5.0
651
+		 */
652
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
653
+		$has_custom             = EEH_Template::locate_template(
654
+			$template_relative_path,
655
+			array(),
656
+			true,
657
+			true,
658
+			true
659
+		);
660
+
661
+		if ($has_custom) {
662
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
663
+		}
664
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
665
+	}
666
+
667
+
668
+	/**
669
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
670
+	 *
671
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
672
+	 * @return string
673
+	 * @throws EE_Error
674
+	 */
675
+	public function invoice_url($messenger = 'html')
676
+	{
677
+		/**
678
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
679
+		 * already in use on old system.  If there is then we just return the standard url for it.
680
+		 *
681
+		 * @since 4.5.0
682
+		 */
683
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
684
+		$has_custom             = EEH_Template::locate_template(
685
+			$template_relative_path,
686
+			array(),
687
+			true,
688
+			true,
689
+			true
690
+		);
691
+
692
+		if ($has_custom) {
693
+			if ($messenger == 'html') {
694
+				return $this->invoice_url('launch');
695
+			}
696
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
697
+
698
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
699
+			if ($messenger == 'html') {
700
+				$query_args['html'] = true;
701
+			}
702
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
703
+		}
704
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
705
+	}
706
+
707
+
708
+	/**
709
+	 * get Registration URL Link
710
+	 *
711
+	 * @access public
712
+	 * @return string
713
+	 * @throws \EE_Error
714
+	 */
715
+	public function reg_url_link()
716
+	{
717
+		return (string) $this->get('REG_url_link');
718
+	}
719
+
720
+
721
+	/**
722
+	 * Echoes out invoice_url()
723
+	 *
724
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
725
+	 * @return void
726
+	 * @throws EE_Error
727
+	 */
728
+	public function e_invoice_url($type = 'launch')
729
+	{
730
+		echo $this->invoice_url($type);
731
+	}
732
+
733
+
734
+	/**
735
+	 * Echoes out payment_overview_url
736
+	 */
737
+	public function e_payment_overview_url()
738
+	{
739
+		echo $this->payment_overview_url();
740
+	}
741
+
742
+
743
+	/**
744
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
745
+	 * a query parameter
746
+	 *
747
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
748
+	 *                            payment overview url.
749
+	 * @return string
750
+	 * @throws EE_Error
751
+	 */
752
+	public function payment_overview_url($clear_session = false)
753
+	{
754
+		return add_query_arg(array(
755
+			'e_reg_url_link' => $this->reg_url_link(),
756
+			'step'           => 'payment_options',
757
+			'revisit'        => true,
758
+			'clear_session' => (bool) $clear_session
759
+		), EE_Registry::instance()->CFG->core->reg_page_url());
760
+	}
761
+
762
+
763
+	/**
764
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
765
+	 * a query parameter
766
+	 *
767
+	 * @return string
768
+	 * @throws EE_Error
769
+	 */
770
+	public function edit_attendee_information_url()
771
+	{
772
+		return add_query_arg(array(
773
+			'e_reg_url_link' => $this->reg_url_link(),
774
+			'step'           => 'attendee_information',
775
+			'revisit'        => true,
776
+		), EE_Registry::instance()->CFG->core->reg_page_url());
777
+	}
778
+
779
+
780
+	/**
781
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
782
+	 *
783
+	 * @return string
784
+	 * @throws EE_Error
785
+	 */
786
+	public function get_admin_edit_url()
787
+	{
788
+		return EEH_URL::add_query_args_and_nonce(array(
789
+			'page'    => 'espresso_registrations',
790
+			'action'  => 'view_registration',
791
+			'_REG_ID' => $this->ID(),
792
+		), admin_url('admin.php'));
793
+	}
794
+
795
+
796
+	/**
797
+	 *    is_primary_registrant?
798
+	 */
799
+	public function is_primary_registrant()
800
+	{
801
+		return $this->get('REG_count') == 1 ? true : false;
802
+	}
803
+
804
+
805
+	/**
806
+	 * This returns the primary registration object for this registration group (which may be this object).
807
+	 *
808
+	 * @return EE_Registration
809
+	 * @throws EE_Error
810
+	 */
811
+	public function get_primary_registration()
812
+	{
813
+		if ($this->is_primary_registrant()) {
814
+			return $this;
815
+		}
816
+
817
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
818
+		/** @var EE_Registration $primary_registrant */
819
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
820
+			array(
821
+				'TXN_ID'    => $this->transaction_ID(),
822
+				'REG_count' => 1,
823
+			),
824
+		));
825
+		return $primary_registrant;
826
+	}
827
+
828
+
829
+	/**
830
+	 *        get  Attendee Number
831
+	 *
832
+	 * @access        public
833
+	 */
834
+	public function count()
835
+	{
836
+		return $this->get('REG_count');
837
+	}
838
+
839
+
840
+	/**
841
+	 *        get Group Size
842
+	 */
843
+	public function group_size()
844
+	{
845
+		return $this->get('REG_group_size');
846
+	}
847
+
848
+
849
+	/**
850
+	 *        get Registration Date
851
+	 */
852
+	public function date()
853
+	{
854
+		return $this->get('REG_date');
855
+	}
856
+
857
+
858
+	/**
859
+	 * gets a pretty date
860
+	 *
861
+	 * @param string $date_format
862
+	 * @param string $time_format
863
+	 * @return string
864
+	 * @throws EE_Error
865
+	 */
866
+	public function pretty_date($date_format = null, $time_format = null)
867
+	{
868
+		return $this->get_datetime('REG_date', $date_format, $time_format);
869
+	}
870
+
871
+
872
+	/**
873
+	 * final_price
874
+	 * the registration's share of the transaction total, so that the
875
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
876
+	 *
877
+	 * @return float
878
+	 * @throws EE_Error
879
+	 */
880
+	public function final_price()
881
+	{
882
+		return $this->get('REG_final_price');
883
+	}
884
+
885
+
886
+	/**
887
+	 * pretty_final_price
888
+	 *  final price as formatted string, with correct decimal places and currency symbol
889
+	 *
890
+	 * @return string
891
+	 * @throws EE_Error
892
+	 */
893
+	public function pretty_final_price()
894
+	{
895
+		return $this->get_pretty('REG_final_price');
896
+	}
897
+
898
+
899
+	/**
900
+	 * get paid (yeah)
901
+	 *
902
+	 * @return float
903
+	 * @throws EE_Error
904
+	 */
905
+	public function paid()
906
+	{
907
+		return $this->get('REG_paid');
908
+	}
909
+
910
+
911
+	/**
912
+	 * pretty_paid
913
+	 *
914
+	 * @return float
915
+	 * @throws EE_Error
916
+	 */
917
+	public function pretty_paid()
918
+	{
919
+		return $this->get_pretty('REG_paid');
920
+	}
921
+
922
+
923
+	/**
924
+	 * owes_monies_and_can_pay
925
+	 * whether or not this registration has monies owing and it's' status allows payment
926
+	 *
927
+	 * @param array $requires_payment
928
+	 * @return bool
929
+	 * @throws EE_Error
930
+	 */
931
+	public function owes_monies_and_can_pay($requires_payment = array())
932
+	{
933
+		// these reg statuses require payment (if event is not free)
934
+		$requires_payment = ! empty($requires_payment)
935
+			? $requires_payment
936
+			: EEM_Registration::reg_statuses_that_allow_payment();
937
+		if (in_array($this->status_ID(), $requires_payment) &&
938
+			$this->final_price() != 0 &&
939
+			$this->final_price() != $this->paid()
940
+		) {
941
+			return true;
942
+		} else {
943
+			return false;
944
+		}
945
+	}
946
+
947
+
948
+	/**
949
+	 * Prints out the return value of $this->pretty_status()
950
+	 *
951
+	 * @param bool $show_icons
952
+	 * @return void
953
+	 * @throws EE_Error
954
+	 */
955
+	public function e_pretty_status($show_icons = false)
956
+	{
957
+		echo $this->pretty_status($show_icons);
958
+	}
959
+
960
+
961
+	/**
962
+	 * Returns a nice version of the status for displaying to customers
963
+	 *
964
+	 * @param bool $show_icons
965
+	 * @return string
966
+	 * @throws EE_Error
967
+	 */
968
+	public function pretty_status($show_icons = false)
969
+	{
970
+		$status = EEM_Status::instance()->localized_status(
971
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
972
+			false,
973
+			'sentence'
974
+		);
975
+		$icon   = '';
976
+		switch ($this->status_ID()) {
977
+			case EEM_Registration::status_id_approved:
978
+				$icon = $show_icons
979
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
980
+					: '';
981
+				break;
982
+			case EEM_Registration::status_id_pending_payment:
983
+				$icon = $show_icons
984
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
985
+					: '';
986
+				break;
987
+			case EEM_Registration::status_id_not_approved:
988
+				$icon = $show_icons
989
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
990
+					: '';
991
+				break;
992
+			case EEM_Registration::status_id_cancelled:
993
+				$icon = $show_icons
994
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
995
+					: '';
996
+				break;
997
+			case EEM_Registration::status_id_incomplete:
998
+				$icon = $show_icons
999
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1000
+					: '';
1001
+				break;
1002
+			case EEM_Registration::status_id_declined:
1003
+				$icon = $show_icons
1004
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1005
+					: '';
1006
+				break;
1007
+			case EEM_Registration::status_id_wait_list:
1008
+				$icon = $show_icons
1009
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1010
+					: '';
1011
+				break;
1012
+		}
1013
+		return $icon . $status[$this->status_ID()];
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 *        get Attendee Is Going
1019
+	 */
1020
+	public function att_is_going()
1021
+	{
1022
+		return $this->get('REG_att_is_going');
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Gets related answers
1028
+	 *
1029
+	 * @param array $query_params like EEM_Base::get_all
1030
+	 * @return EE_Answer[]
1031
+	 * @throws EE_Error
1032
+	 */
1033
+	public function answers($query_params = null)
1034
+	{
1035
+		return $this->get_many_related('Answer', $query_params);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Gets the registration's answer value to the specified question
1041
+	 * (either the question's ID or a question object)
1042
+	 *
1043
+	 * @param EE_Question|int $question
1044
+	 * @param bool            $pretty_value
1045
+	 * @return array|string if pretty_value= true, the result will always be a string
1046
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1047
+	 * will convert it into some kind of string)
1048
+	 * @throws EE_Error
1049
+	 */
1050
+	public function answer_value_to_question($question, $pretty_value = true)
1051
+	{
1052
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1053
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 * question_groups
1059
+	 * returns an array of EE_Question_Group objects for this registration
1060
+	 *
1061
+	 * @return EE_Question_Group[]
1062
+	 * @throws EE_Error
1063
+	 * @throws EntityNotFoundException
1064
+	 */
1065
+	public function question_groups()
1066
+	{
1067
+		$question_groups = array();
1068
+		if ($this->event() instanceof EE_Event) {
1069
+			$question_groups = $this->event()->question_groups(
1070
+				array(
1071
+					array(
1072
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1073
+					),
1074
+					'order_by' => array('QSG_order' => 'ASC'),
1075
+				)
1076
+			);
1077
+		}
1078
+		return $question_groups;
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * count_question_groups
1084
+	 * returns a count of the number of EE_Question_Group objects for this registration
1085
+	 *
1086
+	 * @return int
1087
+	 * @throws EE_Error
1088
+	 * @throws EntityNotFoundException
1089
+	 */
1090
+	public function count_question_groups()
1091
+	{
1092
+		$qg_count = 0;
1093
+		if ($this->event() instanceof EE_Event) {
1094
+			$qg_count = $this->event()->count_related(
1095
+				'Question_Group',
1096
+				array(
1097
+					array(
1098
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1099
+					),
1100
+				)
1101
+			);
1102
+		}
1103
+		return $qg_count;
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * Returns the registration date in the 'standard' string format
1109
+	 * (function may be improved in the future to allow for different formats and timezones)
1110
+	 *
1111
+	 * @return string
1112
+	 * @throws EE_Error
1113
+	 */
1114
+	public function reg_date()
1115
+	{
1116
+		return $this->get_datetime('REG_date');
1117
+	}
1118
+
1119
+
1120
+	/**
1121
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1122
+	 * the ticket this registration purchased, or the datetime they have registered
1123
+	 * to attend)
1124
+	 *
1125
+	 * @return EE_Datetime_Ticket
1126
+	 * @throws EE_Error
1127
+	 */
1128
+	public function datetime_ticket()
1129
+	{
1130
+		return $this->get_first_related('Datetime_Ticket');
1131
+	}
1132
+
1133
+
1134
+	/**
1135
+	 * Sets the registration's datetime_ticket.
1136
+	 *
1137
+	 * @param EE_Datetime_Ticket $datetime_ticket
1138
+	 * @return EE_Datetime_Ticket
1139
+	 * @throws EE_Error
1140
+	 */
1141
+	public function set_datetime_ticket($datetime_ticket)
1142
+	{
1143
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1144
+	}
1145
+
1146
+	/**
1147
+	 * Gets deleted
1148
+	 *
1149
+	 * @return bool
1150
+	 * @throws EE_Error
1151
+	 */
1152
+	public function deleted()
1153
+	{
1154
+		return $this->get('REG_deleted');
1155
+	}
1156
+
1157
+	/**
1158
+	 * Sets deleted
1159
+	 *
1160
+	 * @param boolean $deleted
1161
+	 * @return bool
1162
+	 * @throws EE_Error
1163
+	 * @throws RuntimeException
1164
+	 */
1165
+	public function set_deleted($deleted)
1166
+	{
1167
+		if ($deleted) {
1168
+			$this->delete();
1169
+		} else {
1170
+			$this->restore();
1171
+		}
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * Get the status object of this object
1177
+	 *
1178
+	 * @return EE_Status
1179
+	 * @throws EE_Error
1180
+	 */
1181
+	public function status_obj()
1182
+	{
1183
+		return $this->get_first_related('Status');
1184
+	}
1185
+
1186
+
1187
+	/**
1188
+	 * Returns the number of times this registration has checked into any of the datetimes
1189
+	 * its available for
1190
+	 *
1191
+	 * @return int
1192
+	 * @throws EE_Error
1193
+	 */
1194
+	public function count_checkins()
1195
+	{
1196
+		return $this->get_model()->count_related($this, 'Checkin');
1197
+	}
1198
+
1199
+
1200
+	/**
1201
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1202
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1203
+	 *
1204
+	 * @return int
1205
+	 * @throws EE_Error
1206
+	 */
1207
+	public function count_checkins_not_checkedout()
1208
+	{
1209
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1215
+	 *
1216
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1217
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1218
+	 *                                          consider registration status as well as datetime access.
1219
+	 * @return bool
1220
+	 * @throws EE_Error
1221
+	 */
1222
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1223
+	{
1224
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1225
+
1226
+		//first check registration status
1227
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1228
+			return false;
1229
+		}
1230
+		//is there a datetime ticket that matches this dtt_ID?
1231
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1232
+			array(
1233
+				'TKT_ID' => $this->get('TKT_ID'),
1234
+				'DTT_ID' => $DTT_ID,
1235
+			),
1236
+		)))
1237
+		) {
1238
+			return false;
1239
+		}
1240
+
1241
+		//final check is against TKT_uses
1242
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1248
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1249
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1250
+	 * then return false.  Otherwise return true.
1251
+	 *
1252
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1253
+	 * @return bool true means can checkin.  false means cannot checkin.
1254
+	 * @throws EE_Error
1255
+	 */
1256
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1257
+	{
1258
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1259
+
1260
+		if (! $DTT_ID) {
1261
+			return false;
1262
+		}
1263
+
1264
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1265
+
1266
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1267
+		// check-in or not.
1268
+		if (! $max_uses || $max_uses === EE_INF) {
1269
+			return true;
1270
+		}
1271
+
1272
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1273
+		//go ahead and toggle.
1274
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1275
+			return true;
1276
+		}
1277
+
1278
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1279
+		//disallows further check-ins.
1280
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1281
+			array(
1282
+				'REG_ID' => $this->ID(),
1283
+				'CHK_in' => true,
1284
+			),
1285
+		), 'DTT_ID', true);
1286
+		// checkins have already reached their max number of uses
1287
+		// so registrant can NOT checkin
1288
+		if ($count_unique_dtt_checkins >= $max_uses) {
1289
+			EE_Error::add_error(
1290
+				esc_html__(
1291
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1292
+					'event_espresso'
1293
+				),
1294
+				__FILE__,
1295
+				__FUNCTION__,
1296
+				__LINE__
1297
+			);
1298
+			return false;
1299
+		}
1300
+		return true;
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * toggle Check-in status for this registration
1306
+	 * Check-ins are toggled in the following order:
1307
+	 * never checked in -> checked in
1308
+	 * checked in -> checked out
1309
+	 * checked out -> checked in
1310
+	 *
1311
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1312
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1313
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1314
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1315
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1319
+	{
1320
+		if (empty($DTT_ID)) {
1321
+			$datetime = $this->get_latest_related_datetime();
1322
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1323
+			// verify the registration can checkin for the given DTT_ID
1324
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1325
+			EE_Error::add_error(
1326
+				sprintf(
1327
+					esc_html__(
1328
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1329
+						'event_espresso'
1330
+					),
1331
+					$this->ID(),
1332
+					$DTT_ID
1333
+				),
1334
+				__FILE__,
1335
+				__FUNCTION__,
1336
+				__LINE__
1337
+			);
1338
+			return false;
1339
+		}
1340
+		$status_paths = array(
1341
+			EE_Registration::checkin_status_never => EE_Registration::checkin_status_in,
1342
+			EE_Registration::checkin_status_in    => EE_Registration::checkin_status_out,
1343
+			EE_Registration::checkin_status_out   => EE_Registration::checkin_status_in,
1344
+		);
1345
+		//start by getting the current status so we know what status we'll be changing to.
1346
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1347
+		$status_to  = $status_paths[$cur_status];
1348
+		// database only records true for checked IN or false for checked OUT
1349
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1350
+		$new_status = $status_to === EE_Registration::checkin_status_in ? true : false;
1351
+		// add relation - note Check-ins are always creating new rows
1352
+		// because we are keeping track of Check-ins over time.
1353
+		// Eventually we'll probably want to show a list table
1354
+		// for the individual Check-ins so that they can be managed.
1355
+		$checkin = EE_Checkin::new_instance(array(
1356
+			'REG_ID' => $this->ID(),
1357
+			'DTT_ID' => $DTT_ID,
1358
+			'CHK_in' => $new_status,
1359
+		));
1360
+		// if the record could not be saved then return false
1361
+		if ($checkin->save() === 0) {
1362
+			if (WP_DEBUG) {
1363
+				global $wpdb;
1364
+				$error = sprintf(
1365
+					esc_html__(
1366
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1367
+						'event_espresso'
1368
+					),
1369
+					'<br />',
1370
+					$wpdb->last_error
1371
+				);
1372
+			} else {
1373
+				$error = esc_html__(
1374
+					'Registration check in update failed because of an unknown database error',
1375
+					'event_espresso'
1376
+				);
1377
+			}
1378
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1379
+			return false;
1380
+		}
1381
+		return $status_to;
1382
+	}
1383
+
1384
+
1385
+	/**
1386
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1387
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1388
+	 *
1389
+	 * @return EE_Datetime|null
1390
+	 * @throws \EE_Error
1391
+	 */
1392
+	public function get_latest_related_datetime()
1393
+	{
1394
+		return EEM_Datetime::instance()->get_one(
1395
+			array(
1396
+				array(
1397
+					'Ticket.Registration.REG_ID' => $this->ID(),
1398
+				),
1399
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1400
+			)
1401
+		);
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1407
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1408
+	 *
1409
+	 * @throws \EE_Error
1410
+	 */
1411
+	public function get_earliest_related_datetime()
1412
+	{
1413
+		return EEM_Datetime::instance()->get_one(
1414
+			array(
1415
+				array(
1416
+					'Ticket.Registration.REG_ID' => $this->ID(),
1417
+				),
1418
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1419
+			)
1420
+		);
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * This method simply returns the check-in status for this registration and the given datetime.
1426
+	 * If neither the datetime nor the checkin values are provided as arguments,
1427
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1428
+	 *
1429
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1430
+	 *                            (if empty we'll get the primary datetime for
1431
+	 *                            this registration (via event) and use it's ID);
1432
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1433
+	 * @return int                Integer representing Check-in status.
1434
+	 * @throws \EE_Error
1435
+	 */
1436
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1437
+	{
1438
+		$checkin_query_params = array(
1439
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1440
+		);
1441
+
1442
+		if ($DTT_ID > 0) {
1443
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1444
+		}
1445
+
1446
+		//get checkin object (if exists)
1447
+		$checkin = $checkin instanceof EE_Checkin
1448
+			? $checkin
1449
+			: $this->get_first_related('Checkin', $checkin_query_params);
1450
+		if ($checkin instanceof EE_Checkin) {
1451
+			if ($checkin->get('CHK_in')) {
1452
+				return EE_Registration::checkin_status_in; //checked in
1453
+			}
1454
+			return EE_Registration::checkin_status_out; //had checked in but is now checked out.
1455
+		}
1456
+		return EE_Registration::checkin_status_never; //never been checked in
1457
+	}
1458
+
1459
+
1460
+	/**
1461
+	 * This method returns a localized message for the toggled Check-in message.
1462
+	 *
1463
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1464
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1465
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1466
+	 *                     message can be customized with the attendee name.
1467
+	 * @return string internationalized message
1468
+	 * @throws EE_Error
1469
+	 */
1470
+	public function get_checkin_msg($DTT_ID, $error = false)
1471
+	{
1472
+		//let's get the attendee first so we can include the name of the attendee
1473
+		$attendee = $this->get_first_related('Attendee');
1474
+		if ($attendee instanceof EE_Attendee) {
1475
+			if ($error) {
1476
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1477
+			}
1478
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1479
+			//what is the status message going to be?
1480
+			switch ($cur_status) {
1481
+				case EE_Registration::checkin_status_never:
1482
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1483
+						$attendee->full_name());
1484
+					break;
1485
+				case EE_Registration::checkin_status_in:
1486
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1487
+					break;
1488
+				case EE_Registration::checkin_status_out:
1489
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1490
+					break;
1491
+			}
1492
+		}
1493
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1494
+	}
1495
+
1496
+
1497
+	/**
1498
+	 * Returns the related EE_Transaction to this registration
1499
+	 *
1500
+	 * @return EE_Transaction
1501
+	 * @throws EE_Error
1502
+	 * @throws EntityNotFoundException
1503
+	 */
1504
+	public function transaction()
1505
+	{
1506
+		$transaction = $this->get_first_related('Transaction');
1507
+		if (! $transaction instanceof \EE_Transaction) {
1508
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1509
+		}
1510
+		return $transaction;
1511
+	}
1512
+
1513
+
1514
+	/**
1515
+	 *        get Registration Code
1516
+	 */
1517
+	public function reg_code()
1518
+	{
1519
+		return $this->get('REG_code');
1520
+	}
1521
+
1522
+
1523
+	/**
1524
+	 *        get Transaction ID
1525
+	 */
1526
+	public function transaction_ID()
1527
+	{
1528
+		return $this->get('TXN_ID');
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * @return int
1534
+	 * @throws EE_Error
1535
+	 */
1536
+	public function ticket_ID()
1537
+	{
1538
+		return $this->get('TKT_ID');
1539
+	}
1540
+
1541
+
1542
+	/**
1543
+	 *        Set Registration Code
1544
+	 *
1545
+	 * @access    public
1546
+	 * @param    string  $REG_code Registration Code
1547
+	 * @param    boolean $use_default
1548
+	 * @throws EE_Error
1549
+	 */
1550
+	public function set_reg_code($REG_code, $use_default = false)
1551
+	{
1552
+		if (empty($REG_code)) {
1553
+			EE_Error::add_error(
1554
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1555
+				__FILE__,
1556
+				__FUNCTION__,
1557
+				__LINE__
1558
+			);
1559
+			return;
1560
+		}
1561
+		if (! $this->reg_code()) {
1562
+			parent::set('REG_code', $REG_code, $use_default);
1563
+		} else {
1564
+			EE_Error::doing_it_wrong(
1565
+				__CLASS__ . '::' . __FUNCTION__,
1566
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1567
+				'4.6.0'
1568
+			);
1569
+		}
1570
+	}
1571
+
1572
+
1573
+	/**
1574
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1575
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1576
+	 *    $registration->transaction()->registrations();
1577
+	 *
1578
+	 * @since 4.5.0
1579
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1580
+	 * @throws EE_Error
1581
+	 */
1582
+	public function get_all_other_registrations_in_group()
1583
+	{
1584
+		if ($this->group_size() < 2) {
1585
+			return array();
1586
+		}
1587
+
1588
+		$query[0] = array(
1589
+			'TXN_ID' => $this->transaction_ID(),
1590
+			'REG_ID' => array('!=', $this->ID()),
1591
+			'TKT_ID' => $this->ticket_ID(),
1592
+		);
1593
+		/** @var EE_Registration[] $registrations */
1594
+		$registrations = $this->get_model()->get_all($query);
1595
+		return $registrations;
1596
+	}
1597
+
1598
+	/**
1599
+	 * Return the link to the admin details for the object.
1600
+	 *
1601
+	 * @return string
1602
+	 * @throws EE_Error
1603
+	 */
1604
+	public function get_admin_details_link()
1605
+	{
1606
+		EE_Registry::instance()->load_helper('URL');
1607
+		return EEH_URL::add_query_args_and_nonce(
1608
+			array(
1609
+				'page'    => 'espresso_registrations',
1610
+				'action'  => 'view_registration',
1611
+				'_REG_ID' => $this->ID(),
1612
+			),
1613
+			admin_url('admin.php')
1614
+		);
1615
+	}
1616
+
1617
+	/**
1618
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1619
+	 *
1620
+	 * @return string
1621
+	 * @throws EE_Error
1622
+	 */
1623
+	public function get_admin_edit_link()
1624
+	{
1625
+		return $this->get_admin_details_link();
1626
+	}
1627
+
1628
+	/**
1629
+	 * Returns the link to a settings page for the object.
1630
+	 *
1631
+	 * @return string
1632
+	 * @throws EE_Error
1633
+	 */
1634
+	public function get_admin_settings_link()
1635
+	{
1636
+		return $this->get_admin_details_link();
1637
+	}
1638
+
1639
+	/**
1640
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1641
+	 *
1642
+	 * @return string
1643
+	 */
1644
+	public function get_admin_overview_link()
1645
+	{
1646
+		EE_Registry::instance()->load_helper('URL');
1647
+		return EEH_URL::add_query_args_and_nonce(
1648
+			array(
1649
+				'page' => 'espresso_registrations',
1650
+			),
1651
+			admin_url('admin.php')
1652
+		);
1653
+	}
1654
+
1655
+
1656
+	/**
1657
+	 * @param array $query_params
1658
+	 * @return \EE_Registration[]
1659
+	 * @throws \EE_Error
1660
+	 */
1661
+	public function payments($query_params = array())
1662
+	{
1663
+		return $this->get_many_related('Payment', $query_params);
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 * @param array $query_params
1669
+	 * @return \EE_Registration_Payment[]
1670
+	 * @throws \EE_Error
1671
+	 */
1672
+	public function registration_payments($query_params = array())
1673
+	{
1674
+		return $this->get_many_related('Registration_Payment', $query_params);
1675
+	}
1676
+
1677
+
1678
+	/**
1679
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1680
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1681
+	 *
1682
+	 * @return EE_Payment_Method|null
1683
+	 */
1684
+	public function payment_method()
1685
+	{
1686
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1687
+	}
1688
+
1689
+
1690
+	/**
1691
+	 * @return \EE_Line_Item
1692
+	 * @throws EntityNotFoundException
1693
+	 * @throws \EE_Error
1694
+	 */
1695
+	public function ticket_line_item()
1696
+	{
1697
+		$ticket            = $this->ticket();
1698
+		$transaction       = $this->transaction();
1699
+		$line_item         = null;
1700
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1701
+			$transaction->total_line_item(),
1702
+			'Ticket',
1703
+			array($ticket->ID())
1704
+		);
1705
+		foreach ($ticket_line_items as $ticket_line_item) {
1706
+			if (
1707
+				$ticket_line_item instanceof \EE_Line_Item
1708
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1709
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1710
+			) {
1711
+				$line_item = $ticket_line_item;
1712
+				break;
1713
+			}
1714
+		}
1715
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1716
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1717
+		}
1718
+		return $line_item;
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * Soft Deletes this model object.
1724
+	 *
1725
+	 * @return boolean | int
1726
+	 * @throws \RuntimeException
1727
+	 * @throws \EE_Error
1728
+	 */
1729
+	public function delete()
1730
+	{
1731
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1732
+			$this->set_status(EEM_Registration::status_id_cancelled);
1733
+		}
1734
+		return parent::delete();
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1740
+	 *
1741
+	 * @throws \EE_Error
1742
+	 * @throws \RuntimeException
1743
+	 */
1744
+	public function restore()
1745
+	{
1746
+		$previous_status = $this->get_extra_meta(
1747
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1748
+			true,
1749
+			EEM_Registration::status_id_cancelled
1750
+		);
1751
+		if ($previous_status) {
1752
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1753
+			$this->set_status($previous_status);
1754
+		}
1755
+		return parent::restore();
1756
+	}
1757
+
1758
+
1759
+
1760
+	/*************************** DEPRECATED ***************************/
1761
+
1762
+
1763
+	/**
1764
+	 * @deprecated
1765
+	 * @since     4.7.0
1766
+	 * @access    public
1767
+	 */
1768
+	public function price_paid()
1769
+	{
1770
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1771
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1772
+			'4.7.0');
1773
+		return $this->final_price();
1774
+	}
1775
+
1776
+
1777
+	/**
1778
+	 * @deprecated
1779
+	 * @since     4.7.0
1780
+	 * @access    public
1781
+	 * @param    float $REG_final_price
1782
+	 * @throws EE_Error
1783
+	 * @throws RuntimeException
1784
+	 */
1785
+	public function set_price_paid($REG_final_price = 0.00)
1786
+	{
1787
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1788
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1789
+			'4.7.0');
1790
+		$this->set_final_price($REG_final_price);
1791
+	}
1792
+
1793
+
1794
+	/**
1795
+	 * @deprecated
1796
+	 * @since 4.7.0
1797
+	 * @return string
1798
+	 * @throws EE_Error
1799
+	 */
1800
+	public function pretty_price_paid()
1801
+	{
1802
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1803
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1804
+				'event_espresso'), '4.7.0');
1805
+		return $this->pretty_final_price();
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1811
+	 *
1812
+	 * @deprecated 4.9.17
1813
+	 * @return EE_Datetime
1814
+	 * @throws EE_Error
1815
+	 * @throws EntityNotFoundException
1816
+	 */
1817
+	public function get_related_primary_datetime()
1818
+	{
1819
+		EE_Error::doing_it_wrong(
1820
+			__METHOD__,
1821
+			esc_html__(
1822
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1823
+				'event_espresso'
1824
+			),
1825
+			'4.9.17',
1826
+			'5.0.0'
1827
+		);
1828
+		return $this->event()->primary_datetime();
1829
+	}
1830 1830
 
1831 1831
 
1832 1832
 }
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1856 added lines, -1856 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\exceptions\InvalidEntityException;
6 6
 
7 7
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
8
-    exit('No direct script access allowed');
8
+	exit('No direct script access allowed');
9 9
 }
10 10
 
11 11
 
@@ -20,1861 +20,1861 @@  discard block
 block discarded – undo
20 20
 class EED_Single_Page_Checkout extends EED_Module
21 21
 {
22 22
 
23
-    /**
24
-     * $_initialized - has the SPCO controller already been initialized ?
25
-     *
26
-     * @access private
27
-     * @var bool $_initialized
28
-     */
29
-    private static $_initialized = false;
30
-
31
-
32
-    /**
33
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
-     *
35
-     * @access private
36
-     * @var bool $_valid_checkout
37
-     */
38
-    private static $_checkout_verified = true;
39
-
40
-    /**
41
-     *    $_reg_steps_array - holds initial array of reg steps
42
-     *
43
-     * @access private
44
-     * @var array $_reg_steps_array
45
-     */
46
-    private static $_reg_steps_array = array();
47
-
48
-    /**
49
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
-     *
51
-     * @access public
52
-     * @var EE_Checkout $checkout
53
-     */
54
-    public $checkout;
55
-
56
-
57
-
58
-    /**
59
-     * @return EED_Module|EED_Single_Page_Checkout
60
-     */
61
-    public static function instance()
62
-    {
63
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
-        return parent::get_instance(__CLASS__);
65
-    }
66
-
67
-
68
-
69
-    /**
70
-     * @return EE_CART
71
-     */
72
-    public function cart()
73
-    {
74
-        return $this->checkout->cart;
75
-    }
76
-
77
-
78
-
79
-    /**
80
-     * @return EE_Transaction
81
-     */
82
-    public function transaction()
83
-    {
84
-        return $this->checkout->transaction;
85
-    }
86
-
87
-
88
-
89
-    /**
90
-     *    set_hooks - for hooking into EE Core, other modules, etc
91
-     *
92
-     * @access    public
93
-     * @return    void
94
-     * @throws EE_Error
95
-     */
96
-    public static function set_hooks()
97
-    {
98
-        EED_Single_Page_Checkout::set_definitions();
99
-    }
100
-
101
-
102
-
103
-    /**
104
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
-     *
106
-     * @access    public
107
-     * @return    void
108
-     * @throws EE_Error
109
-     */
110
-    public static function set_hooks_admin()
111
-    {
112
-        EED_Single_Page_Checkout::set_definitions();
113
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
-            return;
115
-        }
116
-        // going to start an output buffer in case anything gets accidentally output
117
-        // that might disrupt our JSON response
118
-        ob_start();
119
-        EED_Single_Page_Checkout::load_request_handler();
120
-        EED_Single_Page_Checkout::load_reg_steps();
121
-        // set ajax hooks
122
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     *    process ajax request
134
-     *
135
-     * @param string $ajax_action
136
-     * @throws EE_Error
137
-     */
138
-    public static function process_ajax_request($ajax_action)
139
-    {
140
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
141
-        EED_Single_Page_Checkout::instance()->_initialize();
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     *    ajax display registration step
148
-     *
149
-     * @throws EE_Error
150
-     */
151
-    public static function display_reg_step()
152
-    {
153
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     *    ajax process registration step
160
-     *
161
-     * @throws EE_Error
162
-     */
163
-    public static function process_reg_step()
164
-    {
165
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
-    }
167
-
168
-
169
-
170
-    /**
171
-     *    ajax process registration step
172
-     *
173
-     * @throws EE_Error
174
-     */
175
-    public static function update_reg_step()
176
-    {
177
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
-    }
179
-
180
-
181
-
182
-    /**
183
-     *   update_checkout
184
-     *
185
-     * @access public
186
-     * @return void
187
-     * @throws EE_Error
188
-     */
189
-    public static function update_checkout()
190
-    {
191
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
-    }
193
-
194
-
195
-
196
-    /**
197
-     *    load_request_handler
198
-     *
199
-     * @access    public
200
-     * @return    void
201
-     */
202
-    public static function load_request_handler()
203
-    {
204
-        // load core Request_Handler class
205
-        if (EE_Registry::instance()->REQ !== null) {
206
-            EE_Registry::instance()->load_core('Request_Handler');
207
-        }
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     *    set_definitions
214
-     *
215
-     * @access    public
216
-     * @return    void
217
-     * @throws EE_Error
218
-     */
219
-    public static function set_definitions()
220
-    {
221
-        if(defined('SPCO_BASE_PATH')) {
222
-            return;
223
-        }
224
-        define(
225
-            'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
-        );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236
-            __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
237
-                'event_espresso'),
238
-            '<h4 class="important-notice">',
239
-            '</h4>',
240
-            '<br />',
241
-            '<p>',
242
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
243
-            '">',
244
-            '</a>',
245
-            '</p>'
246
-        );
247
-    }
248
-
249
-
250
-
251
-    /**
252
-     * load_reg_steps
253
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
254
-     *
255
-     * @access    private
256
-     * @throws EE_Error
257
-     */
258
-    public static function load_reg_steps()
259
-    {
260
-        static $reg_steps_loaded = false;
261
-        if ($reg_steps_loaded) {
262
-            return;
263
-        }
264
-        // filter list of reg_steps
265
-        $reg_steps_to_load = (array)apply_filters(
266
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267
-            EED_Single_Page_Checkout::get_reg_steps()
268
-        );
269
-        // sort by key (order)
270
-        ksort($reg_steps_to_load);
271
-        // loop through folders
272
-        foreach ($reg_steps_to_load as $order => $reg_step) {
273
-            // we need a
274
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
275
-                // copy over to the reg_steps_array
276
-                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
277
-                // register custom key route for each reg step
278
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
279
-                EE_Config::register_route(
280
-                    $reg_step['slug'],
281
-                    'EED_Single_Page_Checkout',
282
-                    'run',
283
-                    'step'
284
-                );
285
-                // add AJAX or other hooks
286
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
287
-                    // setup autoloaders if necessary
288
-                    if ( ! class_exists($reg_step['class_name'])) {
289
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
290
-                            $reg_step['file_path'],
291
-                            true
292
-                        );
293
-                    }
294
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
295
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
296
-                    }
297
-                }
298
-            }
299
-        }
300
-        $reg_steps_loaded = true;
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     *    get_reg_steps
307
-     *
308
-     * @access    public
309
-     * @return    array
310
-     */
311
-    public static function get_reg_steps()
312
-    {
313
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
314
-        if (empty($reg_steps)) {
315
-            $reg_steps = array(
316
-                10  => array(
317
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
318
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319
-                    'slug'       => 'attendee_information',
320
-                    'has_hooks'  => false,
321
-                ),
322
-                20  => array(
323
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
324
-                    'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325
-                    'slug'       => 'registration_confirmation',
326
-                    'has_hooks'  => false,
327
-                ),
328
-                30  => array(
329
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
330
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331
-                    'slug'       => 'payment_options',
332
-                    'has_hooks'  => true,
333
-                ),
334
-                999 => array(
335
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
336
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337
-                    'slug'       => 'finalize_registration',
338
-                    'has_hooks'  => false,
339
-                ),
340
-            );
341
-        }
342
-        return $reg_steps;
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     *    registration_checkout_for_admin
349
-     *
350
-     * @access    public
351
-     * @return    string
352
-     * @throws EE_Error
353
-     */
354
-    public static function registration_checkout_for_admin()
355
-    {
356
-        EED_Single_Page_Checkout::load_request_handler();
357
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
358
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
359
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
360
-        EED_Single_Page_Checkout::instance()->_initialize();
361
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
362
-        return EE_Registry::instance()->REQ->get_output();
363
-    }
364
-
365
-
366
-
367
-    /**
368
-     * process_registration_from_admin
369
-     *
370
-     * @access public
371
-     * @return \EE_Transaction
372
-     * @throws EE_Error
373
-     */
374
-    public static function process_registration_from_admin()
375
-    {
376
-        EED_Single_Page_Checkout::load_request_handler();
377
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
378
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
379
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
380
-        EED_Single_Page_Checkout::instance()->_initialize();
381
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
382
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
383
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
384
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
385
-                if ($final_reg_step->process_reg_step()) {
386
-                    $final_reg_step->set_completed();
387
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
388
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
389
-                }
390
-            }
391
-        }
392
-        return null;
393
-    }
394
-
395
-
396
-
397
-    /**
398
-     *    run
399
-     *
400
-     * @access    public
401
-     * @param WP_Query $WP_Query
402
-     * @return    void
403
-     * @throws EE_Error
404
-     */
405
-    public function run($WP_Query)
406
-    {
407
-        if (
408
-            $WP_Query instanceof WP_Query
409
-            && $WP_Query->is_main_query()
410
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
411
-            && $this->_is_reg_checkout()
412
-        ) {
413
-            $this->_initialize();
414
-        }
415
-    }
416
-
417
-
418
-
419
-    /**
420
-     * determines whether current url matches reg page url
421
-     *
422
-     * @return bool
423
-     */
424
-    protected function _is_reg_checkout()
425
-    {
426
-        // get current permalink for reg page without any extra query args
427
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
428
-        // get request URI for current request, but without the scheme or host
429
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
430
-        $current_request_uri = html_entity_decode($current_request_uri);
431
-        // get array of query args from the current request URI
432
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
433
-        // grab page id if it is set
434
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
435
-        // and remove the page id from the query args (we will re-add it later)
436
-        unset($query_args['page_id']);
437
-        // now strip all query args from current request URI
438
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
439
-        // and re-add the page id if it was set
440
-        if ($page_id) {
441
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
442
-        }
443
-        // remove slashes and ?
444
-        $current_request_uri = trim($current_request_uri, '?/');
445
-        // is current request URI part of the known full reg page URL ?
446
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     * @param WP_Query $wp_query
453
-     * @return    void
454
-     * @throws EE_Error
455
-     */
456
-    public static function init($wp_query)
457
-    {
458
-        EED_Single_Page_Checkout::instance()->run($wp_query);
459
-    }
460
-
461
-
462
-
463
-    /**
464
-     *    _initialize - initial module setup
465
-     *
466
-     * @access    private
467
-     * @throws EE_Error
468
-     * @return    void
469
-     */
470
-    private function _initialize()
471
-    {
472
-        // ensure SPCO doesn't run twice
473
-        if (EED_Single_Page_Checkout::$_initialized) {
474
-            return;
475
-        }
476
-        try {
477
-            EED_Single_Page_Checkout::load_reg_steps();
478
-            $this->_verify_session();
479
-            // setup the EE_Checkout object
480
-            $this->checkout = $this->_initialize_checkout();
481
-            // filter checkout
482
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
483
-            // get the $_GET
484
-            $this->_get_request_vars();
485
-            if ($this->_block_bots()) {
486
-                return;
487
-            }
488
-            // filter continue_reg
489
-            $this->checkout->continue_reg = apply_filters(
490
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
491
-                true,
492
-                $this->checkout
493
-            );
494
-            // load the reg steps array
495
-            if ( ! $this->_load_and_instantiate_reg_steps()) {
496
-                EED_Single_Page_Checkout::$_initialized = true;
497
-                return;
498
-            }
499
-            // set the current step
500
-            $this->checkout->set_current_step($this->checkout->step);
501
-            // and the next step
502
-            $this->checkout->set_next_step();
503
-            // verify that everything has been setup correctly
504
-            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
505
-                EED_Single_Page_Checkout::$_initialized = true;
506
-                return;
507
-            }
508
-            // lock the transaction
509
-            $this->checkout->transaction->lock();
510
-            // make sure all of our cached objects are added to their respective model entity mappers
511
-            $this->checkout->refresh_all_entities();
512
-            // set amount owing
513
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
514
-            // initialize each reg step, which gives them the chance to potentially alter the process
515
-            $this->_initialize_reg_steps();
516
-            // DEBUG LOG
517
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518
-            // get reg form
519
-            if( ! $this->_check_form_submission()) {
520
-                EED_Single_Page_Checkout::$_initialized = true;
521
-                return;
522
-            }
523
-            // checkout the action!!!
524
-            $this->_process_form_action();
525
-            // add some style and make it dance
526
-            $this->add_styles_and_scripts();
527
-            // kk... SPCO has successfully run
528
-            EED_Single_Page_Checkout::$_initialized = true;
529
-            // set no cache headers and constants
530
-            EE_System::do_not_cache();
531
-            // add anchor
532
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
533
-            // remove transaction lock
534
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
535
-        } catch (Exception $e) {
536
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
537
-        }
538
-    }
539
-
540
-
541
-
542
-    /**
543
-     *    _verify_session
544
-     * checks that the session is valid and not expired
545
-     *
546
-     * @access    private
547
-     * @throws EE_Error
548
-     */
549
-    private function _verify_session()
550
-    {
551
-        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
552
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
553
-        }
554
-        $clear_session_requested = filter_var(
555
-            EE_Registry::instance()->REQ->get('clear_session', false),
556
-            FILTER_VALIDATE_BOOLEAN
557
-        );
558
-        // is session still valid ?
559
-        if ($clear_session_requested
560
-            || ( EE_Registry::instance()->SSN->expired()
561
-              && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562
-            )
563
-        ) {
564
-            $this->checkout = new EE_Checkout();
565
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
566
-            // EE_Registry::instance()->SSN->reset_cart();
567
-            // EE_Registry::instance()->SSN->reset_checkout();
568
-            // EE_Registry::instance()->SSN->reset_transaction();
569
-            if (! $clear_session_requested) {
570
-                EE_Error::add_attention(
571
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572
-                    __FILE__, __FUNCTION__, __LINE__
573
-                );
574
-            }
575
-            // EE_Registry::instance()->SSN->reset_expired();
576
-        }
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     *    _initialize_checkout
583
-     * loads and instantiates EE_Checkout
584
-     *
585
-     * @access    private
586
-     * @throws EE_Error
587
-     * @return EE_Checkout
588
-     */
589
-    private function _initialize_checkout()
590
-    {
591
-        // look in session for existing checkout
592
-        /** @type EE_Checkout $checkout */
593
-        $checkout = EE_Registry::instance()->SSN->checkout();
594
-        // verify
595
-        if ( ! $checkout instanceof EE_Checkout) {
596
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
597
-            $checkout = EE_Registry::instance()->load_file(
598
-                SPCO_INC_PATH,
599
-                'EE_Checkout',
600
-                'class', array(),
601
-                false
602
-            );
603
-        } else {
604
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
605
-                $this->unlock_transaction();
606
-                wp_safe_redirect($checkout->redirect_url);
607
-                exit();
608
-            }
609
-        }
610
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
611
-        // verify again
612
-        if ( ! $checkout instanceof EE_Checkout) {
613
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
614
-        }
615
-        // reset anything that needs a clean slate for each request
616
-        $checkout->reset_for_current_request();
617
-        return $checkout;
618
-    }
619
-
620
-
621
-
622
-    /**
623
-     *    _get_request_vars
624
-     *
625
-     * @access    private
626
-     * @return    void
627
-     * @throws EE_Error
628
-     */
629
-    private function _get_request_vars()
630
-    {
631
-        // load classes
632
-        EED_Single_Page_Checkout::load_request_handler();
633
-        //make sure this request is marked as belonging to EE
634
-        EE_Registry::instance()->REQ->set_espresso_page(true);
635
-        // which step is being requested ?
636
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
637
-        // which step is being edited ?
638
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
639
-        // and what we're doing on the current step
640
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
641
-        // timestamp
642
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
643
-        // returning to edit ?
644
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
645
-        // or some other kind of revisit ?
646
-        $this->checkout->revisit = filter_var(
647
-            EE_Registry::instance()->REQ->get('revisit', false),
648
-            FILTER_VALIDATE_BOOLEAN
649
-        );
650
-        // and whether or not to generate a reg form for this request
651
-        $this->checkout->generate_reg_form = filter_var(
652
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
653
-            FILTER_VALIDATE_BOOLEAN
654
-        );
655
-        // and whether or not to process a reg form submission for this request
656
-        $this->checkout->process_form_submission = filter_var(
657
-            EE_Registry::instance()->REQ->get(
658
-                'process_form_submission',
659
-                $this->checkout->action === 'process_reg_step'
660
-            ),
661
-            FILTER_VALIDATE_BOOLEAN
662
-        );
663
-        $this->checkout->process_form_submission = filter_var(
664
-            $this->checkout->action !== 'display_spco_reg_step'
665
-                ? $this->checkout->process_form_submission
666
-                : false,
667
-            FILTER_VALIDATE_BOOLEAN
668
-        );
669
-        // $this->_display_request_vars();
670
-    }
671
-
672
-
673
-
674
-    /**
675
-     *  _display_request_vars
676
-     *
677
-     * @access    protected
678
-     * @return    void
679
-     */
680
-    protected function _display_request_vars()
681
-    {
682
-        if ( ! WP_DEBUG) {
683
-            return;
684
-        }
685
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
686
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
687
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
688
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
689
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
690
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
691
-        EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
692
-        EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
693
-    }
694
-
695
-
696
-
697
-    /**
698
-     * _block_bots
699
-     * checks that the incoming request has either of the following set:
700
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
701
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
702
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
703
-     * then where you coming from man?
704
-     *
705
-     * @return boolean
706
-     */
707
-    private function _block_bots()
708
-    {
709
-        $invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
710
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
711
-            return true;
712
-        }
713
-        return false;
714
-    }
715
-
716
-
717
-
718
-    /**
719
-     *    _get_first_step
720
-     *  gets slug for first step in $_reg_steps_array
721
-     *
722
-     * @access    private
723
-     * @throws EE_Error
724
-     * @return    string
725
-     */
726
-    private function _get_first_step()
727
-    {
728
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
729
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
730
-    }
731
-
732
-
733
-
734
-    /**
735
-     *    _load_and_instantiate_reg_steps
736
-     *  instantiates each reg step based on the loaded reg_steps array
737
-     *
738
-     * @access    private
739
-     * @throws EE_Error
740
-     * @return    bool
741
-     */
742
-    private function _load_and_instantiate_reg_steps()
743
-    {
744
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
745
-        // have reg_steps already been instantiated ?
746
-        if (
747
-            empty($this->checkout->reg_steps)
748
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
749
-        ) {
750
-            // if not, then loop through raw reg steps array
751
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
752
-                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
753
-                    return false;
754
-                }
755
-            }
756
-            EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
757
-            EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
758
-            // skip the registration_confirmation page ?
759
-            if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
760
-                // just remove it from the reg steps array
761
-                $this->checkout->remove_reg_step('registration_confirmation', false);
762
-            } else if (
763
-                isset($this->checkout->reg_steps['registration_confirmation'])
764
-                && EE_Registry::instance()->CFG->registration->reg_confirmation_last
765
-            ) {
766
-                // set the order to something big like 100
767
-                $this->checkout->set_reg_step_order('registration_confirmation', 100);
768
-            }
769
-            // filter the array for good luck
770
-            $this->checkout->reg_steps = apply_filters(
771
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
772
-                $this->checkout->reg_steps
773
-            );
774
-            // finally re-sort based on the reg step class order properties
775
-            $this->checkout->sort_reg_steps();
776
-        } else {
777
-            foreach ($this->checkout->reg_steps as $reg_step) {
778
-                // set all current step stati to FALSE
779
-                $reg_step->set_is_current_step(false);
780
-            }
781
-        }
782
-        if (empty($this->checkout->reg_steps)) {
783
-            EE_Error::add_error(
784
-                __('No Reg Steps were loaded..', 'event_espresso'),
785
-                __FILE__, __FUNCTION__, __LINE__
786
-            );
787
-            return false;
788
-        }
789
-        // make reg step details available to JS
790
-        $this->checkout->set_reg_step_JSON_info();
791
-        return true;
792
-    }
793
-
794
-
795
-
796
-    /**
797
-     *     _load_and_instantiate_reg_step
798
-     *
799
-     * @access    private
800
-     * @param array $reg_step
801
-     * @param int   $order
802
-     * @return bool
803
-     */
804
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
805
-    {
806
-        // we need a file_path, class_name, and slug to add a reg step
807
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
808
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
809
-            if (
810
-                $this->checkout->reg_url_link
811
-                && $this->checkout->step !== $reg_step['slug']
812
-                && $reg_step['slug'] !== 'finalize_registration'
813
-                // normally at this point we would NOT load the reg step, but this filter can change that
814
-                && apply_filters(
815
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
816
-                    true,
817
-                    $reg_step,
818
-                    $this->checkout
819
-                )
820
-            ) {
821
-                return true;
822
-            }
823
-            // instantiate step class using file path and class name
824
-            $reg_step_obj = EE_Registry::instance()->load_file(
825
-                $reg_step['file_path'],
826
-                $reg_step['class_name'],
827
-                'class',
828
-                $this->checkout,
829
-                false
830
-            );
831
-            // did we gets the goods ?
832
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
833
-                // set reg step order based on config
834
-                $reg_step_obj->set_order($order);
835
-                // add instantiated reg step object to the master reg steps array
836
-                $this->checkout->add_reg_step($reg_step_obj);
837
-            } else {
838
-                EE_Error::add_error(
839
-                    __('The current step could not be set.', 'event_espresso'),
840
-                    __FILE__, __FUNCTION__, __LINE__
841
-                );
842
-                return false;
843
-            }
844
-        } else {
845
-            if (WP_DEBUG) {
846
-                EE_Error::add_error(
847
-                    sprintf(
848
-                        __(
849
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
850
-                            'event_espresso'
851
-                        ),
852
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
853
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
854
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
855
-                        '<ul>',
856
-                        '<li>',
857
-                        '</li>',
858
-                        '</ul>'
859
-                    ),
860
-                    __FILE__, __FUNCTION__, __LINE__
861
-                );
862
-            }
863
-            return false;
864
-        }
865
-        return true;
866
-    }
867
-
868
-
869
-    /**
870
-     * _verify_transaction_and_get_registrations
871
-     *
872
-     * @access private
873
-     * @return bool
874
-     * @throws InvalidDataTypeException
875
-     * @throws InvalidEntityException
876
-     * @throws EE_Error
877
-     */
878
-    private function _verify_transaction_and_get_registrations()
879
-    {
880
-        // was there already a valid transaction in the checkout from the session ?
881
-        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
882
-            // get transaction from db or session
883
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
884
-                ? $this->_get_transaction_and_cart_for_previous_visit()
885
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
886
-            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
887
-                EE_Error::add_error(
888
-                    __('Your Registration and Transaction information could not be retrieved from the db.',
889
-                        'event_espresso'),
890
-                    __FILE__, __FUNCTION__, __LINE__
891
-                );
892
-                $this->checkout->transaction = EE_Transaction::new_instance();
893
-                // add some style and make it dance
894
-                $this->add_styles_and_scripts();
895
-                EED_Single_Page_Checkout::$_initialized = true;
896
-                return false;
897
-            }
898
-            // and the registrations for the transaction
899
-            $this->_get_registrations($this->checkout->transaction);
900
-        }
901
-        return true;
902
-    }
903
-
904
-
905
-
906
-    /**
907
-     * _get_transaction_and_cart_for_previous_visit
908
-     *
909
-     * @access private
910
-     * @return mixed EE_Transaction|NULL
911
-     */
912
-    private function _get_transaction_and_cart_for_previous_visit()
913
-    {
914
-        /** @var $TXN_model EEM_Transaction */
915
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
916
-        // because the reg_url_link is present in the request,
917
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
918
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
919
-        // verify transaction
920
-        if ($transaction instanceof EE_Transaction) {
921
-            // and get the cart that was used for that transaction
922
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
923
-            return $transaction;
924
-        }
925
-        EE_Error::add_error(
926
-            __('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
927
-            __FILE__, __FUNCTION__, __LINE__
928
-        );
929
-        return null;
930
-
931
-    }
932
-
933
-
934
-
935
-    /**
936
-     * _get_cart_for_transaction
937
-     *
938
-     * @access private
939
-     * @param EE_Transaction $transaction
940
-     * @return EE_Cart
941
-     */
942
-    private function _get_cart_for_transaction($transaction)
943
-    {
944
-        return $this->checkout->get_cart_for_transaction($transaction);
945
-    }
946
-
947
-
948
-
949
-    /**
950
-     * get_cart_for_transaction
951
-     *
952
-     * @access public
953
-     * @param EE_Transaction $transaction
954
-     * @return EE_Cart
955
-     */
956
-    public function get_cart_for_transaction(EE_Transaction $transaction)
957
-    {
958
-        return $this->checkout->get_cart_for_transaction($transaction);
959
-    }
960
-
961
-
962
-
963
-    /**
964
-     * _get_transaction_and_cart_for_current_session
965
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
966
-     *
967
-     * @access private
968
-     * @return EE_Transaction
969
-     * @throws EE_Error
970
-     */
971
-    private function _get_cart_for_current_session_and_setup_new_transaction()
972
-    {
973
-        //  if there's no transaction, then this is the FIRST visit to SPCO
974
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
975
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
976
-        // and then create a new transaction
977
-        $transaction = $this->_initialize_transaction();
978
-        // verify transaction
979
-        if ($transaction instanceof EE_Transaction) {
980
-            // save it so that we have an ID for other objects to use
981
-            $transaction->save();
982
-            // and save TXN data to the cart
983
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
984
-        } else {
985
-            EE_Error::add_error(
986
-                __('A Valid Transaction could not be initialized.', 'event_espresso'),
987
-                __FILE__, __FUNCTION__, __LINE__
988
-            );
989
-        }
990
-        return $transaction;
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
997
-     *
998
-     * @access private
999
-     * @return mixed EE_Transaction|NULL
1000
-     */
1001
-    private function _initialize_transaction()
1002
-    {
1003
-        try {
1004
-            // ensure cart totals have been calculated
1005
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
1006
-            // grab the cart grand total
1007
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
1008
-            // create new TXN
1009
-            $transaction = EE_Transaction::new_instance(
1010
-                array(
1011
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1012
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1013
-                    'TXN_paid'      => 0,
1014
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
1015
-                )
1016
-            );
1017
-            // save it so that we have an ID for other objects to use
1018
-            $transaction->save();
1019
-            // set cron job for following up on TXNs after their session has expired
1020
-            EE_Cron_Tasks::schedule_expired_transaction_check(
1021
-                EE_Registry::instance()->SSN->expiration() + 1,
1022
-                $transaction->ID()
1023
-            );
1024
-            return $transaction;
1025
-        } catch (Exception $e) {
1026
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1027
-        }
1028
-        return null;
1029
-    }
1030
-
1031
-
1032
-    /**
1033
-     * _get_registrations
1034
-     *
1035
-     * @access private
1036
-     * @param EE_Transaction $transaction
1037
-     * @return void
1038
-     * @throws InvalidDataTypeException
1039
-     * @throws InvalidEntityException
1040
-     * @throws EE_Error
1041
-     */
1042
-    private function _get_registrations(EE_Transaction $transaction)
1043
-    {
1044
-        // first step: grab the registrants  { : o
1045
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
1046
-        // verify registrations have been set
1047
-        if (empty($registrations)) {
1048
-            // if no cached registrations, then check the db
1049
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1050
-            // still nothing ? well as long as this isn't a revisit
1051
-            if (empty($registrations) && ! $this->checkout->revisit) {
1052
-                // generate new registrations from scratch
1053
-                $registrations = $this->_initialize_registrations($transaction);
1054
-            }
1055
-        }
1056
-        // sort by their original registration order
1057
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1058
-        // then loop thru the array
1059
-        foreach ($registrations as $registration) {
1060
-            // verify each registration
1061
-            if ($registration instanceof EE_Registration) {
1062
-                // we display all attendee info for the primary registrant
1063
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1064
-                    && $registration->is_primary_registrant()
1065
-                ) {
1066
-                    $this->checkout->primary_revisit = true;
1067
-                    break;
1068
-                }
1069
-                if ($this->checkout->revisit
1070
-                           && $this->checkout->reg_url_link !== $registration->reg_url_link()
1071
-                ) {
1072
-                    // but hide info if it doesn't belong to you
1073
-                    $transaction->clear_cache('Registration', $registration->ID());
1074
-                }
1075
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1076
-            }
1077
-        }
1078
-    }
1079
-
1080
-
1081
-    /**
1082
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1083
-     *
1084
-     * @access private
1085
-     * @param EE_Transaction $transaction
1086
-     * @return    array
1087
-     * @throws InvalidDataTypeException
1088
-     * @throws InvalidEntityException
1089
-     * @throws EE_Error
1090
-     */
1091
-    private function _initialize_registrations(EE_Transaction $transaction)
1092
-    {
1093
-        $att_nmbr = 0;
1094
-        $registrations = array();
1095
-        if ($transaction instanceof EE_Transaction) {
1096
-            /** @type EE_Registration_Processor $registration_processor */
1097
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1098
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1099
-            // now let's add the cart items to the $transaction
1100
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1101
-                //do the following for each ticket of this type they selected
1102
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1103
-                    $att_nmbr++;
1104
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1105
-                    $CreateRegistrationCommand = EE_Registry::instance()->create(
1106
-                        'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1107
-                        array(
1108
-                            $transaction,
1109
-                            $line_item,
1110
-                            $att_nmbr,
1111
-                            $this->checkout->total_ticket_count,
1112
-                        )
1113
-                    );
1114
-                    // override capabilities for frontend registrations
1115
-                    if ( ! is_admin()) {
1116
-                        $CreateRegistrationCommand->setCapCheck(
1117
-                            new PublicCapabilities('', 'create_new_registration')
1118
-                        );
1119
-                    }
1120
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1121
-                    if ( ! $registration instanceof EE_Registration) {
1122
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1123
-                    }
1124
-                    $registrations[ $registration->ID() ] = $registration;
1125
-                }
1126
-            }
1127
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1128
-        }
1129
-        return $registrations;
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * sorts registrations by REG_count
1136
-     *
1137
-     * @access public
1138
-     * @param EE_Registration $reg_A
1139
-     * @param EE_Registration $reg_B
1140
-     * @return int
1141
-     */
1142
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1143
-    {
1144
-        // this shouldn't ever happen within the same TXN, but oh well
1145
-        if ($reg_A->count() === $reg_B->count()) {
1146
-            return 0;
1147
-        }
1148
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1149
-    }
1150
-
1151
-
1152
-
1153
-    /**
1154
-     *    _final_verifications
1155
-     * just makes sure that everything is set up correctly before proceeding
1156
-     *
1157
-     * @access    private
1158
-     * @return    bool
1159
-     * @throws EE_Error
1160
-     */
1161
-    private function _final_verifications()
1162
-    {
1163
-        // filter checkout
1164
-        $this->checkout = apply_filters(
1165
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1166
-            $this->checkout
1167
-        );
1168
-        //verify that current step is still set correctly
1169
-        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1170
-            EE_Error::add_error(
1171
-                __('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1172
-                __FILE__,
1173
-                __FUNCTION__,
1174
-                __LINE__
1175
-            );
1176
-            return false;
1177
-        }
1178
-        // if returning to SPCO, then verify that primary registrant is set
1179
-        if ( ! empty($this->checkout->reg_url_link)) {
1180
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1181
-            if ( ! $valid_registrant instanceof EE_Registration) {
1182
-                EE_Error::add_error(
1183
-                    __('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1184
-                    __FILE__,
1185
-                    __FUNCTION__,
1186
-                    __LINE__
1187
-                );
1188
-                return false;
1189
-            }
1190
-            $valid_registrant = null;
1191
-            foreach (
1192
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1193
-            ) {
1194
-                if (
1195
-                    $registration instanceof EE_Registration
1196
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1197
-                ) {
1198
-                    $valid_registrant = $registration;
1199
-                }
1200
-            }
1201
-            if ( ! $valid_registrant instanceof EE_Registration) {
1202
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1203
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1204
-                    // clear the session, mark the checkout as unverified, and try again
1205
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1206
-                    EED_Single_Page_Checkout::$_initialized = false;
1207
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1208
-                    $this->_initialize();
1209
-                    EE_Error::reset_notices();
1210
-                    return false;
1211
-                }
1212
-                EE_Error::add_error(
1213
-                    __(
1214
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1215
-                        'event_espresso'
1216
-                    ),
1217
-                    __FILE__,
1218
-                    __FUNCTION__,
1219
-                    __LINE__
1220
-                );
1221
-                return false;
1222
-            }
1223
-        }
1224
-        // now that things have been kinda sufficiently verified,
1225
-        // let's add the checkout to the session so that it's available to other systems
1226
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1227
-        return true;
1228
-    }
1229
-
1230
-
1231
-
1232
-    /**
1233
-     *    _initialize_reg_steps
1234
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1235
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1236
-     *
1237
-     * @access    private
1238
-     * @param bool $reinitializing
1239
-     * @throws EE_Error
1240
-     */
1241
-    private function _initialize_reg_steps($reinitializing = false)
1242
-    {
1243
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1244
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1245
-        foreach ($this->checkout->reg_steps as $reg_step) {
1246
-            if ( ! $reg_step->initialize_reg_step()) {
1247
-                // if not initialized then maybe this step is being removed...
1248
-                if ( ! $reinitializing && $reg_step->is_current_step()) {
1249
-                    // if it was the current step, then we need to start over here
1250
-                    $this->_initialize_reg_steps(true);
1251
-                    return;
1252
-                }
1253
-                continue;
1254
-            }
1255
-            // add css and JS for current step
1256
-            $reg_step->enqueue_styles_and_scripts();
1257
-            // i18n
1258
-            $reg_step->translate_js_strings();
1259
-            if ($reg_step->is_current_step()) {
1260
-                // the text that appears on the reg step form submit button
1261
-                $reg_step->set_submit_button_text();
1262
-            }
1263
-        }
1264
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1265
-        do_action(
1266
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1267
-            $this->checkout->current_step
1268
-        );
1269
-    }
1270
-
1271
-
1272
-
1273
-    /**
1274
-     * _check_form_submission
1275
-     *
1276
-     * @access private
1277
-     * @return boolean
1278
-     */
1279
-    private function _check_form_submission()
1280
-    {
1281
-        //does this request require the reg form to be generated ?
1282
-        if ($this->checkout->generate_reg_form) {
1283
-            // ever heard that song by Blue Rodeo ?
1284
-            try {
1285
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1286
-                // if not displaying a form, then check for form submission
1287
-                if (
1288
-                    $this->checkout->process_form_submission
1289
-                    && $this->checkout->current_step->reg_form->was_submitted()
1290
-                ) {
1291
-                    // clear out any old data in case this step is being run again
1292
-                    $this->checkout->current_step->set_valid_data(array());
1293
-                    // capture submitted form data
1294
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1295
-                        apply_filters(
1296
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1297
-                            EE_Registry::instance()->REQ->params(),
1298
-                            $this->checkout
1299
-                        )
1300
-                    );
1301
-                    // validate submitted form data
1302
-                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1303
-                        // thou shall not pass !!!
1304
-                        $this->checkout->continue_reg = false;
1305
-                        // any form validation errors?
1306
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1307
-                            $submission_error_messages = array();
1308
-                            // bad, bad, bad registrant
1309
-                            foreach (
1310
-                                $this->checkout->current_step->reg_form->get_validation_errors_accumulated()
1311
-                                as $validation_error
1312
-                            ) {
1313
-                                if ($validation_error instanceof EE_Validation_Error) {
1314
-                                    $submission_error_messages[] = sprintf(
1315
-                                        __('%s : %s', 'event_espresso'),
1316
-                                        $validation_error->get_form_section()->html_label_text(),
1317
-                                        $validation_error->getMessage()
1318
-                                    );
1319
-                                }
1320
-                            }
1321
-                            EE_Error::add_error(
1322
-                                implode('<br />', $submission_error_messages),
1323
-                                __FILE__, __FUNCTION__, __LINE__
1324
-                            );
1325
-                        }
1326
-                        // well not really... what will happen is
1327
-                        // we'll just get redirected back to redo the current step
1328
-                        $this->go_to_next_step();
1329
-                        return false;
1330
-                    }
1331
-                }
1332
-            } catch (EE_Error $e) {
1333
-                $e->get_error();
1334
-            }
1335
-        }
1336
-        return true;
1337
-    }
1338
-
1339
-
1340
-
1341
-    /**
1342
-     * _process_action
1343
-     *
1344
-     * @access private
1345
-     * @return void
1346
-     * @throws EE_Error
1347
-     */
1348
-    private function _process_form_action()
1349
-    {
1350
-        // what cha wanna do?
1351
-        switch ($this->checkout->action) {
1352
-            // AJAX next step reg form
1353
-            case 'display_spco_reg_step' :
1354
-                $this->checkout->redirect = false;
1355
-                if (EE_Registry::instance()->REQ->ajax) {
1356
-                    $this->checkout->json_response->set_reg_step_html(
1357
-                        $this->checkout->current_step->display_reg_form()
1358
-                    );
1359
-                }
1360
-                break;
1361
-            default :
1362
-                // meh... do one of those other steps first
1363
-                if (
1364
-                    ! empty($this->checkout->action)
1365
-                    && is_callable(array($this->checkout->current_step, $this->checkout->action))
1366
-                ) {
1367
-                    // dynamically creates hook point like:
1368
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1369
-                    do_action(
1370
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1371
-                        $this->checkout->current_step
1372
-                    );
1373
-                    // call action on current step
1374
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1375
-                        // good registrant, you get to proceed
1376
-                        if (
1377
-                            $this->checkout->current_step->success_message() !== ''
1378
-                            && apply_filters(
1379
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1380
-                                false
1381
-                            )
1382
-                        ) {
1383
-                            EE_Error::add_success(
1384
-                                $this->checkout->current_step->success_message()
1385
-                                . '<br />' . $this->checkout->next_step->_instructions()
1386
-                            );
1387
-                        }
1388
-                        // pack it up, pack it in...
1389
-                        $this->_setup_redirect();
1390
-                    }
1391
-                    // dynamically creates hook point like:
1392
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1393
-                    do_action(
1394
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1395
-                        $this->checkout->current_step
1396
-                    );
1397
-                } else {
1398
-                    EE_Error::add_error(
1399
-                        sprintf(
1400
-                            __(
1401
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1402
-                                'event_espresso'
1403
-                            ),
1404
-                            $this->checkout->action,
1405
-                            $this->checkout->current_step->name()
1406
-                        ),
1407
-                        __FILE__,
1408
-                        __FUNCTION__,
1409
-                        __LINE__
1410
-                    );
1411
-                }
1412
-            // end default
1413
-        }
1414
-        // store our progress so far
1415
-        $this->checkout->stash_transaction_and_checkout();
1416
-        // advance to the next step! If you pass GO, collect $200
1417
-        $this->go_to_next_step();
1418
-    }
1419
-
1420
-
1421
-
1422
-    /**
1423
-     *        add_styles_and_scripts
1424
-     *
1425
-     * @access        public
1426
-     * @return        void
1427
-     */
1428
-    public function add_styles_and_scripts()
1429
-    {
1430
-        // i18n
1431
-        $this->translate_js_strings();
1432
-        if ($this->checkout->admin_request) {
1433
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1434
-        } else {
1435
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1436
-        }
1437
-    }
1438
-
1439
-
1440
-
1441
-    /**
1442
-     *        translate_js_strings
1443
-     *
1444
-     * @access        public
1445
-     * @return        void
1446
-     */
1447
-    public function translate_js_strings()
1448
-    {
1449
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1450
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1451
-        EE_Registry::$i18n_js_strings['server_error'] = __(
1452
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1453
-            'event_espresso'
1454
-        );
1455
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1456
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1457
-            'event_espresso'
1458
-        );
1459
-        EE_Registry::$i18n_js_strings['validation_error'] = __(
1460
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1461
-            'event_espresso'
1462
-        );
1463
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1464
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1465
-            'event_espresso'
1466
-        );
1467
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1468
-            'This registration step could not be completed. Please refresh the page and try again.',
1469
-            'event_espresso'
1470
-        );
1471
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1472
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1473
-            'event_espresso'
1474
-        );
1475
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1476
-            __(
1477
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1478
-                'event_espresso'
1479
-            ),
1480
-            '<br/>',
1481
-            '<br/>'
1482
-        );
1483
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1484
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1485
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1486
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1487
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1488
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1489
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1490
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1491
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1492
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1493
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1494
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1495
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1496
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1497
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1498
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1499
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1500
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1501
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1502
-            __(
1503
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1504
-                'event_espresso'
1505
-            ),
1506
-            '<h4 class="important-notice">',
1507
-            '</h4>',
1508
-            '<br />',
1509
-            '<p>',
1510
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1511
-            '">',
1512
-            '</a>',
1513
-            '</p>'
1514
-        );
1515
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1516
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1517
-            true
1518
-        );
1519
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1520
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1521
-        );
1522
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1523
-            'M d, Y H:i:s',
1524
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1525
-        );
1526
-    }
1527
-
1528
-
1529
-
1530
-    /**
1531
-     *    enqueue_styles_and_scripts
1532
-     *
1533
-     * @access        public
1534
-     * @return        void
1535
-     * @throws EE_Error
1536
-     */
1537
-    public function enqueue_styles_and_scripts()
1538
-    {
1539
-        // load css
1540
-        wp_register_style(
1541
-            'single_page_checkout',
1542
-            SPCO_CSS_URL . 'single_page_checkout.css',
1543
-            array('espresso_default'),
1544
-            EVENT_ESPRESSO_VERSION
1545
-        );
1546
-        wp_enqueue_style('single_page_checkout');
1547
-        // load JS
1548
-        wp_register_script(
1549
-            'jquery_plugin',
1550
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1551
-            array('jquery'),
1552
-            '1.0.1',
1553
-            true
1554
-        );
1555
-        wp_register_script(
1556
-            'jquery_countdown',
1557
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1558
-            array('jquery_plugin'),
1559
-            '2.0.2',
1560
-            true
1561
-        );
1562
-        wp_register_script(
1563
-            'single_page_checkout',
1564
-            SPCO_JS_URL . 'single_page_checkout.js',
1565
-            array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566
-            EVENT_ESPRESSO_VERSION,
1567
-            true
1568
-        );
1569
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1570
-            $this->checkout->registration_form->enqueue_js();
1571
-        }
1572
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1573
-            $this->checkout->current_step->reg_form->enqueue_js();
1574
-        }
1575
-        wp_enqueue_script('single_page_checkout');
1576
-        /**
1577
-         * global action hook for enqueueing styles and scripts with
1578
-         * spco calls.
1579
-         */
1580
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1581
-        /**
1582
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1583
-         * The hook will end up being something like:
1584
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585
-         */
1586
-        do_action(
1587
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1588
-            $this
1589
-        );
1590
-    }
1591
-
1592
-
1593
-
1594
-    /**
1595
-     *    display the Registration Single Page Checkout Form
1596
-     *
1597
-     * @access    private
1598
-     * @return    void
1599
-     * @throws EE_Error
1600
-     */
1601
-    private function _display_spco_reg_form()
1602
-    {
1603
-        // if registering via the admin, just display the reg form for the current step
1604
-        if ($this->checkout->admin_request) {
1605
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1606
-        } else {
1607
-            // add powered by EE msg
1608
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1609
-            $empty_cart = count(
1610
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1611
-            ) < 1;
1612
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1613
-            $cookies_not_set_msg = '';
1614
-            if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1615
-                $cookies_not_set_msg = apply_filters(
1616
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1617
-                    sprintf(
1618
-                        __(
1619
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1620
-                            'event_espresso'
1621
-                        ),
1622
-                        '<div class="ee-attention">',
1623
-                        '</div>',
1624
-                        '<h6 class="important-notice">',
1625
-                        '</h6>',
1626
-                        '<p>',
1627
-                        '</p>',
1628
-                        '<br />',
1629
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1630
-                        '</a>'
1631
-                    )
1632
-                );
1633
-            }
1634
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1635
-                array(
1636
-                    'name'            => 'single-page-checkout',
1637
-                    'html_id'         => 'ee-single-page-checkout-dv',
1638
-                    'layout_strategy' =>
1639
-                        new EE_Template_Layout(
1640
-                            array(
1641
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1642
-                                'template_args'        => array(
1643
-                                    'empty_cart'              => $empty_cart,
1644
-                                    'revisit'                 => $this->checkout->revisit,
1645
-                                    'reg_steps'               => $this->checkout->reg_steps,
1646
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1647
-                                        ? $this->checkout->next_step->slug()
1648
-                                        : '',
1649
-                                    'cancel_page_url'         => $this->checkout->cancel_page_url,
1650
-                                    'empty_msg'               => apply_filters(
1651
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1652
-                                        sprintf(
1653
-                                            __(
1654
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1655
-                                                'event_espresso'
1656
-                                            ),
1657
-                                            '<a href="'
1658
-                                            . get_post_type_archive_link('espresso_events')
1659
-                                            . '" title="',
1660
-                                            '">',
1661
-                                            '</a>'
1662
-                                        )
1663
-                                    ),
1664
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1665
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1666
-                                    'session_expiration'      => gmdate(
1667
-                                        'M d, Y H:i:s',
1668
-                                        EE_Registry::instance()->SSN->expiration()
1669
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1670
-                                    ),
1671
-                                ),
1672
-                            )
1673
-                        ),
1674
-                )
1675
-            );
1676
-            // load template and add to output sent that gets filtered into the_content()
1677
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1678
-        }
1679
-    }
1680
-
1681
-
1682
-
1683
-    /**
1684
-     *    add_extra_finalize_registration_inputs
1685
-     *
1686
-     * @access    public
1687
-     * @param $next_step
1688
-     * @internal  param string $label
1689
-     * @return void
1690
-     */
1691
-    public function add_extra_finalize_registration_inputs($next_step)
1692
-    {
1693
-        if ($next_step === 'finalize_registration') {
1694
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1695
-        }
1696
-    }
1697
-
1698
-
1699
-
1700
-    /**
1701
-     *    display_registration_footer
1702
-     *
1703
-     * @access    public
1704
-     * @return    string
1705
-     */
1706
-    public static function display_registration_footer()
1707
-    {
1708
-        if (
1709
-        apply_filters(
1710
-            'FHEE__EE_Front__Controller__show_reg_footer',
1711
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1712
-        )
1713
-        ) {
1714
-            add_filter(
1715
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
-                function ($url) {
1717
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718
-                }
1719
-            );
1720
-            echo apply_filters(
1721
-                'FHEE__EE_Front_Controller__display_registration_footer',
1722
-                \EEH_Template::powered_by_event_espresso(
1723
-                    '',
1724
-                    'espresso-registration-footer-dv',
1725
-                    array('utm_content' => 'registration_checkout')
1726
-                )
1727
-            );
1728
-        }
1729
-        return '';
1730
-    }
1731
-
1732
-
1733
-
1734
-    /**
1735
-     *    unlock_transaction
1736
-     *
1737
-     * @access    public
1738
-     * @return    void
1739
-     * @throws EE_Error
1740
-     */
1741
-    public function unlock_transaction()
1742
-    {
1743
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1744
-            $this->checkout->transaction->unlock();
1745
-        }
1746
-    }
1747
-
1748
-
1749
-
1750
-    /**
1751
-     *        _setup_redirect
1752
-     *
1753
-     * @access    private
1754
-     * @return void
1755
-     */
1756
-    private function _setup_redirect()
1757
-    {
1758
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1759
-            $this->checkout->redirect = true;
1760
-            if (empty($this->checkout->redirect_url)) {
1761
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1762
-            }
1763
-            $this->checkout->redirect_url = apply_filters(
1764
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1765
-                $this->checkout->redirect_url,
1766
-                $this->checkout
1767
-            );
1768
-        }
1769
-    }
1770
-
1771
-
1772
-
1773
-    /**
1774
-     *   handle ajax message responses and redirects
1775
-     *
1776
-     * @access public
1777
-     * @return void
1778
-     * @throws EE_Error
1779
-     */
1780
-    public function go_to_next_step()
1781
-    {
1782
-        if (EE_Registry::instance()->REQ->ajax) {
1783
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1784
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1785
-        }
1786
-        $this->unlock_transaction();
1787
-        // just return for these conditions
1788
-        if (
1789
-            $this->checkout->admin_request
1790
-            || $this->checkout->action === 'redirect_form'
1791
-            || $this->checkout->action === 'update_checkout'
1792
-        ) {
1793
-            return;
1794
-        }
1795
-        // AJAX response
1796
-        $this->_handle_json_response();
1797
-        // redirect to next step or the Thank You page
1798
-        $this->_handle_html_redirects();
1799
-        // hmmm... must be something wrong, so let's just display the form again !
1800
-        $this->_display_spco_reg_form();
1801
-    }
1802
-
1803
-
1804
-
1805
-    /**
1806
-     *   _handle_json_response
1807
-     *
1808
-     * @access protected
1809
-     * @return void
1810
-     */
1811
-    protected function _handle_json_response()
1812
-    {
1813
-        // if this is an ajax request
1814
-        if (EE_Registry::instance()->REQ->ajax) {
1815
-            // DEBUG LOG
1816
-            //$this->checkout->log(
1817
-            //	__CLASS__, __FUNCTION__, __LINE__,
1818
-            //	array(
1819
-            //		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1820
-            //		'redirect'                   => $this->checkout->redirect,
1821
-            //		'continue_reg'               => $this->checkout->continue_reg,
1822
-            //	)
1823
-            //);
1824
-            $this->checkout->json_response->set_registration_time_limit(
1825
-                $this->checkout->get_registration_time_limit()
1826
-            );
1827
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1828
-            // just send the ajax (
1829
-            $json_response = apply_filters(
1830
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1831
-                $this->checkout->json_response
1832
-            );
1833
-            echo $json_response;
1834
-            exit();
1835
-        }
1836
-    }
1837
-
1838
-
1839
-
1840
-    /**
1841
-     *   _handle_redirects
1842
-     *
1843
-     * @access protected
1844
-     * @return void
1845
-     */
1846
-    protected function _handle_html_redirects()
1847
-    {
1848
-        // going somewhere ?
1849
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1850
-            // store notices in a transient
1851
-            EE_Error::get_notices(false, true, true);
1852
-            // DEBUG LOG
1853
-            //$this->checkout->log(
1854
-            //	__CLASS__, __FUNCTION__, __LINE__,
1855
-            //	array(
1856
-            //		'headers_sent' => headers_sent(),
1857
-            //		'redirect_url'     => $this->checkout->redirect_url,
1858
-            //		'headers_list'    => headers_list(),
1859
-            //	)
1860
-            //);
1861
-            wp_safe_redirect($this->checkout->redirect_url);
1862
-            exit();
1863
-        }
1864
-    }
1865
-
1866
-
1867
-
1868
-    /**
1869
-     *   set_checkout_anchor
1870
-     *
1871
-     * @access public
1872
-     * @return void
1873
-     */
1874
-    public function set_checkout_anchor()
1875
-    {
1876
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1877
-    }
23
+	/**
24
+	 * $_initialized - has the SPCO controller already been initialized ?
25
+	 *
26
+	 * @access private
27
+	 * @var bool $_initialized
28
+	 */
29
+	private static $_initialized = false;
30
+
31
+
32
+	/**
33
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
+	 *
35
+	 * @access private
36
+	 * @var bool $_valid_checkout
37
+	 */
38
+	private static $_checkout_verified = true;
39
+
40
+	/**
41
+	 *    $_reg_steps_array - holds initial array of reg steps
42
+	 *
43
+	 * @access private
44
+	 * @var array $_reg_steps_array
45
+	 */
46
+	private static $_reg_steps_array = array();
47
+
48
+	/**
49
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
+	 *
51
+	 * @access public
52
+	 * @var EE_Checkout $checkout
53
+	 */
54
+	public $checkout;
55
+
56
+
57
+
58
+	/**
59
+	 * @return EED_Module|EED_Single_Page_Checkout
60
+	 */
61
+	public static function instance()
62
+	{
63
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
+		return parent::get_instance(__CLASS__);
65
+	}
66
+
67
+
68
+
69
+	/**
70
+	 * @return EE_CART
71
+	 */
72
+	public function cart()
73
+	{
74
+		return $this->checkout->cart;
75
+	}
76
+
77
+
78
+
79
+	/**
80
+	 * @return EE_Transaction
81
+	 */
82
+	public function transaction()
83
+	{
84
+		return $this->checkout->transaction;
85
+	}
86
+
87
+
88
+
89
+	/**
90
+	 *    set_hooks - for hooking into EE Core, other modules, etc
91
+	 *
92
+	 * @access    public
93
+	 * @return    void
94
+	 * @throws EE_Error
95
+	 */
96
+	public static function set_hooks()
97
+	{
98
+		EED_Single_Page_Checkout::set_definitions();
99
+	}
100
+
101
+
102
+
103
+	/**
104
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
+	 *
106
+	 * @access    public
107
+	 * @return    void
108
+	 * @throws EE_Error
109
+	 */
110
+	public static function set_hooks_admin()
111
+	{
112
+		EED_Single_Page_Checkout::set_definitions();
113
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
+			return;
115
+		}
116
+		// going to start an output buffer in case anything gets accidentally output
117
+		// that might disrupt our JSON response
118
+		ob_start();
119
+		EED_Single_Page_Checkout::load_request_handler();
120
+		EED_Single_Page_Checkout::load_reg_steps();
121
+		// set ajax hooks
122
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 *    process ajax request
134
+	 *
135
+	 * @param string $ajax_action
136
+	 * @throws EE_Error
137
+	 */
138
+	public static function process_ajax_request($ajax_action)
139
+	{
140
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
141
+		EED_Single_Page_Checkout::instance()->_initialize();
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 *    ajax display registration step
148
+	 *
149
+	 * @throws EE_Error
150
+	 */
151
+	public static function display_reg_step()
152
+	{
153
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 *    ajax process registration step
160
+	 *
161
+	 * @throws EE_Error
162
+	 */
163
+	public static function process_reg_step()
164
+	{
165
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
+	}
167
+
168
+
169
+
170
+	/**
171
+	 *    ajax process registration step
172
+	 *
173
+	 * @throws EE_Error
174
+	 */
175
+	public static function update_reg_step()
176
+	{
177
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
+	}
179
+
180
+
181
+
182
+	/**
183
+	 *   update_checkout
184
+	 *
185
+	 * @access public
186
+	 * @return void
187
+	 * @throws EE_Error
188
+	 */
189
+	public static function update_checkout()
190
+	{
191
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
+	}
193
+
194
+
195
+
196
+	/**
197
+	 *    load_request_handler
198
+	 *
199
+	 * @access    public
200
+	 * @return    void
201
+	 */
202
+	public static function load_request_handler()
203
+	{
204
+		// load core Request_Handler class
205
+		if (EE_Registry::instance()->REQ !== null) {
206
+			EE_Registry::instance()->load_core('Request_Handler');
207
+		}
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 *    set_definitions
214
+	 *
215
+	 * @access    public
216
+	 * @return    void
217
+	 * @throws EE_Error
218
+	 */
219
+	public static function set_definitions()
220
+	{
221
+		if(defined('SPCO_BASE_PATH')) {
222
+			return;
223
+		}
224
+		define(
225
+			'SPCO_BASE_PATH',
226
+			rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
+		);
228
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236
+			__('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
237
+				'event_espresso'),
238
+			'<h4 class="important-notice">',
239
+			'</h4>',
240
+			'<br />',
241
+			'<p>',
242
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
243
+			'">',
244
+			'</a>',
245
+			'</p>'
246
+		);
247
+	}
248
+
249
+
250
+
251
+	/**
252
+	 * load_reg_steps
253
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
254
+	 *
255
+	 * @access    private
256
+	 * @throws EE_Error
257
+	 */
258
+	public static function load_reg_steps()
259
+	{
260
+		static $reg_steps_loaded = false;
261
+		if ($reg_steps_loaded) {
262
+			return;
263
+		}
264
+		// filter list of reg_steps
265
+		$reg_steps_to_load = (array)apply_filters(
266
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267
+			EED_Single_Page_Checkout::get_reg_steps()
268
+		);
269
+		// sort by key (order)
270
+		ksort($reg_steps_to_load);
271
+		// loop through folders
272
+		foreach ($reg_steps_to_load as $order => $reg_step) {
273
+			// we need a
274
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
275
+				// copy over to the reg_steps_array
276
+				EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
277
+				// register custom key route for each reg step
278
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
279
+				EE_Config::register_route(
280
+					$reg_step['slug'],
281
+					'EED_Single_Page_Checkout',
282
+					'run',
283
+					'step'
284
+				);
285
+				// add AJAX or other hooks
286
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
287
+					// setup autoloaders if necessary
288
+					if ( ! class_exists($reg_step['class_name'])) {
289
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
290
+							$reg_step['file_path'],
291
+							true
292
+						);
293
+					}
294
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
295
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
296
+					}
297
+				}
298
+			}
299
+		}
300
+		$reg_steps_loaded = true;
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 *    get_reg_steps
307
+	 *
308
+	 * @access    public
309
+	 * @return    array
310
+	 */
311
+	public static function get_reg_steps()
312
+	{
313
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
314
+		if (empty($reg_steps)) {
315
+			$reg_steps = array(
316
+				10  => array(
317
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
318
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319
+					'slug'       => 'attendee_information',
320
+					'has_hooks'  => false,
321
+				),
322
+				20  => array(
323
+					'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
324
+					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325
+					'slug'       => 'registration_confirmation',
326
+					'has_hooks'  => false,
327
+				),
328
+				30  => array(
329
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
330
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331
+					'slug'       => 'payment_options',
332
+					'has_hooks'  => true,
333
+				),
334
+				999 => array(
335
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
336
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337
+					'slug'       => 'finalize_registration',
338
+					'has_hooks'  => false,
339
+				),
340
+			);
341
+		}
342
+		return $reg_steps;
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 *    registration_checkout_for_admin
349
+	 *
350
+	 * @access    public
351
+	 * @return    string
352
+	 * @throws EE_Error
353
+	 */
354
+	public static function registration_checkout_for_admin()
355
+	{
356
+		EED_Single_Page_Checkout::load_request_handler();
357
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
358
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
359
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
360
+		EED_Single_Page_Checkout::instance()->_initialize();
361
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
362
+		return EE_Registry::instance()->REQ->get_output();
363
+	}
364
+
365
+
366
+
367
+	/**
368
+	 * process_registration_from_admin
369
+	 *
370
+	 * @access public
371
+	 * @return \EE_Transaction
372
+	 * @throws EE_Error
373
+	 */
374
+	public static function process_registration_from_admin()
375
+	{
376
+		EED_Single_Page_Checkout::load_request_handler();
377
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
378
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
379
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
380
+		EED_Single_Page_Checkout::instance()->_initialize();
381
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
382
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
383
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
384
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
385
+				if ($final_reg_step->process_reg_step()) {
386
+					$final_reg_step->set_completed();
387
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
388
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
389
+				}
390
+			}
391
+		}
392
+		return null;
393
+	}
394
+
395
+
396
+
397
+	/**
398
+	 *    run
399
+	 *
400
+	 * @access    public
401
+	 * @param WP_Query $WP_Query
402
+	 * @return    void
403
+	 * @throws EE_Error
404
+	 */
405
+	public function run($WP_Query)
406
+	{
407
+		if (
408
+			$WP_Query instanceof WP_Query
409
+			&& $WP_Query->is_main_query()
410
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
411
+			&& $this->_is_reg_checkout()
412
+		) {
413
+			$this->_initialize();
414
+		}
415
+	}
416
+
417
+
418
+
419
+	/**
420
+	 * determines whether current url matches reg page url
421
+	 *
422
+	 * @return bool
423
+	 */
424
+	protected function _is_reg_checkout()
425
+	{
426
+		// get current permalink for reg page without any extra query args
427
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
428
+		// get request URI for current request, but without the scheme or host
429
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
430
+		$current_request_uri = html_entity_decode($current_request_uri);
431
+		// get array of query args from the current request URI
432
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
433
+		// grab page id if it is set
434
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
435
+		// and remove the page id from the query args (we will re-add it later)
436
+		unset($query_args['page_id']);
437
+		// now strip all query args from current request URI
438
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
439
+		// and re-add the page id if it was set
440
+		if ($page_id) {
441
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
442
+		}
443
+		// remove slashes and ?
444
+		$current_request_uri = trim($current_request_uri, '?/');
445
+		// is current request URI part of the known full reg page URL ?
446
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 * @param WP_Query $wp_query
453
+	 * @return    void
454
+	 * @throws EE_Error
455
+	 */
456
+	public static function init($wp_query)
457
+	{
458
+		EED_Single_Page_Checkout::instance()->run($wp_query);
459
+	}
460
+
461
+
462
+
463
+	/**
464
+	 *    _initialize - initial module setup
465
+	 *
466
+	 * @access    private
467
+	 * @throws EE_Error
468
+	 * @return    void
469
+	 */
470
+	private function _initialize()
471
+	{
472
+		// ensure SPCO doesn't run twice
473
+		if (EED_Single_Page_Checkout::$_initialized) {
474
+			return;
475
+		}
476
+		try {
477
+			EED_Single_Page_Checkout::load_reg_steps();
478
+			$this->_verify_session();
479
+			// setup the EE_Checkout object
480
+			$this->checkout = $this->_initialize_checkout();
481
+			// filter checkout
482
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
483
+			// get the $_GET
484
+			$this->_get_request_vars();
485
+			if ($this->_block_bots()) {
486
+				return;
487
+			}
488
+			// filter continue_reg
489
+			$this->checkout->continue_reg = apply_filters(
490
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
491
+				true,
492
+				$this->checkout
493
+			);
494
+			// load the reg steps array
495
+			if ( ! $this->_load_and_instantiate_reg_steps()) {
496
+				EED_Single_Page_Checkout::$_initialized = true;
497
+				return;
498
+			}
499
+			// set the current step
500
+			$this->checkout->set_current_step($this->checkout->step);
501
+			// and the next step
502
+			$this->checkout->set_next_step();
503
+			// verify that everything has been setup correctly
504
+			if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
505
+				EED_Single_Page_Checkout::$_initialized = true;
506
+				return;
507
+			}
508
+			// lock the transaction
509
+			$this->checkout->transaction->lock();
510
+			// make sure all of our cached objects are added to their respective model entity mappers
511
+			$this->checkout->refresh_all_entities();
512
+			// set amount owing
513
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
514
+			// initialize each reg step, which gives them the chance to potentially alter the process
515
+			$this->_initialize_reg_steps();
516
+			// DEBUG LOG
517
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518
+			// get reg form
519
+			if( ! $this->_check_form_submission()) {
520
+				EED_Single_Page_Checkout::$_initialized = true;
521
+				return;
522
+			}
523
+			// checkout the action!!!
524
+			$this->_process_form_action();
525
+			// add some style and make it dance
526
+			$this->add_styles_and_scripts();
527
+			// kk... SPCO has successfully run
528
+			EED_Single_Page_Checkout::$_initialized = true;
529
+			// set no cache headers and constants
530
+			EE_System::do_not_cache();
531
+			// add anchor
532
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
533
+			// remove transaction lock
534
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
535
+		} catch (Exception $e) {
536
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
537
+		}
538
+	}
539
+
540
+
541
+
542
+	/**
543
+	 *    _verify_session
544
+	 * checks that the session is valid and not expired
545
+	 *
546
+	 * @access    private
547
+	 * @throws EE_Error
548
+	 */
549
+	private function _verify_session()
550
+	{
551
+		if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
552
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
553
+		}
554
+		$clear_session_requested = filter_var(
555
+			EE_Registry::instance()->REQ->get('clear_session', false),
556
+			FILTER_VALIDATE_BOOLEAN
557
+		);
558
+		// is session still valid ?
559
+		if ($clear_session_requested
560
+			|| ( EE_Registry::instance()->SSN->expired()
561
+			  && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562
+			)
563
+		) {
564
+			$this->checkout = new EE_Checkout();
565
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
566
+			// EE_Registry::instance()->SSN->reset_cart();
567
+			// EE_Registry::instance()->SSN->reset_checkout();
568
+			// EE_Registry::instance()->SSN->reset_transaction();
569
+			if (! $clear_session_requested) {
570
+				EE_Error::add_attention(
571
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572
+					__FILE__, __FUNCTION__, __LINE__
573
+				);
574
+			}
575
+			// EE_Registry::instance()->SSN->reset_expired();
576
+		}
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 *    _initialize_checkout
583
+	 * loads and instantiates EE_Checkout
584
+	 *
585
+	 * @access    private
586
+	 * @throws EE_Error
587
+	 * @return EE_Checkout
588
+	 */
589
+	private function _initialize_checkout()
590
+	{
591
+		// look in session for existing checkout
592
+		/** @type EE_Checkout $checkout */
593
+		$checkout = EE_Registry::instance()->SSN->checkout();
594
+		// verify
595
+		if ( ! $checkout instanceof EE_Checkout) {
596
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
597
+			$checkout = EE_Registry::instance()->load_file(
598
+				SPCO_INC_PATH,
599
+				'EE_Checkout',
600
+				'class', array(),
601
+				false
602
+			);
603
+		} else {
604
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
605
+				$this->unlock_transaction();
606
+				wp_safe_redirect($checkout->redirect_url);
607
+				exit();
608
+			}
609
+		}
610
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
611
+		// verify again
612
+		if ( ! $checkout instanceof EE_Checkout) {
613
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
614
+		}
615
+		// reset anything that needs a clean slate for each request
616
+		$checkout->reset_for_current_request();
617
+		return $checkout;
618
+	}
619
+
620
+
621
+
622
+	/**
623
+	 *    _get_request_vars
624
+	 *
625
+	 * @access    private
626
+	 * @return    void
627
+	 * @throws EE_Error
628
+	 */
629
+	private function _get_request_vars()
630
+	{
631
+		// load classes
632
+		EED_Single_Page_Checkout::load_request_handler();
633
+		//make sure this request is marked as belonging to EE
634
+		EE_Registry::instance()->REQ->set_espresso_page(true);
635
+		// which step is being requested ?
636
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
637
+		// which step is being edited ?
638
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
639
+		// and what we're doing on the current step
640
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
641
+		// timestamp
642
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
643
+		// returning to edit ?
644
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
645
+		// or some other kind of revisit ?
646
+		$this->checkout->revisit = filter_var(
647
+			EE_Registry::instance()->REQ->get('revisit', false),
648
+			FILTER_VALIDATE_BOOLEAN
649
+		);
650
+		// and whether or not to generate a reg form for this request
651
+		$this->checkout->generate_reg_form = filter_var(
652
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
653
+			FILTER_VALIDATE_BOOLEAN
654
+		);
655
+		// and whether or not to process a reg form submission for this request
656
+		$this->checkout->process_form_submission = filter_var(
657
+			EE_Registry::instance()->REQ->get(
658
+				'process_form_submission',
659
+				$this->checkout->action === 'process_reg_step'
660
+			),
661
+			FILTER_VALIDATE_BOOLEAN
662
+		);
663
+		$this->checkout->process_form_submission = filter_var(
664
+			$this->checkout->action !== 'display_spco_reg_step'
665
+				? $this->checkout->process_form_submission
666
+				: false,
667
+			FILTER_VALIDATE_BOOLEAN
668
+		);
669
+		// $this->_display_request_vars();
670
+	}
671
+
672
+
673
+
674
+	/**
675
+	 *  _display_request_vars
676
+	 *
677
+	 * @access    protected
678
+	 * @return    void
679
+	 */
680
+	protected function _display_request_vars()
681
+	{
682
+		if ( ! WP_DEBUG) {
683
+			return;
684
+		}
685
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
686
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
687
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
688
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
689
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
690
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
691
+		EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
692
+		EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
693
+	}
694
+
695
+
696
+
697
+	/**
698
+	 * _block_bots
699
+	 * checks that the incoming request has either of the following set:
700
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
701
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
702
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
703
+	 * then where you coming from man?
704
+	 *
705
+	 * @return boolean
706
+	 */
707
+	private function _block_bots()
708
+	{
709
+		$invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
710
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
711
+			return true;
712
+		}
713
+		return false;
714
+	}
715
+
716
+
717
+
718
+	/**
719
+	 *    _get_first_step
720
+	 *  gets slug for first step in $_reg_steps_array
721
+	 *
722
+	 * @access    private
723
+	 * @throws EE_Error
724
+	 * @return    string
725
+	 */
726
+	private function _get_first_step()
727
+	{
728
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
729
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
730
+	}
731
+
732
+
733
+
734
+	/**
735
+	 *    _load_and_instantiate_reg_steps
736
+	 *  instantiates each reg step based on the loaded reg_steps array
737
+	 *
738
+	 * @access    private
739
+	 * @throws EE_Error
740
+	 * @return    bool
741
+	 */
742
+	private function _load_and_instantiate_reg_steps()
743
+	{
744
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
745
+		// have reg_steps already been instantiated ?
746
+		if (
747
+			empty($this->checkout->reg_steps)
748
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
749
+		) {
750
+			// if not, then loop through raw reg steps array
751
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
752
+				if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
753
+					return false;
754
+				}
755
+			}
756
+			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
757
+			EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
758
+			// skip the registration_confirmation page ?
759
+			if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
760
+				// just remove it from the reg steps array
761
+				$this->checkout->remove_reg_step('registration_confirmation', false);
762
+			} else if (
763
+				isset($this->checkout->reg_steps['registration_confirmation'])
764
+				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
765
+			) {
766
+				// set the order to something big like 100
767
+				$this->checkout->set_reg_step_order('registration_confirmation', 100);
768
+			}
769
+			// filter the array for good luck
770
+			$this->checkout->reg_steps = apply_filters(
771
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
772
+				$this->checkout->reg_steps
773
+			);
774
+			// finally re-sort based on the reg step class order properties
775
+			$this->checkout->sort_reg_steps();
776
+		} else {
777
+			foreach ($this->checkout->reg_steps as $reg_step) {
778
+				// set all current step stati to FALSE
779
+				$reg_step->set_is_current_step(false);
780
+			}
781
+		}
782
+		if (empty($this->checkout->reg_steps)) {
783
+			EE_Error::add_error(
784
+				__('No Reg Steps were loaded..', 'event_espresso'),
785
+				__FILE__, __FUNCTION__, __LINE__
786
+			);
787
+			return false;
788
+		}
789
+		// make reg step details available to JS
790
+		$this->checkout->set_reg_step_JSON_info();
791
+		return true;
792
+	}
793
+
794
+
795
+
796
+	/**
797
+	 *     _load_and_instantiate_reg_step
798
+	 *
799
+	 * @access    private
800
+	 * @param array $reg_step
801
+	 * @param int   $order
802
+	 * @return bool
803
+	 */
804
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
805
+	{
806
+		// we need a file_path, class_name, and slug to add a reg step
807
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
808
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
809
+			if (
810
+				$this->checkout->reg_url_link
811
+				&& $this->checkout->step !== $reg_step['slug']
812
+				&& $reg_step['slug'] !== 'finalize_registration'
813
+				// normally at this point we would NOT load the reg step, but this filter can change that
814
+				&& apply_filters(
815
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
816
+					true,
817
+					$reg_step,
818
+					$this->checkout
819
+				)
820
+			) {
821
+				return true;
822
+			}
823
+			// instantiate step class using file path and class name
824
+			$reg_step_obj = EE_Registry::instance()->load_file(
825
+				$reg_step['file_path'],
826
+				$reg_step['class_name'],
827
+				'class',
828
+				$this->checkout,
829
+				false
830
+			);
831
+			// did we gets the goods ?
832
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
833
+				// set reg step order based on config
834
+				$reg_step_obj->set_order($order);
835
+				// add instantiated reg step object to the master reg steps array
836
+				$this->checkout->add_reg_step($reg_step_obj);
837
+			} else {
838
+				EE_Error::add_error(
839
+					__('The current step could not be set.', 'event_espresso'),
840
+					__FILE__, __FUNCTION__, __LINE__
841
+				);
842
+				return false;
843
+			}
844
+		} else {
845
+			if (WP_DEBUG) {
846
+				EE_Error::add_error(
847
+					sprintf(
848
+						__(
849
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
850
+							'event_espresso'
851
+						),
852
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
853
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
854
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
855
+						'<ul>',
856
+						'<li>',
857
+						'</li>',
858
+						'</ul>'
859
+					),
860
+					__FILE__, __FUNCTION__, __LINE__
861
+				);
862
+			}
863
+			return false;
864
+		}
865
+		return true;
866
+	}
867
+
868
+
869
+	/**
870
+	 * _verify_transaction_and_get_registrations
871
+	 *
872
+	 * @access private
873
+	 * @return bool
874
+	 * @throws InvalidDataTypeException
875
+	 * @throws InvalidEntityException
876
+	 * @throws EE_Error
877
+	 */
878
+	private function _verify_transaction_and_get_registrations()
879
+	{
880
+		// was there already a valid transaction in the checkout from the session ?
881
+		if ( ! $this->checkout->transaction instanceof EE_Transaction) {
882
+			// get transaction from db or session
883
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
884
+				? $this->_get_transaction_and_cart_for_previous_visit()
885
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
886
+			if ( ! $this->checkout->transaction instanceof EE_Transaction) {
887
+				EE_Error::add_error(
888
+					__('Your Registration and Transaction information could not be retrieved from the db.',
889
+						'event_espresso'),
890
+					__FILE__, __FUNCTION__, __LINE__
891
+				);
892
+				$this->checkout->transaction = EE_Transaction::new_instance();
893
+				// add some style and make it dance
894
+				$this->add_styles_and_scripts();
895
+				EED_Single_Page_Checkout::$_initialized = true;
896
+				return false;
897
+			}
898
+			// and the registrations for the transaction
899
+			$this->_get_registrations($this->checkout->transaction);
900
+		}
901
+		return true;
902
+	}
903
+
904
+
905
+
906
+	/**
907
+	 * _get_transaction_and_cart_for_previous_visit
908
+	 *
909
+	 * @access private
910
+	 * @return mixed EE_Transaction|NULL
911
+	 */
912
+	private function _get_transaction_and_cart_for_previous_visit()
913
+	{
914
+		/** @var $TXN_model EEM_Transaction */
915
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
916
+		// because the reg_url_link is present in the request,
917
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
918
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
919
+		// verify transaction
920
+		if ($transaction instanceof EE_Transaction) {
921
+			// and get the cart that was used for that transaction
922
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
923
+			return $transaction;
924
+		}
925
+		EE_Error::add_error(
926
+			__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
927
+			__FILE__, __FUNCTION__, __LINE__
928
+		);
929
+		return null;
930
+
931
+	}
932
+
933
+
934
+
935
+	/**
936
+	 * _get_cart_for_transaction
937
+	 *
938
+	 * @access private
939
+	 * @param EE_Transaction $transaction
940
+	 * @return EE_Cart
941
+	 */
942
+	private function _get_cart_for_transaction($transaction)
943
+	{
944
+		return $this->checkout->get_cart_for_transaction($transaction);
945
+	}
946
+
947
+
948
+
949
+	/**
950
+	 * get_cart_for_transaction
951
+	 *
952
+	 * @access public
953
+	 * @param EE_Transaction $transaction
954
+	 * @return EE_Cart
955
+	 */
956
+	public function get_cart_for_transaction(EE_Transaction $transaction)
957
+	{
958
+		return $this->checkout->get_cart_for_transaction($transaction);
959
+	}
960
+
961
+
962
+
963
+	/**
964
+	 * _get_transaction_and_cart_for_current_session
965
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
966
+	 *
967
+	 * @access private
968
+	 * @return EE_Transaction
969
+	 * @throws EE_Error
970
+	 */
971
+	private function _get_cart_for_current_session_and_setup_new_transaction()
972
+	{
973
+		//  if there's no transaction, then this is the FIRST visit to SPCO
974
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
975
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
976
+		// and then create a new transaction
977
+		$transaction = $this->_initialize_transaction();
978
+		// verify transaction
979
+		if ($transaction instanceof EE_Transaction) {
980
+			// save it so that we have an ID for other objects to use
981
+			$transaction->save();
982
+			// and save TXN data to the cart
983
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
984
+		} else {
985
+			EE_Error::add_error(
986
+				__('A Valid Transaction could not be initialized.', 'event_espresso'),
987
+				__FILE__, __FUNCTION__, __LINE__
988
+			);
989
+		}
990
+		return $transaction;
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
997
+	 *
998
+	 * @access private
999
+	 * @return mixed EE_Transaction|NULL
1000
+	 */
1001
+	private function _initialize_transaction()
1002
+	{
1003
+		try {
1004
+			// ensure cart totals have been calculated
1005
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
1006
+			// grab the cart grand total
1007
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
1008
+			// create new TXN
1009
+			$transaction = EE_Transaction::new_instance(
1010
+				array(
1011
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1012
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1013
+					'TXN_paid'      => 0,
1014
+					'STS_ID'        => EEM_Transaction::failed_status_code,
1015
+				)
1016
+			);
1017
+			// save it so that we have an ID for other objects to use
1018
+			$transaction->save();
1019
+			// set cron job for following up on TXNs after their session has expired
1020
+			EE_Cron_Tasks::schedule_expired_transaction_check(
1021
+				EE_Registry::instance()->SSN->expiration() + 1,
1022
+				$transaction->ID()
1023
+			);
1024
+			return $transaction;
1025
+		} catch (Exception $e) {
1026
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1027
+		}
1028
+		return null;
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * _get_registrations
1034
+	 *
1035
+	 * @access private
1036
+	 * @param EE_Transaction $transaction
1037
+	 * @return void
1038
+	 * @throws InvalidDataTypeException
1039
+	 * @throws InvalidEntityException
1040
+	 * @throws EE_Error
1041
+	 */
1042
+	private function _get_registrations(EE_Transaction $transaction)
1043
+	{
1044
+		// first step: grab the registrants  { : o
1045
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
1046
+		// verify registrations have been set
1047
+		if (empty($registrations)) {
1048
+			// if no cached registrations, then check the db
1049
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1050
+			// still nothing ? well as long as this isn't a revisit
1051
+			if (empty($registrations) && ! $this->checkout->revisit) {
1052
+				// generate new registrations from scratch
1053
+				$registrations = $this->_initialize_registrations($transaction);
1054
+			}
1055
+		}
1056
+		// sort by their original registration order
1057
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1058
+		// then loop thru the array
1059
+		foreach ($registrations as $registration) {
1060
+			// verify each registration
1061
+			if ($registration instanceof EE_Registration) {
1062
+				// we display all attendee info for the primary registrant
1063
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1064
+					&& $registration->is_primary_registrant()
1065
+				) {
1066
+					$this->checkout->primary_revisit = true;
1067
+					break;
1068
+				}
1069
+				if ($this->checkout->revisit
1070
+						   && $this->checkout->reg_url_link !== $registration->reg_url_link()
1071
+				) {
1072
+					// but hide info if it doesn't belong to you
1073
+					$transaction->clear_cache('Registration', $registration->ID());
1074
+				}
1075
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1076
+			}
1077
+		}
1078
+	}
1079
+
1080
+
1081
+	/**
1082
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1083
+	 *
1084
+	 * @access private
1085
+	 * @param EE_Transaction $transaction
1086
+	 * @return    array
1087
+	 * @throws InvalidDataTypeException
1088
+	 * @throws InvalidEntityException
1089
+	 * @throws EE_Error
1090
+	 */
1091
+	private function _initialize_registrations(EE_Transaction $transaction)
1092
+	{
1093
+		$att_nmbr = 0;
1094
+		$registrations = array();
1095
+		if ($transaction instanceof EE_Transaction) {
1096
+			/** @type EE_Registration_Processor $registration_processor */
1097
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1098
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1099
+			// now let's add the cart items to the $transaction
1100
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1101
+				//do the following for each ticket of this type they selected
1102
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1103
+					$att_nmbr++;
1104
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1105
+					$CreateRegistrationCommand = EE_Registry::instance()->create(
1106
+						'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1107
+						array(
1108
+							$transaction,
1109
+							$line_item,
1110
+							$att_nmbr,
1111
+							$this->checkout->total_ticket_count,
1112
+						)
1113
+					);
1114
+					// override capabilities for frontend registrations
1115
+					if ( ! is_admin()) {
1116
+						$CreateRegistrationCommand->setCapCheck(
1117
+							new PublicCapabilities('', 'create_new_registration')
1118
+						);
1119
+					}
1120
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1121
+					if ( ! $registration instanceof EE_Registration) {
1122
+						throw new InvalidEntityException($registration, 'EE_Registration');
1123
+					}
1124
+					$registrations[ $registration->ID() ] = $registration;
1125
+				}
1126
+			}
1127
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1128
+		}
1129
+		return $registrations;
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * sorts registrations by REG_count
1136
+	 *
1137
+	 * @access public
1138
+	 * @param EE_Registration $reg_A
1139
+	 * @param EE_Registration $reg_B
1140
+	 * @return int
1141
+	 */
1142
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1143
+	{
1144
+		// this shouldn't ever happen within the same TXN, but oh well
1145
+		if ($reg_A->count() === $reg_B->count()) {
1146
+			return 0;
1147
+		}
1148
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1149
+	}
1150
+
1151
+
1152
+
1153
+	/**
1154
+	 *    _final_verifications
1155
+	 * just makes sure that everything is set up correctly before proceeding
1156
+	 *
1157
+	 * @access    private
1158
+	 * @return    bool
1159
+	 * @throws EE_Error
1160
+	 */
1161
+	private function _final_verifications()
1162
+	{
1163
+		// filter checkout
1164
+		$this->checkout = apply_filters(
1165
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1166
+			$this->checkout
1167
+		);
1168
+		//verify that current step is still set correctly
1169
+		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1170
+			EE_Error::add_error(
1171
+				__('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1172
+				__FILE__,
1173
+				__FUNCTION__,
1174
+				__LINE__
1175
+			);
1176
+			return false;
1177
+		}
1178
+		// if returning to SPCO, then verify that primary registrant is set
1179
+		if ( ! empty($this->checkout->reg_url_link)) {
1180
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1181
+			if ( ! $valid_registrant instanceof EE_Registration) {
1182
+				EE_Error::add_error(
1183
+					__('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1184
+					__FILE__,
1185
+					__FUNCTION__,
1186
+					__LINE__
1187
+				);
1188
+				return false;
1189
+			}
1190
+			$valid_registrant = null;
1191
+			foreach (
1192
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1193
+			) {
1194
+				if (
1195
+					$registration instanceof EE_Registration
1196
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1197
+				) {
1198
+					$valid_registrant = $registration;
1199
+				}
1200
+			}
1201
+			if ( ! $valid_registrant instanceof EE_Registration) {
1202
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1203
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1204
+					// clear the session, mark the checkout as unverified, and try again
1205
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1206
+					EED_Single_Page_Checkout::$_initialized = false;
1207
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1208
+					$this->_initialize();
1209
+					EE_Error::reset_notices();
1210
+					return false;
1211
+				}
1212
+				EE_Error::add_error(
1213
+					__(
1214
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1215
+						'event_espresso'
1216
+					),
1217
+					__FILE__,
1218
+					__FUNCTION__,
1219
+					__LINE__
1220
+				);
1221
+				return false;
1222
+			}
1223
+		}
1224
+		// now that things have been kinda sufficiently verified,
1225
+		// let's add the checkout to the session so that it's available to other systems
1226
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1227
+		return true;
1228
+	}
1229
+
1230
+
1231
+
1232
+	/**
1233
+	 *    _initialize_reg_steps
1234
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1235
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1236
+	 *
1237
+	 * @access    private
1238
+	 * @param bool $reinitializing
1239
+	 * @throws EE_Error
1240
+	 */
1241
+	private function _initialize_reg_steps($reinitializing = false)
1242
+	{
1243
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1244
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1245
+		foreach ($this->checkout->reg_steps as $reg_step) {
1246
+			if ( ! $reg_step->initialize_reg_step()) {
1247
+				// if not initialized then maybe this step is being removed...
1248
+				if ( ! $reinitializing && $reg_step->is_current_step()) {
1249
+					// if it was the current step, then we need to start over here
1250
+					$this->_initialize_reg_steps(true);
1251
+					return;
1252
+				}
1253
+				continue;
1254
+			}
1255
+			// add css and JS for current step
1256
+			$reg_step->enqueue_styles_and_scripts();
1257
+			// i18n
1258
+			$reg_step->translate_js_strings();
1259
+			if ($reg_step->is_current_step()) {
1260
+				// the text that appears on the reg step form submit button
1261
+				$reg_step->set_submit_button_text();
1262
+			}
1263
+		}
1264
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1265
+		do_action(
1266
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1267
+			$this->checkout->current_step
1268
+		);
1269
+	}
1270
+
1271
+
1272
+
1273
+	/**
1274
+	 * _check_form_submission
1275
+	 *
1276
+	 * @access private
1277
+	 * @return boolean
1278
+	 */
1279
+	private function _check_form_submission()
1280
+	{
1281
+		//does this request require the reg form to be generated ?
1282
+		if ($this->checkout->generate_reg_form) {
1283
+			// ever heard that song by Blue Rodeo ?
1284
+			try {
1285
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1286
+				// if not displaying a form, then check for form submission
1287
+				if (
1288
+					$this->checkout->process_form_submission
1289
+					&& $this->checkout->current_step->reg_form->was_submitted()
1290
+				) {
1291
+					// clear out any old data in case this step is being run again
1292
+					$this->checkout->current_step->set_valid_data(array());
1293
+					// capture submitted form data
1294
+					$this->checkout->current_step->reg_form->receive_form_submission(
1295
+						apply_filters(
1296
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1297
+							EE_Registry::instance()->REQ->params(),
1298
+							$this->checkout
1299
+						)
1300
+					);
1301
+					// validate submitted form data
1302
+					if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1303
+						// thou shall not pass !!!
1304
+						$this->checkout->continue_reg = false;
1305
+						// any form validation errors?
1306
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1307
+							$submission_error_messages = array();
1308
+							// bad, bad, bad registrant
1309
+							foreach (
1310
+								$this->checkout->current_step->reg_form->get_validation_errors_accumulated()
1311
+								as $validation_error
1312
+							) {
1313
+								if ($validation_error instanceof EE_Validation_Error) {
1314
+									$submission_error_messages[] = sprintf(
1315
+										__('%s : %s', 'event_espresso'),
1316
+										$validation_error->get_form_section()->html_label_text(),
1317
+										$validation_error->getMessage()
1318
+									);
1319
+								}
1320
+							}
1321
+							EE_Error::add_error(
1322
+								implode('<br />', $submission_error_messages),
1323
+								__FILE__, __FUNCTION__, __LINE__
1324
+							);
1325
+						}
1326
+						// well not really... what will happen is
1327
+						// we'll just get redirected back to redo the current step
1328
+						$this->go_to_next_step();
1329
+						return false;
1330
+					}
1331
+				}
1332
+			} catch (EE_Error $e) {
1333
+				$e->get_error();
1334
+			}
1335
+		}
1336
+		return true;
1337
+	}
1338
+
1339
+
1340
+
1341
+	/**
1342
+	 * _process_action
1343
+	 *
1344
+	 * @access private
1345
+	 * @return void
1346
+	 * @throws EE_Error
1347
+	 */
1348
+	private function _process_form_action()
1349
+	{
1350
+		// what cha wanna do?
1351
+		switch ($this->checkout->action) {
1352
+			// AJAX next step reg form
1353
+			case 'display_spco_reg_step' :
1354
+				$this->checkout->redirect = false;
1355
+				if (EE_Registry::instance()->REQ->ajax) {
1356
+					$this->checkout->json_response->set_reg_step_html(
1357
+						$this->checkout->current_step->display_reg_form()
1358
+					);
1359
+				}
1360
+				break;
1361
+			default :
1362
+				// meh... do one of those other steps first
1363
+				if (
1364
+					! empty($this->checkout->action)
1365
+					&& is_callable(array($this->checkout->current_step, $this->checkout->action))
1366
+				) {
1367
+					// dynamically creates hook point like:
1368
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1369
+					do_action(
1370
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1371
+						$this->checkout->current_step
1372
+					);
1373
+					// call action on current step
1374
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1375
+						// good registrant, you get to proceed
1376
+						if (
1377
+							$this->checkout->current_step->success_message() !== ''
1378
+							&& apply_filters(
1379
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1380
+								false
1381
+							)
1382
+						) {
1383
+							EE_Error::add_success(
1384
+								$this->checkout->current_step->success_message()
1385
+								. '<br />' . $this->checkout->next_step->_instructions()
1386
+							);
1387
+						}
1388
+						// pack it up, pack it in...
1389
+						$this->_setup_redirect();
1390
+					}
1391
+					// dynamically creates hook point like:
1392
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1393
+					do_action(
1394
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1395
+						$this->checkout->current_step
1396
+					);
1397
+				} else {
1398
+					EE_Error::add_error(
1399
+						sprintf(
1400
+							__(
1401
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1402
+								'event_espresso'
1403
+							),
1404
+							$this->checkout->action,
1405
+							$this->checkout->current_step->name()
1406
+						),
1407
+						__FILE__,
1408
+						__FUNCTION__,
1409
+						__LINE__
1410
+					);
1411
+				}
1412
+			// end default
1413
+		}
1414
+		// store our progress so far
1415
+		$this->checkout->stash_transaction_and_checkout();
1416
+		// advance to the next step! If you pass GO, collect $200
1417
+		$this->go_to_next_step();
1418
+	}
1419
+
1420
+
1421
+
1422
+	/**
1423
+	 *        add_styles_and_scripts
1424
+	 *
1425
+	 * @access        public
1426
+	 * @return        void
1427
+	 */
1428
+	public function add_styles_and_scripts()
1429
+	{
1430
+		// i18n
1431
+		$this->translate_js_strings();
1432
+		if ($this->checkout->admin_request) {
1433
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1434
+		} else {
1435
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1436
+		}
1437
+	}
1438
+
1439
+
1440
+
1441
+	/**
1442
+	 *        translate_js_strings
1443
+	 *
1444
+	 * @access        public
1445
+	 * @return        void
1446
+	 */
1447
+	public function translate_js_strings()
1448
+	{
1449
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1450
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1451
+		EE_Registry::$i18n_js_strings['server_error'] = __(
1452
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1453
+			'event_espresso'
1454
+		);
1455
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1456
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1457
+			'event_espresso'
1458
+		);
1459
+		EE_Registry::$i18n_js_strings['validation_error'] = __(
1460
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1461
+			'event_espresso'
1462
+		);
1463
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1464
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1465
+			'event_espresso'
1466
+		);
1467
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1468
+			'This registration step could not be completed. Please refresh the page and try again.',
1469
+			'event_espresso'
1470
+		);
1471
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1472
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1473
+			'event_espresso'
1474
+		);
1475
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1476
+			__(
1477
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1478
+				'event_espresso'
1479
+			),
1480
+			'<br/>',
1481
+			'<br/>'
1482
+		);
1483
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1484
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1485
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1486
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1487
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1488
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1489
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1490
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1491
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1492
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1493
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1494
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1495
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1496
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1497
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1498
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1499
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1500
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1501
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1502
+			__(
1503
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
1504
+				'event_espresso'
1505
+			),
1506
+			'<h4 class="important-notice">',
1507
+			'</h4>',
1508
+			'<br />',
1509
+			'<p>',
1510
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1511
+			'">',
1512
+			'</a>',
1513
+			'</p>'
1514
+		);
1515
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1516
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1517
+			true
1518
+		);
1519
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1520
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1521
+		);
1522
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1523
+			'M d, Y H:i:s',
1524
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1525
+		);
1526
+	}
1527
+
1528
+
1529
+
1530
+	/**
1531
+	 *    enqueue_styles_and_scripts
1532
+	 *
1533
+	 * @access        public
1534
+	 * @return        void
1535
+	 * @throws EE_Error
1536
+	 */
1537
+	public function enqueue_styles_and_scripts()
1538
+	{
1539
+		// load css
1540
+		wp_register_style(
1541
+			'single_page_checkout',
1542
+			SPCO_CSS_URL . 'single_page_checkout.css',
1543
+			array('espresso_default'),
1544
+			EVENT_ESPRESSO_VERSION
1545
+		);
1546
+		wp_enqueue_style('single_page_checkout');
1547
+		// load JS
1548
+		wp_register_script(
1549
+			'jquery_plugin',
1550
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1551
+			array('jquery'),
1552
+			'1.0.1',
1553
+			true
1554
+		);
1555
+		wp_register_script(
1556
+			'jquery_countdown',
1557
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1558
+			array('jquery_plugin'),
1559
+			'2.0.2',
1560
+			true
1561
+		);
1562
+		wp_register_script(
1563
+			'single_page_checkout',
1564
+			SPCO_JS_URL . 'single_page_checkout.js',
1565
+			array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566
+			EVENT_ESPRESSO_VERSION,
1567
+			true
1568
+		);
1569
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1570
+			$this->checkout->registration_form->enqueue_js();
1571
+		}
1572
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1573
+			$this->checkout->current_step->reg_form->enqueue_js();
1574
+		}
1575
+		wp_enqueue_script('single_page_checkout');
1576
+		/**
1577
+		 * global action hook for enqueueing styles and scripts with
1578
+		 * spco calls.
1579
+		 */
1580
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1581
+		/**
1582
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1583
+		 * The hook will end up being something like:
1584
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585
+		 */
1586
+		do_action(
1587
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1588
+			$this
1589
+		);
1590
+	}
1591
+
1592
+
1593
+
1594
+	/**
1595
+	 *    display the Registration Single Page Checkout Form
1596
+	 *
1597
+	 * @access    private
1598
+	 * @return    void
1599
+	 * @throws EE_Error
1600
+	 */
1601
+	private function _display_spco_reg_form()
1602
+	{
1603
+		// if registering via the admin, just display the reg form for the current step
1604
+		if ($this->checkout->admin_request) {
1605
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1606
+		} else {
1607
+			// add powered by EE msg
1608
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1609
+			$empty_cart = count(
1610
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1611
+			) < 1;
1612
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1613
+			$cookies_not_set_msg = '';
1614
+			if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1615
+				$cookies_not_set_msg = apply_filters(
1616
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1617
+					sprintf(
1618
+						__(
1619
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1620
+							'event_espresso'
1621
+						),
1622
+						'<div class="ee-attention">',
1623
+						'</div>',
1624
+						'<h6 class="important-notice">',
1625
+						'</h6>',
1626
+						'<p>',
1627
+						'</p>',
1628
+						'<br />',
1629
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1630
+						'</a>'
1631
+					)
1632
+				);
1633
+			}
1634
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1635
+				array(
1636
+					'name'            => 'single-page-checkout',
1637
+					'html_id'         => 'ee-single-page-checkout-dv',
1638
+					'layout_strategy' =>
1639
+						new EE_Template_Layout(
1640
+							array(
1641
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1642
+								'template_args'        => array(
1643
+									'empty_cart'              => $empty_cart,
1644
+									'revisit'                 => $this->checkout->revisit,
1645
+									'reg_steps'               => $this->checkout->reg_steps,
1646
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1647
+										? $this->checkout->next_step->slug()
1648
+										: '',
1649
+									'cancel_page_url'         => $this->checkout->cancel_page_url,
1650
+									'empty_msg'               => apply_filters(
1651
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1652
+										sprintf(
1653
+											__(
1654
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1655
+												'event_espresso'
1656
+											),
1657
+											'<a href="'
1658
+											. get_post_type_archive_link('espresso_events')
1659
+											. '" title="',
1660
+											'">',
1661
+											'</a>'
1662
+										)
1663
+									),
1664
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1665
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1666
+									'session_expiration'      => gmdate(
1667
+										'M d, Y H:i:s',
1668
+										EE_Registry::instance()->SSN->expiration()
1669
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1670
+									),
1671
+								),
1672
+							)
1673
+						),
1674
+				)
1675
+			);
1676
+			// load template and add to output sent that gets filtered into the_content()
1677
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1678
+		}
1679
+	}
1680
+
1681
+
1682
+
1683
+	/**
1684
+	 *    add_extra_finalize_registration_inputs
1685
+	 *
1686
+	 * @access    public
1687
+	 * @param $next_step
1688
+	 * @internal  param string $label
1689
+	 * @return void
1690
+	 */
1691
+	public function add_extra_finalize_registration_inputs($next_step)
1692
+	{
1693
+		if ($next_step === 'finalize_registration') {
1694
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1695
+		}
1696
+	}
1697
+
1698
+
1699
+
1700
+	/**
1701
+	 *    display_registration_footer
1702
+	 *
1703
+	 * @access    public
1704
+	 * @return    string
1705
+	 */
1706
+	public static function display_registration_footer()
1707
+	{
1708
+		if (
1709
+		apply_filters(
1710
+			'FHEE__EE_Front__Controller__show_reg_footer',
1711
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1712
+		)
1713
+		) {
1714
+			add_filter(
1715
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
+				function ($url) {
1717
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718
+				}
1719
+			);
1720
+			echo apply_filters(
1721
+				'FHEE__EE_Front_Controller__display_registration_footer',
1722
+				\EEH_Template::powered_by_event_espresso(
1723
+					'',
1724
+					'espresso-registration-footer-dv',
1725
+					array('utm_content' => 'registration_checkout')
1726
+				)
1727
+			);
1728
+		}
1729
+		return '';
1730
+	}
1731
+
1732
+
1733
+
1734
+	/**
1735
+	 *    unlock_transaction
1736
+	 *
1737
+	 * @access    public
1738
+	 * @return    void
1739
+	 * @throws EE_Error
1740
+	 */
1741
+	public function unlock_transaction()
1742
+	{
1743
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1744
+			$this->checkout->transaction->unlock();
1745
+		}
1746
+	}
1747
+
1748
+
1749
+
1750
+	/**
1751
+	 *        _setup_redirect
1752
+	 *
1753
+	 * @access    private
1754
+	 * @return void
1755
+	 */
1756
+	private function _setup_redirect()
1757
+	{
1758
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1759
+			$this->checkout->redirect = true;
1760
+			if (empty($this->checkout->redirect_url)) {
1761
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1762
+			}
1763
+			$this->checkout->redirect_url = apply_filters(
1764
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1765
+				$this->checkout->redirect_url,
1766
+				$this->checkout
1767
+			);
1768
+		}
1769
+	}
1770
+
1771
+
1772
+
1773
+	/**
1774
+	 *   handle ajax message responses and redirects
1775
+	 *
1776
+	 * @access public
1777
+	 * @return void
1778
+	 * @throws EE_Error
1779
+	 */
1780
+	public function go_to_next_step()
1781
+	{
1782
+		if (EE_Registry::instance()->REQ->ajax) {
1783
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1784
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1785
+		}
1786
+		$this->unlock_transaction();
1787
+		// just return for these conditions
1788
+		if (
1789
+			$this->checkout->admin_request
1790
+			|| $this->checkout->action === 'redirect_form'
1791
+			|| $this->checkout->action === 'update_checkout'
1792
+		) {
1793
+			return;
1794
+		}
1795
+		// AJAX response
1796
+		$this->_handle_json_response();
1797
+		// redirect to next step or the Thank You page
1798
+		$this->_handle_html_redirects();
1799
+		// hmmm... must be something wrong, so let's just display the form again !
1800
+		$this->_display_spco_reg_form();
1801
+	}
1802
+
1803
+
1804
+
1805
+	/**
1806
+	 *   _handle_json_response
1807
+	 *
1808
+	 * @access protected
1809
+	 * @return void
1810
+	 */
1811
+	protected function _handle_json_response()
1812
+	{
1813
+		// if this is an ajax request
1814
+		if (EE_Registry::instance()->REQ->ajax) {
1815
+			// DEBUG LOG
1816
+			//$this->checkout->log(
1817
+			//	__CLASS__, __FUNCTION__, __LINE__,
1818
+			//	array(
1819
+			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1820
+			//		'redirect'                   => $this->checkout->redirect,
1821
+			//		'continue_reg'               => $this->checkout->continue_reg,
1822
+			//	)
1823
+			//);
1824
+			$this->checkout->json_response->set_registration_time_limit(
1825
+				$this->checkout->get_registration_time_limit()
1826
+			);
1827
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1828
+			// just send the ajax (
1829
+			$json_response = apply_filters(
1830
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1831
+				$this->checkout->json_response
1832
+			);
1833
+			echo $json_response;
1834
+			exit();
1835
+		}
1836
+	}
1837
+
1838
+
1839
+
1840
+	/**
1841
+	 *   _handle_redirects
1842
+	 *
1843
+	 * @access protected
1844
+	 * @return void
1845
+	 */
1846
+	protected function _handle_html_redirects()
1847
+	{
1848
+		// going somewhere ?
1849
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1850
+			// store notices in a transient
1851
+			EE_Error::get_notices(false, true, true);
1852
+			// DEBUG LOG
1853
+			//$this->checkout->log(
1854
+			//	__CLASS__, __FUNCTION__, __LINE__,
1855
+			//	array(
1856
+			//		'headers_sent' => headers_sent(),
1857
+			//		'redirect_url'     => $this->checkout->redirect_url,
1858
+			//		'headers_list'    => headers_list(),
1859
+			//	)
1860
+			//);
1861
+			wp_safe_redirect($this->checkout->redirect_url);
1862
+			exit();
1863
+		}
1864
+	}
1865
+
1866
+
1867
+
1868
+	/**
1869
+	 *   set_checkout_anchor
1870
+	 *
1871
+	 * @access public
1872
+	 * @return void
1873
+	 */
1874
+	public function set_checkout_anchor()
1875
+	{
1876
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1877
+	}
1878 1878
 
1879 1879
 
1880 1880
 
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -218,19 +218,19 @@  discard block
 block discarded – undo
218 218
      */
219 219
     public static function set_definitions()
220 220
     {
221
-        if(defined('SPCO_BASE_PATH')) {
221
+        if (defined('SPCO_BASE_PATH')) {
222 222
             return;
223 223
         }
224 224
         define(
225 225
             'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
226
+            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS
227 227
         );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
228
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css'.DS);
229
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img'.DS);
230
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js'.DS);
231
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc'.DS);
232
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps'.DS);
233
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates'.DS);
234 234
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235 235
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
236 236
             __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please except our apologies for any inconvenience this may have caused.%8$s',
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
             '</h4>',
240 240
             '<br />',
241 241
             '<p>',
242
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
242
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
243 243
             '">',
244 244
             '</a>',
245 245
             '</p>'
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
             return;
263 263
         }
264 264
         // filter list of reg_steps
265
-        $reg_steps_to_load = (array)apply_filters(
265
+        $reg_steps_to_load = (array) apply_filters(
266 266
             'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
267 267
             EED_Single_Page_Checkout::get_reg_steps()
268 268
         );
@@ -314,25 +314,25 @@  discard block
 block discarded – undo
314 314
         if (empty($reg_steps)) {
315 315
             $reg_steps = array(
316 316
                 10  => array(
317
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
317
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
318 318
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
319 319
                     'slug'       => 'attendee_information',
320 320
                     'has_hooks'  => false,
321 321
                 ),
322 322
                 20  => array(
323
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
323
+                    'file_path'  => SPCO_REG_STEPS_PATH.'registration_confirmation',
324 324
                     'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
325 325
                     'slug'       => 'registration_confirmation',
326 326
                     'has_hooks'  => false,
327 327
                 ),
328 328
                 30  => array(
329
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
329
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
330 330
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
331 331
                     'slug'       => 'payment_options',
332 332
                     'has_hooks'  => true,
333 333
                 ),
334 334
                 999 => array(
335
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
335
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
336 336
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
337 337
                     'slug'       => 'finalize_registration',
338 338
                     'has_hooks'  => false,
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
             // DEBUG LOG
517 517
             //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
518 518
             // get reg form
519
-            if( ! $this->_check_form_submission()) {
519
+            if ( ! $this->_check_form_submission()) {
520 520
                 EED_Single_Page_Checkout::$_initialized = true;
521 521
                 return;
522 522
             }
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
         );
558 558
         // is session still valid ?
559 559
         if ($clear_session_requested
560
-            || ( EE_Registry::instance()->SSN->expired()
560
+            || (EE_Registry::instance()->SSN->expired()
561 561
               && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
562 562
             )
563 563
         ) {
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
             // EE_Registry::instance()->SSN->reset_cart();
567 567
             // EE_Registry::instance()->SSN->reset_checkout();
568 568
             // EE_Registry::instance()->SSN->reset_transaction();
569
-            if (! $clear_session_requested) {
569
+            if ( ! $clear_session_requested) {
570 570
                 EE_Error::add_attention(
571 571
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
572 572
                     __FILE__, __FUNCTION__, __LINE__
@@ -1121,7 +1121,7 @@  discard block
 block discarded – undo
1121 1121
                     if ( ! $registration instanceof EE_Registration) {
1122 1122
                         throw new InvalidEntityException($registration, 'EE_Registration');
1123 1123
                     }
1124
-                    $registrations[ $registration->ID() ] = $registration;
1124
+                    $registrations[$registration->ID()] = $registration;
1125 1125
                 }
1126 1126
             }
1127 1127
             $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1382,7 +1382,7 @@  discard block
 block discarded – undo
1382 1382
                         ) {
1383 1383
                             EE_Error::add_success(
1384 1384
                                 $this->checkout->current_step->success_message()
1385
-                                . '<br />' . $this->checkout->next_step->_instructions()
1385
+                                . '<br />'.$this->checkout->next_step->_instructions()
1386 1386
                             );
1387 1387
                         }
1388 1388
                         // pack it up, pack it in...
@@ -1507,7 +1507,7 @@  discard block
 block discarded – undo
1507 1507
             '</h4>',
1508 1508
             '<br />',
1509 1509
             '<p>',
1510
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1510
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1511 1511
             '">',
1512 1512
             '</a>',
1513 1513
             '</p>'
@@ -1539,7 +1539,7 @@  discard block
 block discarded – undo
1539 1539
         // load css
1540 1540
         wp_register_style(
1541 1541
             'single_page_checkout',
1542
-            SPCO_CSS_URL . 'single_page_checkout.css',
1542
+            SPCO_CSS_URL.'single_page_checkout.css',
1543 1543
             array('espresso_default'),
1544 1544
             EVENT_ESPRESSO_VERSION
1545 1545
         );
@@ -1547,21 +1547,21 @@  discard block
 block discarded – undo
1547 1547
         // load JS
1548 1548
         wp_register_script(
1549 1549
             'jquery_plugin',
1550
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1550
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1551 1551
             array('jquery'),
1552 1552
             '1.0.1',
1553 1553
             true
1554 1554
         );
1555 1555
         wp_register_script(
1556 1556
             'jquery_countdown',
1557
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1557
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1558 1558
             array('jquery_plugin'),
1559 1559
             '2.0.2',
1560 1560
             true
1561 1561
         );
1562 1562
         wp_register_script(
1563 1563
             'single_page_checkout',
1564
-            SPCO_JS_URL . 'single_page_checkout.js',
1564
+            SPCO_JS_URL.'single_page_checkout.js',
1565 1565
             array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1566 1566
             EVENT_ESPRESSO_VERSION,
1567 1567
             true
@@ -1584,7 +1584,7 @@  discard block
 block discarded – undo
1584 1584
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1585 1585
          */
1586 1586
         do_action(
1587
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1587
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1588 1588
             $this
1589 1589
         );
1590 1590
     }
@@ -1638,7 +1638,7 @@  discard block
 block discarded – undo
1638 1638
                     'layout_strategy' =>
1639 1639
                         new EE_Template_Layout(
1640 1640
                             array(
1641
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1641
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1642 1642
                                 'template_args'        => array(
1643 1643
                                     'empty_cart'              => $empty_cart,
1644 1644
                                     'revisit'                 => $this->checkout->revisit,
@@ -1713,7 +1713,7 @@  discard block
 block discarded – undo
1713 1713
         ) {
1714 1714
             add_filter(
1715 1715
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1716
-                function ($url) {
1716
+                function($url) {
1717 1717
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1718 1718
                 }
1719 1719
             );
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +1967 added lines, -1967 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 /**
@@ -27,1975 +27,1975 @@  discard block
 block discarded – undo
27 27
 class Transactions_Admin_Page extends EE_Admin_Page
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Transaction
32
-     */
33
-    private $_transaction;
34
-
35
-    /**
36
-     * @var EE_Session
37
-     */
38
-    private $_session;
39
-
40
-    /**
41
-     * @var array $_txn_status
42
-     */
43
-    private static $_txn_status;
44
-
45
-    /**
46
-     * @var array $_pay_status
47
-     */
48
-    private static $_pay_status;
49
-
50
-    /**
51
-     * @var array $_existing_reg_payment_REG_IDs
52
-     */
53
-    protected $_existing_reg_payment_REG_IDs = null;
54
-
55
-
56
-    /**
57
-     * @Constructor
58
-     * @access public
59
-     *
60
-     * @param bool $routing
61
-     *
62
-     * @return Transactions_Admin_Page
63
-     */
64
-    public function __construct($routing = true)
65
-    {
66
-        parent::__construct($routing);
67
-    }
68
-
69
-
70
-    /**
71
-     *    _init_page_props
72
-     * @return void
73
-     */
74
-    protected function _init_page_props()
75
-    {
76
-        $this->page_slug        = TXN_PG_SLUG;
77
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
78
-        $this->_admin_base_url  = TXN_ADMIN_URL;
79
-        $this->_admin_base_path = TXN_ADMIN;
80
-    }
81
-
82
-
83
-    /**
84
-     *    _ajax_hooks
85
-     * @return void
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
90
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
91
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
92
-    }
93
-
94
-
95
-    /**
96
-     *    _define_page_props
97
-     * @return void
98
-     */
99
-    protected function _define_page_props()
100
-    {
101
-        $this->_admin_page_title = $this->page_label;
102
-        $this->_labels           = array(
103
-            'buttons' => array(
104
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
105
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
106
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
107
-            )
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     *        grab url requests and route them
114
-     * @access private
115
-     * @return void
116
-     */
117
-    public function _set_page_routes()
118
-    {
119
-
120
-        $this->_set_transaction_status_array();
121
-
122
-        $txn_id = ! empty($this->_req_data['TXN_ID']) && ! is_array($this->_req_data['TXN_ID']) ? $this->_req_data['TXN_ID'] : 0;
123
-
124
-        $this->_page_routes = array(
125
-
126
-            'default' => array(
127
-                'func'       => '_transactions_overview_list_table',
128
-                'capability' => 'ee_read_transactions'
129
-            ),
130
-
131
-            'view_transaction' => array(
132
-                'func'       => '_transaction_details',
133
-                'capability' => 'ee_read_transaction',
134
-                'obj_id'     => $txn_id
135
-            ),
136
-
137
-            'send_payment_reminder' => array(
138
-                'func'       => '_send_payment_reminder',
139
-                'noheader'   => true,
140
-                'capability' => 'ee_send_message'
141
-            ),
142
-
143
-            'espresso_apply_payment' => array(
144
-                'func'       => 'apply_payments_or_refunds',
145
-                'noheader'   => true,
146
-                'capability' => 'ee_edit_payments'
147
-            ),
148
-
149
-            'espresso_apply_refund' => array(
150
-                'func'       => 'apply_payments_or_refunds',
151
-                'noheader'   => true,
152
-                'capability' => 'ee_edit_payments'
153
-            ),
154
-
155
-            'espresso_delete_payment' => array(
156
-                'func'       => 'delete_payment',
157
-                'noheader'   => true,
158
-                'capability' => 'ee_delete_payments'
159
-            ),
160
-
161
-        );
162
-
163
-    }
164
-
165
-
166
-    protected function _set_page_config()
167
-    {
168
-        $this->_page_config = array(
169
-            'default'          => array(
170
-                'nav'           => array(
171
-                    'label' => esc_html__('Overview', 'event_espresso'),
172
-                    'order' => 10
173
-                ),
174
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
175
-                'help_tabs'     => array(
176
-                    'transactions_overview_help_tab'                       => array(
177
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
178
-                        'filename' => 'transactions_overview'
179
-                    ),
180
-                    'transactions_overview_table_column_headings_help_tab' => array(
181
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
182
-                        'filename' => 'transactions_overview_table_column_headings'
183
-                    ),
184
-                    'transactions_overview_views_filters_help_tab'         => array(
185
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
186
-                        'filename' => 'transactions_overview_views_filters_search'
187
-                    ),
188
-                ),
189
-                'help_tour'     => array('Transactions_Overview_Help_Tour'),
190
-                /**
191
-                 * commented out because currently we are not displaying tips for transaction list table status but this
192
-                 * may change in a later iteration so want to keep the code for then.
193
-                 */
194
-                //'qtips' => array( 'Transactions_List_Table_Tips' ),
195
-                'require_nonce' => false
196
-            ),
197
-            'view_transaction' => array(
198
-                'nav'       => array(
199
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
200
-                    'order'      => 5,
201
-                    'url'        => isset($this->_req_data['TXN_ID']) ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']),
202
-                        $this->_current_page_view_url) : $this->_admin_base_url,
203
-                    'persistent' => false
204
-                ),
205
-                'help_tabs' => array(
206
-                    'transactions_view_transaction_help_tab'                                              => array(
207
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
208
-                        'filename' => 'transactions_view_transaction'
209
-                    ),
210
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
-                        'filename' => 'transactions_view_transaction_transaction_details_table'
213
-                    ),
214
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
-                        'filename' => 'transactions_view_transaction_attendees_registered'
217
-                    ),
218
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information'
221
-                    ),
222
-                ),
223
-                'qtips'     => array('Transaction_Details_Tips'),
224
-                'help_tour' => array('Transaction_Details_Help_Tour'),
225
-                'metaboxes' => array('_transaction_details_metaboxes'),
226
-
227
-                'require_nonce' => false
228
-            )
229
-        );
230
-    }
231
-
232
-
233
-    /**
234
-     * The below methods aren't used by this class currently
235
-     */
236
-    protected function _add_screen_options()
237
-    {
238
-    }
239
-
240
-    protected function _add_feature_pointers()
241
-    {
242
-    }
243
-
244
-    public function admin_init()
245
-    {
246
-        // IF a registration was JUST added via the admin...
247
-        if (
248
-        isset(
249
-            $this->_req_data['redirect_from'],
250
-            $this->_req_data['EVT_ID'],
251
-            $this->_req_data['event_name']
252
-        )
253
-        ) {
254
-            // then set a cookie so that we can block any attempts to use
255
-            // the back button as a way to enter another registration.
256
-            setcookie('ee_registration_added', $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/');
257
-            // and update the global
258
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
-        }
260
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__('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.',
261
-            'event_espresso');
262
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__('An error occurred! Please refresh the page and try again.',
263
-            'event_espresso');
264
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
265
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
266
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
267
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__('This transaction has been overpaid ! Payments Total',
268
-            'event_espresso');
269
-    }
270
-
271
-    public function admin_notices()
272
-    {
273
-    }
274
-
275
-    public function admin_footer_scripts()
276
-    {
277
-    }
278
-
279
-
280
-    /**
281
-     * _set_transaction_status_array
282
-     * sets list of transaction statuses
283
-     *
284
-     * @access private
285
-     * @return void
286
-     */
287
-    private function _set_transaction_status_array()
288
-    {
289
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
-    }
291
-
292
-
293
-    /**
294
-     * get_transaction_status_array
295
-     * return the transaction status array for wp_list_table
296
-     *
297
-     * @access public
298
-     * @return array
299
-     */
300
-    public function get_transaction_status_array()
301
-    {
302
-        return self::$_txn_status;
303
-    }
304
-
305
-
306
-    /**
307
-     *    get list of payment statuses
308
-     *
309
-     * @access private
310
-     * @return void
311
-     */
312
-    private function _get_payment_status_array()
313
-    {
314
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
-        $this->_template_args['payment_status'] = self::$_pay_status;
316
-
317
-    }
318
-
319
-
320
-    /**
321
-     *    _add_screen_options_default
322
-     *
323
-     * @access protected
324
-     * @return void
325
-     */
326
-    protected function _add_screen_options_default()
327
-    {
328
-        $this->_per_page_screen_option();
329
-    }
330
-
331
-
332
-    /**
333
-     * load_scripts_styles
334
-     *
335
-     * @access public
336
-     * @return void
337
-     */
338
-    public function load_scripts_styles()
339
-    {
340
-        //enqueue style
341
-        wp_register_style('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.css', array(),
342
-            EVENT_ESPRESSO_VERSION);
343
-        wp_enqueue_style('espresso_txn');
344
-        //scripts
345
-        wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
346
-            'ee_admin_js',
347
-            'ee-datepicker',
348
-            'jquery-ui-datepicker',
349
-            'jquery-ui-draggable',
350
-            'ee-dialog',
351
-            'ee-accounting',
352
-            'ee-serialize-full-array'
353
-        ), EVENT_ESPRESSO_VERSION, true);
354
-        wp_enqueue_script('espresso_txn');
355
-
356
-    }
357
-
358
-
359
-    /**
360
-     *    load_scripts_styles_view_transaction
361
-     *
362
-     * @access public
363
-     * @return void
364
-     */
365
-    public function load_scripts_styles_view_transaction()
366
-    {
367
-        //styles
368
-        wp_enqueue_style('espresso-ui-theme');
369
-    }
370
-
371
-
372
-    /**
373
-     *    load_scripts_styles_default
374
-     *
375
-     * @access public
376
-     * @return void
377
-     */
378
-    public function load_scripts_styles_default()
379
-    {
380
-        //styles
381
-        wp_enqueue_style('espresso-ui-theme');
382
-    }
383
-
384
-
385
-    /**
386
-     *    _set_list_table_views_default
387
-     *
388
-     * @access protected
389
-     * @return void
390
-     */
391
-    protected function _set_list_table_views_default()
392
-    {
393
-        $this->_views = array(
394
-            'all'       => array(
395
-                'slug'  => 'all',
396
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
397
-                'count' => 0
398
-            ),
399
-            'abandoned' => array(
400
-                'slug'  => 'abandoned',
401
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
402
-                'count' => 0
403
-            ),
404
-            'failed'    => array(
405
-                'slug'  => 'failed',
406
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
407
-                'count' => 0
408
-            )
409
-        );
410
-    }
411
-
412
-
413
-    /**
414
-     * _set_transaction_object
415
-     * This sets the _transaction property for the transaction details screen
416
-     *
417
-     * @access private
418
-     * @return void
419
-     */
420
-    private function _set_transaction_object()
421
-    {
422
-        if (is_object($this->_transaction)) {
423
-            return;
424
-        } //get out we've already set the object
425
-
426
-        $TXN = EEM_Transaction::instance();
427
-
428
-        $TXN_ID = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
429
-
430
-        //get transaction object
431
-        $this->_transaction = $TXN->get_one_by_ID($TXN_ID);
432
-        $this->_session     = ! empty($this->_transaction) ? $this->_transaction->get('TXN_session_data') : null;
433
-        $this->_transaction->verify_abandoned_transaction_status();
434
-
435
-        if (empty($this->_transaction)) {
436
-            $error_msg = esc_html__('An error occurred and the details for Transaction ID #',
437
-                    'event_espresso') . $TXN_ID . esc_html__(' could not be retrieved.', 'event_espresso');
438
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
439
-        }
440
-    }
441
-
442
-
443
-    /**
444
-     *    _transaction_legend_items
445
-     *
446
-     * @access protected
447
-     * @return array
448
-     */
449
-    protected function _transaction_legend_items()
450
-    {
451
-        EE_Registry::instance()->load_helper('MSG_Template');
452
-        $items = array();
453
-
454
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
-                $items['view_related_messages'] = array(
458
-                    'class' => $related_for_icon['css_class'],
459
-                    'desc'  => $related_for_icon['label'],
460
-                );
461
-            }
462
-        }
463
-
464
-        $items = apply_filters(
465
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
466
-            array_merge($items,
467
-                array(
468
-                    'view_details'      => array(
469
-                        'class' => 'dashicons dashicons-cart',
470
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso')
471
-                    ),
472
-                    'view_invoice'      => array(
473
-                        'class' => 'dashicons dashicons-media-spreadsheet',
474
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso')
475
-                    ),
476
-                    'view_receipt'      => array(
477
-                        'class' => 'dashicons dashicons-media-default',
478
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso')
479
-                    ),
480
-                    'view_registration' => array(
481
-                        'class' => 'dashicons dashicons-clipboard',
482
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso')
483
-                    ),
484
-                    'payment_overview_link' => array(
485
-                        'class' => 'dashicons dashicons-money',
486
-                        'desc' => esc_html__('Make Payment on Frontend', 'event_espresso')
487
-                    )
488
-                )
489
-            )
490
-        );
491
-
492
-        if (EE_Registry::instance()->CAP->current_user_can('ee_send_message',
493
-            'espresso_transactions_send_payment_reminder')
494
-        ) {
495
-            if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
496
-                $items['send_payment_reminder'] = array(
497
-                    'class' => 'dashicons dashicons-email-alt',
498
-                    'desc'  => esc_html__('Send Payment Reminder', 'event_espresso')
499
-                );
500
-            } else {
501
-                $items['blank*'] = array(
502
-                    'class' => '',
503
-                    'desc'  => ''
504
-                );
505
-            }
506
-        } else {
507
-            $items['blank*'] = array(
508
-                'class' => '',
509
-                'desc'  => ''
510
-            );
511
-        }
512
-        $more_items = apply_filters(
513
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
514
-            array(
515
-                'overpaid'   => array(
516
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
517
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::overpaid_status_code, false, 'sentence')
518
-                ),
519
-                'complete'   => array(
520
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
521
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::complete_status_code, false, 'sentence')
522
-                ),
523
-                'incomplete' => array(
524
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
525
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::incomplete_status_code, false, 'sentence')
526
-                ),
527
-                'abandoned'  => array(
528
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
529
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::abandoned_status_code, false, 'sentence')
530
-                ),
531
-                'failed'     => array(
532
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
533
-                    'desc'  => EEH_Template::pretty_status(EEM_Transaction::failed_status_code, false, 'sentence')
534
-                )
535
-            )
536
-        );
537
-
538
-        return array_merge($items, $more_items);
539
-    }
540
-
541
-
542
-    /**
543
-     *    _transactions_overview_list_table
544
-     *
545
-     * @access protected
546
-     * @return void
547
-     */
548
-    protected function _transactions_overview_list_table()
549
-    {
550
-        $this->_admin_page_title                   = esc_html__('Transactions', 'event_espresso');
551
-        $event                                     = isset($this->_req_data['EVT_ID']) ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) : null;
552
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event ? sprintf(esc_html__('%sViewing Transactions for the Event: %s%s',
553
-            'event_espresso'), '<h3>',
554
-            '<a href="' . EE_Admin_Page::add_query_args_and_nonce(array('action' => 'edit', 'post' => $event->ID()),
555
-                EVENTS_ADMIN_URL) . '" title="' . esc_attr__('Click to Edit event',
556
-                'event_espresso') . '">' . $event->get('EVT_name') . '</a>', '</h3>') : '';
557
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
558
-        $this->display_admin_list_table_page_with_no_sidebar();
559
-    }
560
-
561
-
562
-    /**
563
-     *    _transaction_details
564
-     * generates HTML for the View Transaction Details Admin page
565
-     *
566
-     * @access protected
567
-     * @return void
568
-     */
569
-    protected function _transaction_details()
570
-    {
571
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
572
-
573
-        $this->_set_transaction_status_array();
574
-
575
-        $this->_template_args                      = array();
576
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
577
-
578
-        $this->_set_transaction_object();
579
-
580
-        $primary_registration = $this->_transaction->primary_registration();
581
-        $attendee             = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : null;
582
-
583
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
584
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
585
-
586
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
587
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
588
-
589
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
590
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
591
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
592
-
593
-        $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
594
-        $this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
595
-
596
-        if (
597
-            $attendee instanceof EE_Attendee
598
-            && EE_Registry::instance()->CAP->current_user_can(
599
-                'ee_send_message',
600
-                'espresso_transactions_send_payment_reminder'
601
-            )
602
-        ) {
603
-            $this->_template_args['send_payment_reminder_button'] =
604
-                EEH_MSG_Template::is_mt_active('payment_reminder')
605
-                && $this->_transaction->get('STS_ID') != EEM_Transaction::complete_status_code
606
-                && $this->_transaction->get('STS_ID') != EEM_Transaction::overpaid_status_code
607
-                    ? EEH_Template::get_button_or_link(
608
-                    EE_Admin_Page::add_query_args_and_nonce(
609
-                        array(
610
-                            'action'      => 'send_payment_reminder',
611
-                            'TXN_ID'      => $this->_transaction->ID(),
612
-                            'redirect_to' => 'view_transaction'
613
-                        ),
614
-                        TXN_ADMIN_URL
615
-                    ),
616
-                    __(' Send Payment Reminder', 'event_espresso'),
617
-                    'button secondary-button right',
618
-                    'dashicons dashicons-email-alt'
619
-                )
620
-                    : '';
621
-        } else {
622
-            $this->_template_args['send_payment_reminder_button'] = '';
623
-        }
624
-
625
-        $amount_due                         = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
626
-        $this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, true);
627
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
628
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign . $this->_template_args['amount_due'];
629
-        } else {
630
-            $this->_template_args['amount_due'] = $this->_template_args['amount_due'] . EE_Registry::instance()->CFG->currency->sign;
631
-        }
632
-        $this->_template_args['amount_due_class'] = '';
633
-
634
-        if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
635
-            // paid in full
636
-            $this->_template_args['amount_due'] = false;
637
-        } elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
638
-            // overpaid
639
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
640
-        } elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') > 0)) {
641
-            // monies owing
642
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
643
-        } elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') == 0)) {
644
-            // no payments made yet
645
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
646
-        } elseif ($this->_transaction->get('TXN_total') == 0) {
647
-            // free event
648
-            $this->_template_args['amount_due'] = false;
649
-        }
650
-
651
-        $payment_method = $this->_transaction->payment_method();
652
-
653
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
654
-            ? $payment_method->admin_name()
655
-            : esc_html__('Unknown', 'event_espresso');
656
-
657
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
658
-        // link back to overview
659
-        $this->_template_args['txn_overview_url'] = ! empty ($_SERVER['HTTP_REFERER'])
660
-            ? $_SERVER['HTTP_REFERER']
661
-            : TXN_ADMIN_URL;
662
-
663
-
664
-        // next link
665
-        $next_txn                                 = $this->_transaction->next(
666
-            null,
667
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
668
-            'TXN_ID'
669
-        );
670
-        $this->_template_args['next_transaction'] = $next_txn
671
-            ? $this->_next_link(
672
-                EE_Admin_Page::add_query_args_and_nonce(
673
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
674
-                    TXN_ADMIN_URL
675
-                ),
676
-                'dashicons dashicons-arrow-right ee-icon-size-22'
677
-            )
678
-            : '';
679
-        // previous link
680
-        $previous_txn                                 = $this->_transaction->previous(
681
-            null,
682
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
683
-            'TXN_ID'
684
-        );
685
-        $this->_template_args['previous_transaction'] = $previous_txn
686
-            ? $this->_previous_link(
687
-                EE_Admin_Page::add_query_args_and_nonce(
688
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
689
-                    TXN_ADMIN_URL
690
-                ),
691
-                'dashicons dashicons-arrow-left ee-icon-size-22'
692
-            )
693
-            : '';
694
-
695
-        // were we just redirected here after adding a new registration ???
696
-        if (
697
-        isset(
698
-            $this->_req_data['redirect_from'],
699
-            $this->_req_data['EVT_ID'],
700
-            $this->_req_data['event_name']
701
-        )
702
-        ) {
703
-            if (
704
-            EE_Registry::instance()->CAP->current_user_can(
705
-                'ee_edit_registrations',
706
-                'espresso_registrations_new_registration',
707
-                $this->_req_data['EVT_ID']
708
-            )
709
-            ) {
710
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
711
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
712
-                    array(
713
-                        'page'     => 'espresso_registrations',
714
-                        'action'   => 'new_registration',
715
-                        'return'   => 'default',
716
-                        'TXN_ID'   => $this->_transaction->ID(),
717
-                        'event_id' => $this->_req_data['EVT_ID'],
718
-                    ),
719
-                    REG_ADMIN_URL
720
-                );
721
-                $this->_admin_page_title .= '">';
722
-
723
-                $this->_admin_page_title .= sprintf(
724
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
725
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
726
-                );
727
-                $this->_admin_page_title .= '</a>';
728
-            }
729
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
730
-        }
731
-        // grab messages at the last second
732
-        $this->_template_args['notices'] = EE_Error::get_notices();
733
-        // path to template
734
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
735
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template($template_path,
736
-            $this->_template_args, true);
737
-
738
-        // the details template wrapper
739
-        $this->display_admin_page_with_sidebar();
740
-
741
-    }
742
-
743
-
744
-    /**
745
-     *        _transaction_details_metaboxes
746
-     *
747
-     * @access protected
748
-     * @return void
749
-     */
750
-    protected function _transaction_details_metaboxes()
751
-    {
752
-
753
-        $this->_set_transaction_object();
754
-
755
-        add_meta_box('edit-txn-details-mbox', esc_html__('Transaction Details', 'event_espresso'),
756
-            array($this, 'txn_details_meta_box'), $this->_wp_page_slug, 'normal', 'high');
757
-        add_meta_box(
758
-            'edit-txn-attendees-mbox',
759
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
760
-            array($this, 'txn_attendees_meta_box'),
761
-            $this->_wp_page_slug,
762
-            'normal',
763
-            'high',
764
-            array('TXN_ID' => $this->_transaction->ID())
765
-        );
766
-        add_meta_box('edit-txn-registrant-mbox', esc_html__('Primary Contact', 'event_espresso'),
767
-            array($this, 'txn_registrant_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
768
-        add_meta_box('edit-txn-billing-info-mbox', esc_html__('Billing Information', 'event_espresso'),
769
-            array($this, 'txn_billing_info_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
770
-
771
-    }
772
-
773
-
774
-    /**
775
-     * txn_details_meta_box
776
-     * generates HTML for the Transaction main meta box
777
-     *
778
-     * @access public
779
-     * @return void
780
-     */
781
-    public function txn_details_meta_box()
782
-    {
783
-
784
-        $this->_set_transaction_object();
785
-        $this->_template_args['TXN_ID']   = $this->_transaction->ID();
786
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->attendee() : null;
787
-
788
-        //get line table
789
-        EEH_Autoloader::register_line_item_display_autoloaders();
790
-        $Line_Item_Display                       = new EE_Line_Item_Display('admin_table',
791
-            'EE_Admin_Table_Line_Item_Display_Strategy');
792
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item($this->_transaction->total_line_item());
793
-        $this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')->get('REG_code');
794
-
795
-        // process taxes
796
-        $taxes                         = $this->_transaction->get_many_related('Line_Item',
797
-            array(array('LIN_type' => EEM_Line_Item::type_tax)));
798
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
799
-
800
-        $this->_template_args['grand_total']     = EEH_Template::format_currency($this->_transaction->get('TXN_total'),
801
-            false, false);
802
-        $this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
803
-        $this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
30
+	/**
31
+	 * @var EE_Transaction
32
+	 */
33
+	private $_transaction;
34
+
35
+	/**
36
+	 * @var EE_Session
37
+	 */
38
+	private $_session;
39
+
40
+	/**
41
+	 * @var array $_txn_status
42
+	 */
43
+	private static $_txn_status;
44
+
45
+	/**
46
+	 * @var array $_pay_status
47
+	 */
48
+	private static $_pay_status;
49
+
50
+	/**
51
+	 * @var array $_existing_reg_payment_REG_IDs
52
+	 */
53
+	protected $_existing_reg_payment_REG_IDs = null;
54
+
55
+
56
+	/**
57
+	 * @Constructor
58
+	 * @access public
59
+	 *
60
+	 * @param bool $routing
61
+	 *
62
+	 * @return Transactions_Admin_Page
63
+	 */
64
+	public function __construct($routing = true)
65
+	{
66
+		parent::__construct($routing);
67
+	}
68
+
69
+
70
+	/**
71
+	 *    _init_page_props
72
+	 * @return void
73
+	 */
74
+	protected function _init_page_props()
75
+	{
76
+		$this->page_slug        = TXN_PG_SLUG;
77
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
78
+		$this->_admin_base_url  = TXN_ADMIN_URL;
79
+		$this->_admin_base_path = TXN_ADMIN;
80
+	}
81
+
82
+
83
+	/**
84
+	 *    _ajax_hooks
85
+	 * @return void
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
90
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
91
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
92
+	}
93
+
94
+
95
+	/**
96
+	 *    _define_page_props
97
+	 * @return void
98
+	 */
99
+	protected function _define_page_props()
100
+	{
101
+		$this->_admin_page_title = $this->page_label;
102
+		$this->_labels           = array(
103
+			'buttons' => array(
104
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
105
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
106
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
107
+			)
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 *        grab url requests and route them
114
+	 * @access private
115
+	 * @return void
116
+	 */
117
+	public function _set_page_routes()
118
+	{
119
+
120
+		$this->_set_transaction_status_array();
121
+
122
+		$txn_id = ! empty($this->_req_data['TXN_ID']) && ! is_array($this->_req_data['TXN_ID']) ? $this->_req_data['TXN_ID'] : 0;
123
+
124
+		$this->_page_routes = array(
125
+
126
+			'default' => array(
127
+				'func'       => '_transactions_overview_list_table',
128
+				'capability' => 'ee_read_transactions'
129
+			),
130
+
131
+			'view_transaction' => array(
132
+				'func'       => '_transaction_details',
133
+				'capability' => 'ee_read_transaction',
134
+				'obj_id'     => $txn_id
135
+			),
136
+
137
+			'send_payment_reminder' => array(
138
+				'func'       => '_send_payment_reminder',
139
+				'noheader'   => true,
140
+				'capability' => 'ee_send_message'
141
+			),
142
+
143
+			'espresso_apply_payment' => array(
144
+				'func'       => 'apply_payments_or_refunds',
145
+				'noheader'   => true,
146
+				'capability' => 'ee_edit_payments'
147
+			),
148
+
149
+			'espresso_apply_refund' => array(
150
+				'func'       => 'apply_payments_or_refunds',
151
+				'noheader'   => true,
152
+				'capability' => 'ee_edit_payments'
153
+			),
154
+
155
+			'espresso_delete_payment' => array(
156
+				'func'       => 'delete_payment',
157
+				'noheader'   => true,
158
+				'capability' => 'ee_delete_payments'
159
+			),
160
+
161
+		);
162
+
163
+	}
164
+
165
+
166
+	protected function _set_page_config()
167
+	{
168
+		$this->_page_config = array(
169
+			'default'          => array(
170
+				'nav'           => array(
171
+					'label' => esc_html__('Overview', 'event_espresso'),
172
+					'order' => 10
173
+				),
174
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
175
+				'help_tabs'     => array(
176
+					'transactions_overview_help_tab'                       => array(
177
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
178
+						'filename' => 'transactions_overview'
179
+					),
180
+					'transactions_overview_table_column_headings_help_tab' => array(
181
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
182
+						'filename' => 'transactions_overview_table_column_headings'
183
+					),
184
+					'transactions_overview_views_filters_help_tab'         => array(
185
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
186
+						'filename' => 'transactions_overview_views_filters_search'
187
+					),
188
+				),
189
+				'help_tour'     => array('Transactions_Overview_Help_Tour'),
190
+				/**
191
+				 * commented out because currently we are not displaying tips for transaction list table status but this
192
+				 * may change in a later iteration so want to keep the code for then.
193
+				 */
194
+				//'qtips' => array( 'Transactions_List_Table_Tips' ),
195
+				'require_nonce' => false
196
+			),
197
+			'view_transaction' => array(
198
+				'nav'       => array(
199
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
200
+					'order'      => 5,
201
+					'url'        => isset($this->_req_data['TXN_ID']) ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']),
202
+						$this->_current_page_view_url) : $this->_admin_base_url,
203
+					'persistent' => false
204
+				),
205
+				'help_tabs' => array(
206
+					'transactions_view_transaction_help_tab'                                              => array(
207
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
208
+						'filename' => 'transactions_view_transaction'
209
+					),
210
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
+						'filename' => 'transactions_view_transaction_transaction_details_table'
213
+					),
214
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
+						'filename' => 'transactions_view_transaction_attendees_registered'
217
+					),
218
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information'
221
+					),
222
+				),
223
+				'qtips'     => array('Transaction_Details_Tips'),
224
+				'help_tour' => array('Transaction_Details_Help_Tour'),
225
+				'metaboxes' => array('_transaction_details_metaboxes'),
226
+
227
+				'require_nonce' => false
228
+			)
229
+		);
230
+	}
231
+
232
+
233
+	/**
234
+	 * The below methods aren't used by this class currently
235
+	 */
236
+	protected function _add_screen_options()
237
+	{
238
+	}
239
+
240
+	protected function _add_feature_pointers()
241
+	{
242
+	}
243
+
244
+	public function admin_init()
245
+	{
246
+		// IF a registration was JUST added via the admin...
247
+		if (
248
+		isset(
249
+			$this->_req_data['redirect_from'],
250
+			$this->_req_data['EVT_ID'],
251
+			$this->_req_data['event_name']
252
+		)
253
+		) {
254
+			// then set a cookie so that we can block any attempts to use
255
+			// the back button as a way to enter another registration.
256
+			setcookie('ee_registration_added', $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/');
257
+			// and update the global
258
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
+		}
260
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__('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.',
261
+			'event_espresso');
262
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__('An error occurred! Please refresh the page and try again.',
263
+			'event_espresso');
264
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
265
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
266
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
267
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__('This transaction has been overpaid ! Payments Total',
268
+			'event_espresso');
269
+	}
270
+
271
+	public function admin_notices()
272
+	{
273
+	}
274
+
275
+	public function admin_footer_scripts()
276
+	{
277
+	}
278
+
279
+
280
+	/**
281
+	 * _set_transaction_status_array
282
+	 * sets list of transaction statuses
283
+	 *
284
+	 * @access private
285
+	 * @return void
286
+	 */
287
+	private function _set_transaction_status_array()
288
+	{
289
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
+	}
291
+
292
+
293
+	/**
294
+	 * get_transaction_status_array
295
+	 * return the transaction status array for wp_list_table
296
+	 *
297
+	 * @access public
298
+	 * @return array
299
+	 */
300
+	public function get_transaction_status_array()
301
+	{
302
+		return self::$_txn_status;
303
+	}
304
+
305
+
306
+	/**
307
+	 *    get list of payment statuses
308
+	 *
309
+	 * @access private
310
+	 * @return void
311
+	 */
312
+	private function _get_payment_status_array()
313
+	{
314
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
315
+		$this->_template_args['payment_status'] = self::$_pay_status;
316
+
317
+	}
318
+
319
+
320
+	/**
321
+	 *    _add_screen_options_default
322
+	 *
323
+	 * @access protected
324
+	 * @return void
325
+	 */
326
+	protected function _add_screen_options_default()
327
+	{
328
+		$this->_per_page_screen_option();
329
+	}
330
+
331
+
332
+	/**
333
+	 * load_scripts_styles
334
+	 *
335
+	 * @access public
336
+	 * @return void
337
+	 */
338
+	public function load_scripts_styles()
339
+	{
340
+		//enqueue style
341
+		wp_register_style('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.css', array(),
342
+			EVENT_ESPRESSO_VERSION);
343
+		wp_enqueue_style('espresso_txn');
344
+		//scripts
345
+		wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
346
+			'ee_admin_js',
347
+			'ee-datepicker',
348
+			'jquery-ui-datepicker',
349
+			'jquery-ui-draggable',
350
+			'ee-dialog',
351
+			'ee-accounting',
352
+			'ee-serialize-full-array'
353
+		), EVENT_ESPRESSO_VERSION, true);
354
+		wp_enqueue_script('espresso_txn');
355
+
356
+	}
357
+
358
+
359
+	/**
360
+	 *    load_scripts_styles_view_transaction
361
+	 *
362
+	 * @access public
363
+	 * @return void
364
+	 */
365
+	public function load_scripts_styles_view_transaction()
366
+	{
367
+		//styles
368
+		wp_enqueue_style('espresso-ui-theme');
369
+	}
370
+
371
+
372
+	/**
373
+	 *    load_scripts_styles_default
374
+	 *
375
+	 * @access public
376
+	 * @return void
377
+	 */
378
+	public function load_scripts_styles_default()
379
+	{
380
+		//styles
381
+		wp_enqueue_style('espresso-ui-theme');
382
+	}
383
+
384
+
385
+	/**
386
+	 *    _set_list_table_views_default
387
+	 *
388
+	 * @access protected
389
+	 * @return void
390
+	 */
391
+	protected function _set_list_table_views_default()
392
+	{
393
+		$this->_views = array(
394
+			'all'       => array(
395
+				'slug'  => 'all',
396
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
397
+				'count' => 0
398
+			),
399
+			'abandoned' => array(
400
+				'slug'  => 'abandoned',
401
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
402
+				'count' => 0
403
+			),
404
+			'failed'    => array(
405
+				'slug'  => 'failed',
406
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
407
+				'count' => 0
408
+			)
409
+		);
410
+	}
411
+
412
+
413
+	/**
414
+	 * _set_transaction_object
415
+	 * This sets the _transaction property for the transaction details screen
416
+	 *
417
+	 * @access private
418
+	 * @return void
419
+	 */
420
+	private function _set_transaction_object()
421
+	{
422
+		if (is_object($this->_transaction)) {
423
+			return;
424
+		} //get out we've already set the object
425
+
426
+		$TXN = EEM_Transaction::instance();
427
+
428
+		$TXN_ID = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
429
+
430
+		//get transaction object
431
+		$this->_transaction = $TXN->get_one_by_ID($TXN_ID);
432
+		$this->_session     = ! empty($this->_transaction) ? $this->_transaction->get('TXN_session_data') : null;
433
+		$this->_transaction->verify_abandoned_transaction_status();
434
+
435
+		if (empty($this->_transaction)) {
436
+			$error_msg = esc_html__('An error occurred and the details for Transaction ID #',
437
+					'event_espresso') . $TXN_ID . esc_html__(' could not be retrieved.', 'event_espresso');
438
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
439
+		}
440
+	}
441
+
442
+
443
+	/**
444
+	 *    _transaction_legend_items
445
+	 *
446
+	 * @access protected
447
+	 * @return array
448
+	 */
449
+	protected function _transaction_legend_items()
450
+	{
451
+		EE_Registry::instance()->load_helper('MSG_Template');
452
+		$items = array();
453
+
454
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
+				$items['view_related_messages'] = array(
458
+					'class' => $related_for_icon['css_class'],
459
+					'desc'  => $related_for_icon['label'],
460
+				);
461
+			}
462
+		}
463
+
464
+		$items = apply_filters(
465
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
466
+			array_merge($items,
467
+				array(
468
+					'view_details'      => array(
469
+						'class' => 'dashicons dashicons-cart',
470
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso')
471
+					),
472
+					'view_invoice'      => array(
473
+						'class' => 'dashicons dashicons-media-spreadsheet',
474
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso')
475
+					),
476
+					'view_receipt'      => array(
477
+						'class' => 'dashicons dashicons-media-default',
478
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso')
479
+					),
480
+					'view_registration' => array(
481
+						'class' => 'dashicons dashicons-clipboard',
482
+						'desc'  => esc_html__('View Registration Details', 'event_espresso')
483
+					),
484
+					'payment_overview_link' => array(
485
+						'class' => 'dashicons dashicons-money',
486
+						'desc' => esc_html__('Make Payment on Frontend', 'event_espresso')
487
+					)
488
+				)
489
+			)
490
+		);
491
+
492
+		if (EE_Registry::instance()->CAP->current_user_can('ee_send_message',
493
+			'espresso_transactions_send_payment_reminder')
494
+		) {
495
+			if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
496
+				$items['send_payment_reminder'] = array(
497
+					'class' => 'dashicons dashicons-email-alt',
498
+					'desc'  => esc_html__('Send Payment Reminder', 'event_espresso')
499
+				);
500
+			} else {
501
+				$items['blank*'] = array(
502
+					'class' => '',
503
+					'desc'  => ''
504
+				);
505
+			}
506
+		} else {
507
+			$items['blank*'] = array(
508
+				'class' => '',
509
+				'desc'  => ''
510
+			);
511
+		}
512
+		$more_items = apply_filters(
513
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
514
+			array(
515
+				'overpaid'   => array(
516
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
517
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::overpaid_status_code, false, 'sentence')
518
+				),
519
+				'complete'   => array(
520
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
521
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::complete_status_code, false, 'sentence')
522
+				),
523
+				'incomplete' => array(
524
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
525
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::incomplete_status_code, false, 'sentence')
526
+				),
527
+				'abandoned'  => array(
528
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
529
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::abandoned_status_code, false, 'sentence')
530
+				),
531
+				'failed'     => array(
532
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
533
+					'desc'  => EEH_Template::pretty_status(EEM_Transaction::failed_status_code, false, 'sentence')
534
+				)
535
+			)
536
+		);
537
+
538
+		return array_merge($items, $more_items);
539
+	}
540
+
541
+
542
+	/**
543
+	 *    _transactions_overview_list_table
544
+	 *
545
+	 * @access protected
546
+	 * @return void
547
+	 */
548
+	protected function _transactions_overview_list_table()
549
+	{
550
+		$this->_admin_page_title                   = esc_html__('Transactions', 'event_espresso');
551
+		$event                                     = isset($this->_req_data['EVT_ID']) ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) : null;
552
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event ? sprintf(esc_html__('%sViewing Transactions for the Event: %s%s',
553
+			'event_espresso'), '<h3>',
554
+			'<a href="' . EE_Admin_Page::add_query_args_and_nonce(array('action' => 'edit', 'post' => $event->ID()),
555
+				EVENTS_ADMIN_URL) . '" title="' . esc_attr__('Click to Edit event',
556
+				'event_espresso') . '">' . $event->get('EVT_name') . '</a>', '</h3>') : '';
557
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
558
+		$this->display_admin_list_table_page_with_no_sidebar();
559
+	}
560
+
561
+
562
+	/**
563
+	 *    _transaction_details
564
+	 * generates HTML for the View Transaction Details Admin page
565
+	 *
566
+	 * @access protected
567
+	 * @return void
568
+	 */
569
+	protected function _transaction_details()
570
+	{
571
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
572
+
573
+		$this->_set_transaction_status_array();
574
+
575
+		$this->_template_args                      = array();
576
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
577
+
578
+		$this->_set_transaction_object();
579
+
580
+		$primary_registration = $this->_transaction->primary_registration();
581
+		$attendee             = $primary_registration instanceof EE_Registration ? $primary_registration->attendee() : null;
582
+
583
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
584
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
585
+
586
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
587
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
588
+
589
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
590
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
591
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
592
+
593
+		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
594
+		$this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
595
+
596
+		if (
597
+			$attendee instanceof EE_Attendee
598
+			&& EE_Registry::instance()->CAP->current_user_can(
599
+				'ee_send_message',
600
+				'espresso_transactions_send_payment_reminder'
601
+			)
602
+		) {
603
+			$this->_template_args['send_payment_reminder_button'] =
604
+				EEH_MSG_Template::is_mt_active('payment_reminder')
605
+				&& $this->_transaction->get('STS_ID') != EEM_Transaction::complete_status_code
606
+				&& $this->_transaction->get('STS_ID') != EEM_Transaction::overpaid_status_code
607
+					? EEH_Template::get_button_or_link(
608
+					EE_Admin_Page::add_query_args_and_nonce(
609
+						array(
610
+							'action'      => 'send_payment_reminder',
611
+							'TXN_ID'      => $this->_transaction->ID(),
612
+							'redirect_to' => 'view_transaction'
613
+						),
614
+						TXN_ADMIN_URL
615
+					),
616
+					__(' Send Payment Reminder', 'event_espresso'),
617
+					'button secondary-button right',
618
+					'dashicons dashicons-email-alt'
619
+				)
620
+					: '';
621
+		} else {
622
+			$this->_template_args['send_payment_reminder_button'] = '';
623
+		}
624
+
625
+		$amount_due                         = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
626
+		$this->_template_args['amount_due'] = EEH_Template::format_currency($amount_due, true);
627
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
628
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign . $this->_template_args['amount_due'];
629
+		} else {
630
+			$this->_template_args['amount_due'] = $this->_template_args['amount_due'] . EE_Registry::instance()->CFG->currency->sign;
631
+		}
632
+		$this->_template_args['amount_due_class'] = '';
633
+
634
+		if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
635
+			// paid in full
636
+			$this->_template_args['amount_due'] = false;
637
+		} elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
638
+			// overpaid
639
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
640
+		} elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') > 0)) {
641
+			// monies owing
642
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
643
+		} elseif (($this->_transaction->get('TXN_total') > 0) && ($this->_transaction->get('TXN_paid') == 0)) {
644
+			// no payments made yet
645
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
646
+		} elseif ($this->_transaction->get('TXN_total') == 0) {
647
+			// free event
648
+			$this->_template_args['amount_due'] = false;
649
+		}
650
+
651
+		$payment_method = $this->_transaction->payment_method();
652
+
653
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
654
+			? $payment_method->admin_name()
655
+			: esc_html__('Unknown', 'event_espresso');
656
+
657
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
658
+		// link back to overview
659
+		$this->_template_args['txn_overview_url'] = ! empty ($_SERVER['HTTP_REFERER'])
660
+			? $_SERVER['HTTP_REFERER']
661
+			: TXN_ADMIN_URL;
662
+
663
+
664
+		// next link
665
+		$next_txn                                 = $this->_transaction->next(
666
+			null,
667
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
668
+			'TXN_ID'
669
+		);
670
+		$this->_template_args['next_transaction'] = $next_txn
671
+			? $this->_next_link(
672
+				EE_Admin_Page::add_query_args_and_nonce(
673
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
674
+					TXN_ADMIN_URL
675
+				),
676
+				'dashicons dashicons-arrow-right ee-icon-size-22'
677
+			)
678
+			: '';
679
+		// previous link
680
+		$previous_txn                                 = $this->_transaction->previous(
681
+			null,
682
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
683
+			'TXN_ID'
684
+		);
685
+		$this->_template_args['previous_transaction'] = $previous_txn
686
+			? $this->_previous_link(
687
+				EE_Admin_Page::add_query_args_and_nonce(
688
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
689
+					TXN_ADMIN_URL
690
+				),
691
+				'dashicons dashicons-arrow-left ee-icon-size-22'
692
+			)
693
+			: '';
694
+
695
+		// were we just redirected here after adding a new registration ???
696
+		if (
697
+		isset(
698
+			$this->_req_data['redirect_from'],
699
+			$this->_req_data['EVT_ID'],
700
+			$this->_req_data['event_name']
701
+		)
702
+		) {
703
+			if (
704
+			EE_Registry::instance()->CAP->current_user_can(
705
+				'ee_edit_registrations',
706
+				'espresso_registrations_new_registration',
707
+				$this->_req_data['EVT_ID']
708
+			)
709
+			) {
710
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
711
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
712
+					array(
713
+						'page'     => 'espresso_registrations',
714
+						'action'   => 'new_registration',
715
+						'return'   => 'default',
716
+						'TXN_ID'   => $this->_transaction->ID(),
717
+						'event_id' => $this->_req_data['EVT_ID'],
718
+					),
719
+					REG_ADMIN_URL
720
+				);
721
+				$this->_admin_page_title .= '">';
722
+
723
+				$this->_admin_page_title .= sprintf(
724
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
725
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
726
+				);
727
+				$this->_admin_page_title .= '</a>';
728
+			}
729
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
730
+		}
731
+		// grab messages at the last second
732
+		$this->_template_args['notices'] = EE_Error::get_notices();
733
+		// path to template
734
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
735
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template($template_path,
736
+			$this->_template_args, true);
737
+
738
+		// the details template wrapper
739
+		$this->display_admin_page_with_sidebar();
740
+
741
+	}
742
+
743
+
744
+	/**
745
+	 *        _transaction_details_metaboxes
746
+	 *
747
+	 * @access protected
748
+	 * @return void
749
+	 */
750
+	protected function _transaction_details_metaboxes()
751
+	{
752
+
753
+		$this->_set_transaction_object();
754
+
755
+		add_meta_box('edit-txn-details-mbox', esc_html__('Transaction Details', 'event_espresso'),
756
+			array($this, 'txn_details_meta_box'), $this->_wp_page_slug, 'normal', 'high');
757
+		add_meta_box(
758
+			'edit-txn-attendees-mbox',
759
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
760
+			array($this, 'txn_attendees_meta_box'),
761
+			$this->_wp_page_slug,
762
+			'normal',
763
+			'high',
764
+			array('TXN_ID' => $this->_transaction->ID())
765
+		);
766
+		add_meta_box('edit-txn-registrant-mbox', esc_html__('Primary Contact', 'event_espresso'),
767
+			array($this, 'txn_registrant_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
768
+		add_meta_box('edit-txn-billing-info-mbox', esc_html__('Billing Information', 'event_espresso'),
769
+			array($this, 'txn_billing_info_side_meta_box'), $this->_wp_page_slug, 'side', 'high');
770
+
771
+	}
772
+
773
+
774
+	/**
775
+	 * txn_details_meta_box
776
+	 * generates HTML for the Transaction main meta box
777
+	 *
778
+	 * @access public
779
+	 * @return void
780
+	 */
781
+	public function txn_details_meta_box()
782
+	{
783
+
784
+		$this->_set_transaction_object();
785
+		$this->_template_args['TXN_ID']   = $this->_transaction->ID();
786
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->attendee() : null;
787
+
788
+		//get line table
789
+		EEH_Autoloader::register_line_item_display_autoloaders();
790
+		$Line_Item_Display                       = new EE_Line_Item_Display('admin_table',
791
+			'EE_Admin_Table_Line_Item_Display_Strategy');
792
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item($this->_transaction->total_line_item());
793
+		$this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')->get('REG_code');
794
+
795
+		// process taxes
796
+		$taxes                         = $this->_transaction->get_many_related('Line_Item',
797
+			array(array('LIN_type' => EEM_Line_Item::type_tax)));
798
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
799
+
800
+		$this->_template_args['grand_total']     = EEH_Template::format_currency($this->_transaction->get('TXN_total'),
801
+			false, false);
802
+		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
803
+		$this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
804 804
 
805 805
 //		$txn_status_class = 'status-' . $this->_transaction->get('STS_ID');
806 806
 
807
-        // process payment details
808
-        $payments = $this->_transaction->get_many_related('Payment');
809
-        if ( ! empty($payments)) {
810
-            $this->_template_args['payments']              = $payments;
811
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
812
-        } else {
813
-            $this->_template_args['payments']              = false;
814
-            $this->_template_args['existing_reg_payments'] = array();
815
-        }
816
-
817
-        $this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
818
-        $this->_template_args['delete_payment_url'] = add_query_arg(array('action' => 'espresso_delete_payment'),
819
-            TXN_ADMIN_URL);
820
-
821
-        if (isset($txn_details['invoice_number'])) {
822
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
823
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__('Invoice Number',
824
-                'event_espresso');
825
-        }
826
-
827
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction->get_first_related('Registration')->get('REG_session');
828
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__('Registration Session',
829
-            'event_espresso');
830
-
831
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '';
832
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__('Transaction placed from IP',
833
-            'event_espresso');
834
-
835
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '';
836
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__('Registrant User Agent',
837
-            'event_espresso');
838
-
839
-        $reg_steps = '<ul>';
840
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
841
-            if ($reg_step_status === true) {
842
-                $reg_steps .= '<li style="color:#70cc50">' . sprintf(esc_html__('%1$s : Completed', 'event_espresso'),
843
-                        ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
844
-            } else if (is_numeric($reg_step_status) && $reg_step_status !== false) {
845
-                $reg_steps .= '<li style="color:#2EA2CC">' . sprintf(
846
-                        esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
847
-                        ucwords(str_replace('_', ' ', $reg_step)),
848
-                        date(get_option('date_format') . ' ' . get_option('time_format'),
849
-                            ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)))
850
-                    ) . '</li>';
851
-            } else {
852
-                $reg_steps .= '<li style="color:#E76700">' . sprintf(esc_html__('%1$s : Never Initiated',
853
-                        'event_espresso'), ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
854
-            }
855
-        }
856
-        $reg_steps .= '</ul>';
857
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
858
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__('Registration Step Progress',
859
-            'event_espresso');
860
-
861
-
862
-        $this->_get_registrations_to_apply_payment_to();
863
-        $this->_get_payment_methods($payments);
864
-        $this->_get_payment_status_array();
865
-        $this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
866
-
867
-        $this->_template_args['transaction_form_url']    = add_query_arg(array(
868
-            'action'  => 'edit_transaction',
869
-            'process' => 'transaction'
870
-        ), TXN_ADMIN_URL);
871
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(array(
872
-            'page'   => 'espresso_transactions',
873
-            'action' => 'espresso_apply_payment'
874
-        ), WP_AJAX_URL);
875
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(array(
876
-            'page'   => 'espresso_transactions',
877
-            'action' => 'espresso_delete_payment'
878
-        ), WP_AJAX_URL);
879
-
880
-        // 'espresso_delete_payment_nonce'
881
-
882
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
883
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
884
-
885
-    }
886
-
887
-
888
-    /**
889
-     * _get_registration_payment_IDs
890
-     *
891
-     *    generates an array of Payment IDs and their corresponding Registration IDs
892
-     *
893
-     * @access protected
894
-     *
895
-     * @param EE_Payment[] $payments
896
-     *
897
-     * @return array
898
-     */
899
-    protected function _get_registration_payment_IDs($payments = array())
900
-    {
901
-        $existing_reg_payments = array();
902
-        // get all reg payments for these payments
903
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(array(
904
-            array(
905
-                'PAY_ID' => array(
906
-                    'IN',
907
-                    array_keys($payments)
908
-                )
909
-            )
910
-        ));
911
-        if ( ! empty($reg_payments)) {
912
-            foreach ($payments as $payment) {
913
-                if ( ! $payment instanceof EE_Payment) {
914
-                    continue;
915
-                } else if ( ! isset($existing_reg_payments[$payment->ID()])) {
916
-                    $existing_reg_payments[$payment->ID()] = array();
917
-                }
918
-                foreach ($reg_payments as $reg_payment) {
919
-                    if ($reg_payment instanceof EE_Registration_Payment && $reg_payment->payment_ID() === $payment->ID()) {
920
-                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
921
-                    }
922
-                }
923
-            }
924
-        }
925
-
926
-        return $existing_reg_payments;
927
-    }
928
-
929
-
930
-    /**
931
-     * _get_registrations_to_apply_payment_to
932
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
933
-     * which allows the admin to only apply the payment to the specific registrations
934
-     *
935
-     * @access protected
936
-     * @return void
937
-     * @throws \EE_Error
938
-     */
939
-    protected function _get_registrations_to_apply_payment_to()
940
-    {
941
-        // we want any registration with an active status (ie: not deleted or cancelled)
942
-        $query_params                      = array(
943
-            array(
944
-                'STS_ID' => array(
945
-                    'IN',
946
-                    array(
947
-                        EEM_Registration::status_id_approved,
948
-                        EEM_Registration::status_id_pending_payment,
949
-                        EEM_Registration::status_id_not_approved,
950
-                    )
951
-                )
952
-            )
953
-        );
954
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
955
-                '', 'txn-admin-apply-payment-to-registrations-dv', '', 'clear: both; margin: 1.5em 0 0; display: none;'
956
-            );
957
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
958
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
959
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
960
-            EEH_HTML::tr(
961
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
962
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
963
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
964
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
965
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
966
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
967
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
968
-            )
969
-        );
970
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
971
-        // get registrations for TXN
972
-        $registrations = $this->_transaction->registrations($query_params);
973
-        foreach ($registrations as $registration) {
974
-            if ($registration instanceof EE_Registration) {
975
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
976
-                    ? $registration->attendee()->full_name()
977
-                    : esc_html__('Unknown Attendee', 'event_espresso');
978
-                $owing         = $registration->final_price() - $registration->paid();
979
-                $taxable       = $registration->ticket()->taxable()
980
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
981
-                    : '';
982
-                $checked       = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
983
-                    ? ' checked="checked"'
984
-                    : '';
985
-                $disabled      = $registration->final_price() > 0 ? '' : ' disabled';
986
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
987
-                    EEH_HTML::td($registration->ID()) .
988
-                    EEH_HTML::td($attendee_name) .
989
-                    EEH_HTML::td(
990
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
991
-                    ) .
992
-                    EEH_HTML::td($registration->event_name()) .
993
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
994
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
995
-                    EEH_HTML::td(
996
-                        '<input type="checkbox" value="' . $registration->ID()
997
-                        . '" name="txn_admin_payment[registrations]"'
998
-                        . $checked . $disabled . '>',
999
-                        '', 'jst-cntr'
1000
-                    ),
1001
-                    'apply-payment-registration-row-' . $registration->ID()
1002
-                );
1003
-            }
1004
-        }
1005
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1006
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1007
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1008
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1009
-            esc_html__(
1010
-                '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.',
1011
-                'event_espresso'
1012
-            ),
1013
-            '', 'clear description'
1014
-        );
1015
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1016
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * _get_reg_status_selection
1022
-     *
1023
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1024
-     *         instead of events.
1025
-     * @access protected
1026
-     * @return void
1027
-     */
1028
-    protected function _get_reg_status_selection()
1029
-    {
1030
-        //first get all possible statuses
1031
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1032
-        //let's add a "don't change" option.
1033
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1034
-        $status_array                                        = array_merge($status_array, $statuses);
1035
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input('txn_reg_status_change[reg_status]',
1036
-            $status_array, 'NAN', 'id="txn-admin-payment-reg-status-inp"', 'txn-reg-status-change-reg-status');
1037
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input('delete_txn_reg_status_change[reg_status]',
1038
-            $status_array, 'NAN', 'delete-txn-admin-payment-reg-status-inp', 'delete-txn-reg-status-change-reg-status');
1039
-
1040
-    }
1041
-
1042
-
1043
-    /**
1044
-     *    _get_payment_methods
1045
-     * Gets all the payment methods available generally, or the ones that are already
1046
-     * selected on these payments (in case their payment methods are no longer active).
1047
-     * Has the side-effect of updating the template args' payment_methods item
1048
-     * @access private
1049
-     *
1050
-     * @param EE_Payment[] to show on this page
1051
-     *
1052
-     * @return void
1053
-     */
1054
-    private function _get_payment_methods($payments = array())
1055
-    {
1056
-        $payment_methods_of_payments = array();
1057
-        foreach ($payments as $payment) {
1058
-            if ($payment instanceof EE_Payment) {
1059
-                $payment_methods_of_payments[] = $payment->get('PMD_ID');
1060
-            }
1061
-        }
1062
-        if ($payment_methods_of_payments) {
1063
-            $query_args = array(
1064
-                array(
1065
-                    'OR*payment_method_for_payment' => array(
1066
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1067
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')
1068
-                    )
1069
-                )
1070
-            );
1071
-        } else {
1072
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1073
-        }
1074
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * txn_attendees_meta_box
1080
-     *    generates HTML for the Attendees Transaction main meta box
1081
-     *
1082
-     * @access public
1083
-     *
1084
-     * @param WP_Post $post
1085
-     * @param array   $metabox
1086
-     *
1087
-     * @return void
1088
-     */
1089
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1090
-    {
1091
-
1092
-        extract($metabox['args']);
1093
-        $this->_template_args['post']            = $post;
1094
-        $this->_template_args['event_attendees'] = array();
1095
-        // process items in cart
1096
-        $line_items = $this->_transaction->get_many_related('Line_Item', array(array('LIN_type' => 'line-item')));
1097
-        if ( ! empty($line_items)) {
1098
-            foreach ($line_items as $item) {
1099
-                if ($item instanceof EE_Line_Item) {
1100
-                    switch ($item->OBJ_type()) {
1101
-
1102
-                        case 'Event' :
1103
-                            break;
1104
-
1105
-                        case 'Ticket' :
1106
-                            $ticket = $item->ticket();
1107
-                            //right now we're only handling tickets here.  Cause its expected that only tickets will have attendees right?
1108
-                            if ( ! $ticket instanceof EE_Ticket) {
1109
-                                continue;
1110
-                            }
1111
-                            try {
1112
-                                $event_name = $ticket->get_event_name();
1113
-                            } catch (Exception $e) {
1114
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1115
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1116
-                            }
1117
-                            $event_name .= ' - ' . $item->get('LIN_name');
1118
-                            $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1119
-                            // now get all of the registrations for this transaction that use this ticket
1120
-                            $registrations = $ticket->get_many_related('Registration',
1121
-                                array(array('TXN_ID' => $this->_transaction->ID())));
1122
-                            foreach ($registrations as $registration) {
1123
-                                if ( ! $registration instanceof EE_Registration) {
1124
-                                    continue;
1125
-                                }
1126
-                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']            = $registration->status_ID();
1127
-                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']           = $registration->count();
1128
-                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] = $event_name;
1129
-                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']      = $ticket_price;
1130
-                                // attendee info
1131
-                                $attendee = $registration->get_first_related('Attendee');
1132
-                                if ($attendee instanceof EE_Attendee) {
1133
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = $attendee->ID();
1134
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = $attendee->full_name();
1135
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name . esc_html__(' Event',
1136
-                                            'event_espresso') . '">' . $attendee->email() . '</a>';
1137
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = EEH_Address::format($attendee,
1138
-                                        'inline', false, false);
1139
-                                } else {
1140
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1141
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1142
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1143
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1144
-                                }
1145
-                            }
1146
-                            break;
1147
-
1148
-                    }
1149
-                }
1150
-            }
1151
-
1152
-            $this->_template_args['transaction_form_url'] = add_query_arg(array(
1153
-                'action'  => 'edit_transaction',
1154
-                'process' => 'attendees'
1155
-            ), TXN_ADMIN_URL);
1156
-            echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1157
-                $this->_template_args, true);
1158
-
1159
-        } else {
1160
-            echo sprintf(
1161
-                esc_html__('%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1162
-                    'event_espresso'),
1163
-                '<p class="important-notice">',
1164
-                '</p>'
1165
-            );
1166
-        }
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * txn_registrant_side_meta_box
1172
-     * generates HTML for the Edit Transaction side meta box
1173
-     *
1174
-     * @access public
1175
-     * @throws \EE_Error
1176
-     * @return void
1177
-     */
1178
-    public function txn_registrant_side_meta_box()
1179
-    {
1180
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->get_first_related('Attendee') : null;
1181
-        if ( ! $primary_att instanceof EE_Attendee) {
1182
-            $this->_template_args['no_attendee_message'] = esc_html__('There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1183
-                'event_espresso');
1184
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1185
-        }
1186
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1187
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1188
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1189
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1190
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1191
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1192
-            'action' => 'edit_attendee',
1193
-            'post'   => $primary_att->ID()
1194
-        ), REG_ADMIN_URL);
1195
-        // get formatted address for registrant
1196
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1197
-        echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1198
-            $this->_template_args, true);
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * txn_billing_info_side_meta_box
1204
-     *    generates HTML for the Edit Transaction side meta box
1205
-     *
1206
-     * @access public
1207
-     * @return void
1208
-     */
1209
-    public function txn_billing_info_side_meta_box()
1210
-    {
1211
-
1212
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1213
-        $this->_template_args['billing_form_url'] = add_query_arg(
1214
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1215
-            TXN_ADMIN_URL
1216
-        );
1217
-
1218
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1219
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * apply_payments_or_refunds
1225
-     *    registers a payment or refund made towards a transaction
1226
-     *
1227
-     * @access public
1228
-     * @return void
1229
-     */
1230
-    public function apply_payments_or_refunds()
1231
-    {
1232
-        $json_response_data = array('return_data' => false);
1233
-        $valid_data         = $this->_validate_payment_request_data();
1234
-        if ( ! empty($valid_data)) {
1235
-            $PAY_ID = $valid_data['PAY_ID'];
1236
-            //save  the new payment
1237
-            $payment = $this->_create_payment_from_request_data($valid_data);
1238
-            // get the TXN for this payment
1239
-            $transaction = $payment->transaction();
1240
-            // verify transaction
1241
-            if ($transaction instanceof EE_Transaction) {
1242
-                // calculate_total_payments_and_update_status
1243
-                $this->_process_transaction_payments($transaction);
1244
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1245
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1246
-                // apply payment to registrations (if applicable)
1247
-                if ( ! empty($REG_IDs)) {
1248
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1249
-                    $this->_maybe_send_notifications();
1250
-                    // now process status changes for the same registrations
1251
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1252
-                }
1253
-                $this->_maybe_send_notifications($payment);
1254
-                //prepare to render page
1255
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1256
-                do_action('AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', $transaction,
1257
-                    $payment);
1258
-            } else {
1259
-                EE_Error::add_error(
1260
-                    esc_html__('A valid Transaction for this payment could not be retrieved.', 'event_espresso'),
1261
-                    __FILE__, __FUNCTION__, __LINE__
1262
-                );
1263
-            }
1264
-        } else {
1265
-            EE_Error::add_error(esc_html__('The payment form data could not be processed. Please try again.',
1266
-                'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1267
-        }
1268
-
1269
-        $notices              = EE_Error::get_notices(false, false, false);
1270
-        $this->_template_args = array(
1271
-            'data'    => $json_response_data,
1272
-            'error'   => $notices['errors'],
1273
-            'success' => $notices['success']
1274
-        );
1275
-        $this->_return_json();
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * _validate_payment_request_data
1281
-     *
1282
-     * @return array
1283
-     */
1284
-    protected function _validate_payment_request_data()
1285
-    {
1286
-        if ( ! isset($this->_req_data['txn_admin_payment'])) {
1287
-            return false;
1288
-        }
1289
-        $payment_form = $this->_generate_payment_form_section();
1290
-        try {
1291
-            if ($payment_form->was_submitted()) {
1292
-                $payment_form->receive_form_submission();
1293
-                if ( ! $payment_form->is_valid()) {
1294
-                    $submission_error_messages = array();
1295
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1296
-                        if ($validation_error instanceof EE_Validation_Error) {
1297
-                            $submission_error_messages[] = sprintf(
1298
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1299
-                                $validation_error->get_form_section()->html_label_text(),
1300
-                                $validation_error->getMessage()
1301
-                            );
1302
-                        }
1303
-                    }
1304
-                    EE_Error::add_error(join('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1305
-
1306
-                    return array();
1307
-                }
1308
-            }
1309
-        } catch (EE_Error $e) {
1310
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1311
-
1312
-            return array();
1313
-        }
1314
-
1315
-        return $payment_form->valid_data();
1316
-    }
1317
-
1318
-
1319
-    /**
1320
-     * _generate_payment_form_section
1321
-     *
1322
-     * @return EE_Form_Section_Proper
1323
-     */
1324
-    protected function _generate_payment_form_section()
1325
-    {
1326
-        return new EE_Form_Section_Proper(
1327
-            array(
1328
-                'name'        => 'txn_admin_payment',
1329
-                'subsections' => array(
1330
-                    'PAY_ID'          => new EE_Text_Input(
1331
-                        array(
1332
-                            'default'               => 0,
1333
-                            'required'              => false,
1334
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1335
-                            'validation_strategies' => array(new EE_Int_Normalization())
1336
-                        )
1337
-                    ),
1338
-                    'TXN_ID'          => new EE_Text_Input(
1339
-                        array(
1340
-                            'default'               => 0,
1341
-                            'required'              => true,
1342
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1343
-                            'validation_strategies' => array(new EE_Int_Normalization())
1344
-                        )
1345
-                    ),
1346
-                    'type'            => new EE_Text_Input(
1347
-                        array(
1348
-                            'default'               => 1,
1349
-                            'required'              => true,
1350
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1351
-                            'validation_strategies' => array(new EE_Int_Normalization())
1352
-                        )
1353
-                    ),
1354
-                    'amount'          => new EE_Text_Input(
1355
-                        array(
1356
-                            'default'               => 0,
1357
-                            'required'              => true,
1358
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1359
-                            'validation_strategies' => array(new EE_Float_Normalization())
1360
-                        )
1361
-                    ),
1362
-                    'status'          => new EE_Text_Input(
1363
-                        array(
1364
-                            'default'         => EEM_Payment::status_id_approved,
1365
-                            'required'        => true,
1366
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1367
-                        )
1368
-                    ),
1369
-                    'PMD_ID'          => new EE_Text_Input(
1370
-                        array(
1371
-                            'default'               => 2,
1372
-                            'required'              => true,
1373
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1374
-                            'validation_strategies' => array(new EE_Int_Normalization())
1375
-                        )
1376
-                    ),
1377
-                    'date'            => new EE_Text_Input(
1378
-                        array(
1379
-                            'default'         => time(),
1380
-                            'required'        => true,
1381
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1382
-                        )
1383
-                    ),
1384
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1385
-                        array(
1386
-                            'default'               => '',
1387
-                            'required'              => false,
1388
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1389
-                            'validation_strategies' => array(
1390
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1391
-                                    100),
1392
-                            )
1393
-                        )
1394
-                    ),
1395
-                    'po_number'       => new EE_Text_Input(
1396
-                        array(
1397
-                            'default'               => '',
1398
-                            'required'              => false,
1399
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1400
-                            'validation_strategies' => array(
1401
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1402
-                                    100),
1403
-                            )
1404
-                        )
1405
-                    ),
1406
-                    'accounting'      => new EE_Text_Input(
1407
-                        array(
1408
-                            'default'               => '',
1409
-                            'required'              => false,
1410
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1411
-                            'validation_strategies' => array(
1412
-                                new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1413
-                                    100),
1414
-                            )
1415
-                        )
1416
-                    ),
1417
-                )
1418
-            )
1419
-        );
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * _create_payment_from_request_data
1425
-     *
1426
-     * @param array $valid_data
1427
-     *
1428
-     * @return EE_Payment
1429
-     */
1430
-    protected function _create_payment_from_request_data($valid_data)
1431
-    {
1432
-        $PAY_ID = $valid_data['PAY_ID'];
1433
-        // get payment amount
1434
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1435
-        // payments have a type value of 1 and refunds have a type value of -1
1436
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1437
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1438
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1439
-        $date    = $valid_data['date'] ? preg_replace('/\s+/', ' ', $valid_data['date']) : date('Y-m-d g:i a',
1440
-            current_time('timestamp'));
1441
-        $payment = EE_Payment::new_instance(
1442
-            array(
1443
-                'TXN_ID'              => $valid_data['TXN_ID'],
1444
-                'STS_ID'              => $valid_data['status'],
1445
-                'PAY_timestamp'       => $date,
1446
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1447
-                'PMD_ID'              => $valid_data['PMD_ID'],
1448
-                'PAY_amount'          => $amount,
1449
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1450
-                'PAY_po_number'       => $valid_data['po_number'],
1451
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1452
-                'PAY_details'         => $valid_data,
1453
-                'PAY_ID'              => $PAY_ID
1454
-            ),
1455
-            '',
1456
-            array('Y-m-d', 'g:i a')
1457
-        );
1458
-
1459
-        if ( ! $payment->save()) {
1460
-            EE_Error::add_error(
1461
-                sprintf(
1462
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1463
-                    $payment->ID()
1464
-                ),
1465
-                __FILE__, __FUNCTION__, __LINE__
1466
-            );
1467
-        }
1468
-
1469
-        return $payment;
1470
-    }
1471
-
1472
-
1473
-    /**
1474
-     * _process_transaction_payments
1475
-     *
1476
-     * @param \EE_Transaction $transaction
1477
-     *
1478
-     * @return array
1479
-     */
1480
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1481
-    {
1482
-        /** @type EE_Transaction_Payments $transaction_payments */
1483
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1484
-        //update the transaction with this payment
1485
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1486
-            EE_Error::add_success(esc_html__('The payment has been processed successfully.', 'event_espresso'),
1487
-                __FILE__, __FUNCTION__, __LINE__);
1488
-        } else {
1489
-            EE_Error::add_error(
1490
-                esc_html__('The payment was processed successfully but the amount paid for the transaction was not updated.',
1491
-                    'event_espresso')
1492
-                , __FILE__, __FUNCTION__, __LINE__
1493
-            );
1494
-        }
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * _get_REG_IDs_to_apply_payment_to
1500
-     *
1501
-     * returns a list of registration IDs that the payment will apply to
1502
-     *
1503
-     * @param \EE_Payment $payment
1504
-     *
1505
-     * @return array
1506
-     */
1507
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1508
-    {
1509
-        $REG_IDs = array();
1510
-        // grab array of IDs for specific registrations to apply changes to
1511
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1512
-            $REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1513
-        }
1514
-        //nothing specified ? then get all reg IDs
1515
-        if (empty($REG_IDs)) {
1516
-            $registrations = $payment->transaction()->registrations();
1517
-            $REG_IDs       = ! empty($registrations) ? array_keys($registrations) : $this->_get_existing_reg_payment_REG_IDs($payment);
1518
-        }
1519
-
1520
-        // ensure that REG_IDs are integers and NOT strings
1521
-        return array_map('intval', $REG_IDs);
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * @return array
1527
-     */
1528
-    public function existing_reg_payment_REG_IDs()
1529
-    {
1530
-        return $this->_existing_reg_payment_REG_IDs;
1531
-    }
1532
-
1533
-
1534
-    /**
1535
-     * @param array $existing_reg_payment_REG_IDs
1536
-     */
1537
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1538
-    {
1539
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1540
-    }
1541
-
1542
-
1543
-    /**
1544
-     * _get_existing_reg_payment_REG_IDs
1545
-     *
1546
-     * returns a list of registration IDs that the payment is currently related to
1547
-     * as recorded in the database
1548
-     *
1549
-     * @param \EE_Payment $payment
1550
-     *
1551
-     * @return array
1552
-     */
1553
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1554
-    {
1555
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1556
-            // let's get any existing reg payment records for this payment
1557
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1558
-            // but we only want the REG IDs, so grab the array keys
1559
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) ? array_keys($existing_reg_payment_REG_IDs) : array();
1560
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1561
-        }
1562
-
1563
-        return $this->existing_reg_payment_REG_IDs();
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * _remove_existing_registration_payments
1569
-     *
1570
-     * this calculates the difference between existing relations
1571
-     * to the supplied payment and the new list registration IDs,
1572
-     * removes any related registrations that no longer apply,
1573
-     * and then updates the registration paid fields
1574
-     *
1575
-     * @param \EE_Payment $payment
1576
-     * @param int         $PAY_ID
1577
-     *
1578
-     * @return bool;
1579
-     */
1580
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1581
-    {
1582
-        // newly created payments will have nothing recorded for $PAY_ID
1583
-        if ($PAY_ID == 0) {
1584
-            return false;
1585
-        }
1586
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1587
-        if (empty($existing_reg_payment_REG_IDs)) {
1588
-            return false;
1589
-        }
1590
-        /** @type EE_Transaction_Payments $transaction_payments */
1591
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1592
-
1593
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
1594
-            $payment,
1595
-            array(
1596
-                array(
1597
-                    'PAY_ID' => $payment->ID(),
1598
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1599
-                )
1600
-            )
1601
-        );
1602
-    }
1603
-
1604
-
1605
-    /**
1606
-     * _update_registration_payments
1607
-     *
1608
-     * this applies the payments to the selected registrations
1609
-     * but only if they have not already been paid for
1610
-     *
1611
-     * @param  EE_Transaction $transaction
1612
-     * @param \EE_Payment     $payment
1613
-     * @param array           $REG_IDs
1614
-     *
1615
-     * @return bool
1616
-     */
1617
-    protected function _update_registration_payments(
1618
-        EE_Transaction $transaction,
1619
-        EE_Payment $payment,
1620
-        $REG_IDs = array()
1621
-    ) {
1622
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1623
-        // so let's do that using our set of REG_IDs from the form
1624
-        $registration_query_where_params = array(
1625
-            'REG_ID' => array('IN', $REG_IDs)
1626
-        );
1627
-        // but add in some conditions regarding payment,
1628
-        // so that we don't apply payments to registrations that are free or have already been paid for
1629
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1630
-        if ( ! $payment->is_a_refund()) {
1631
-            $registration_query_where_params['REG_final_price']  = array('!=', 0);
1632
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1633
-        }
1634
-        //EEH_Debug_Tools::printr( $registration_query_where_params, '$registration_query_where_params', __FILE__, __LINE__ );
1635
-        $registrations = $transaction->registrations(array($registration_query_where_params));
1636
-        if ( ! empty($registrations)) {
1637
-            /** @type EE_Payment_Processor $payment_processor */
1638
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1639
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
1640
-        }
1641
-    }
1642
-
1643
-
1644
-    /**
1645
-     * _process_registration_status_change
1646
-     *
1647
-     * This processes requested registration status changes for all the registrations
1648
-     * on a given transaction and (optionally) sends out notifications for the changes.
1649
-     *
1650
-     * @param  EE_Transaction $transaction
1651
-     * @param array           $REG_IDs
1652
-     *
1653
-     * @return bool
1654
-     */
1655
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1656
-    {
1657
-        // first if there is no change in status then we get out.
1658
-        if (
1659
-            ! isset($this->_req_data['txn_reg_status_change'], $this->_req_data['txn_reg_status_change']['reg_status'])
1660
-            || $this->_req_data['txn_reg_status_change']['reg_status'] == 'NAN'
1661
-        ) {
1662
-            //no error message, no change requested, just nothing to do man.
1663
-            return false;
1664
-        }
1665
-        /** @type EE_Transaction_Processor $transaction_processor */
1666
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1667
-
1668
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1669
-        return $transaction_processor->manually_update_registration_statuses(
1670
-            $transaction,
1671
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1672
-            array(array('REG_ID' => array('IN', $REG_IDs)))
1673
-        );
1674
-    }
1675
-
1676
-
1677
-    /**
1678
-     * _build_payment_json_response
1679
-     *
1680
-     * @access public
1681
-     *
1682
-     * @param \EE_Payment $payment
1683
-     * @param array       $REG_IDs
1684
-     * @param bool | null $delete_txn_reg_status_change
1685
-     *
1686
-     * @return array
1687
-     */
1688
-    protected function _build_payment_json_response(
1689
-        EE_Payment $payment,
1690
-        $REG_IDs = array(),
1691
-        $delete_txn_reg_status_change = null
1692
-    ) {
1693
-        // was the payment deleted ?
1694
-        if (is_bool($delete_txn_reg_status_change)) {
1695
-            return array(
1696
-                'PAY_ID'                       => $payment->ID(),
1697
-                'amount'                       => $payment->amount(),
1698
-                'total_paid'                   => $payment->transaction()->paid(),
1699
-                'txn_status'                   => $payment->transaction()->status_ID(),
1700
-                'pay_status'                   => $payment->STS_ID(),
1701
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
1702
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
1703
-            );
1704
-        } else {
1705
-            $this->_get_payment_status_array();
1706
-
1707
-            return array(
1708
-                'amount'           => $payment->amount(),
1709
-                'total_paid'       => $payment->transaction()->paid(),
1710
-                'txn_status'       => $payment->transaction()->status_ID(),
1711
-                'pay_status'       => $payment->STS_ID(),
1712
-                'PAY_ID'           => $payment->ID(),
1713
-                'STS_ID'           => $payment->STS_ID(),
1714
-                'status'           => self::$_pay_status[$payment->STS_ID()],
1715
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
1716
-                'method'           => strtoupper($payment->source()),
1717
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
1718
-                'gateway'          => $payment->payment_method() ? $payment->payment_method()->admin_name() : esc_html__("Unknown",
1719
-                    'event_espresso'),
1720
-                'gateway_response' => $payment->gateway_response(),
1721
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
1722
-                'po_number'        => $payment->po_number(),
1723
-                'extra_accntng'    => $payment->extra_accntng(),
1724
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
1725
-            );
1726
-        }
1727
-    }
1728
-
1729
-
1730
-    /**
1731
-     * delete_payment
1732
-     *    delete a payment or refund made towards a transaction
1733
-     *
1734
-     * @access public
1735
-     * @return void
1736
-     */
1737
-    public function delete_payment()
1738
-    {
1739
-        $json_response_data = array('return_data' => false);
1740
-        $PAY_ID             = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0;
1741
-        if ($PAY_ID) {
1742
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false;
1743
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
1744
-            if ($payment instanceof EE_Payment) {
1745
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1746
-                /** @type EE_Transaction_Payments $transaction_payments */
1747
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1748
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
1749
-                    $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs,
1750
-                        $delete_txn_reg_status_change);
1751
-                    if ($delete_txn_reg_status_change) {
1752
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
1753
-                        //MAKE sure we also add the delete_txn_req_status_change to the
1754
-                        //$_REQUEST global because that's how messages will be looking for it.
1755
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
1756
-                        $this->_maybe_send_notifications();
1757
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
1758
-                    }
1759
-                }
1760
-            } else {
1761
-                EE_Error::add_error(
1762
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
1763
-                    __FILE__, __FUNCTION__, __LINE__
1764
-                );
1765
-            }
1766
-        } else {
1767
-            EE_Error::add_error(
1768
-                esc_html__('A valid Payment ID was not received, therefore payment form data could not be loaded.',
1769
-                    'event_espresso'),
1770
-                __FILE__, __FUNCTION__, __LINE__
1771
-            );
1772
-        }
1773
-        $notices              = EE_Error::get_notices(false, false, false);
1774
-        $this->_template_args = array(
1775
-            'data'      => $json_response_data,
1776
-            'success'   => $notices['success'],
1777
-            'error'     => $notices['errors'],
1778
-            'attention' => $notices['attention']
1779
-        );
1780
-        $this->_return_json();
1781
-    }
1782
-
1783
-
1784
-    /**
1785
-     * _registration_payment_data_array
1786
-     * adds info for 'owing' and 'paid' for each registration to the json response
1787
-     *
1788
-     * @access protected
1789
-     *
1790
-     * @param array $REG_IDs
1791
-     *
1792
-     * @return array
1793
-     */
1794
-    protected function _registration_payment_data_array($REG_IDs)
1795
-    {
1796
-        $registration_payment_data = array();
1797
-        //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
1798
-        if ( ! empty($REG_IDs)) {
1799
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
1800
-            foreach ($registrations as $registration) {
1801
-                if ($registration instanceof EE_Registration) {
1802
-                    $registration_payment_data[$registration->ID()] = array(
1803
-                        'paid'  => $registration->pretty_paid(),
1804
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
1805
-                    );
1806
-                }
1807
-            }
1808
-        }
1809
-
1810
-        return $registration_payment_data;
1811
-    }
1812
-
1813
-
1814
-    /**
1815
-     * _maybe_send_notifications
1816
-     *
1817
-     * determines whether or not the admin has indicated that notifications should be sent.
1818
-     * If so, will toggle a filter switch for delivering registration notices.
1819
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
1820
-     *
1821
-     * @access protected
1822
-     *
1823
-     * @param \EE_Payment | null $payment
1824
-     */
1825
-    protected function _maybe_send_notifications($payment = null)
1826
-    {
1827
-        switch ($payment instanceof EE_Payment) {
1828
-            // payment notifications
1829
-            case true :
1830
-                if (
1831
-                    isset(
1832
-                        $this->_req_data['txn_payments'],
1833
-                        $this->_req_data['txn_payments']['send_notifications']
1834
-                    ) &&
1835
-                    filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1836
-                ) {
1837
-                    $this->_process_payment_notification($payment);
1838
-                }
1839
-                break;
1840
-            // registration notifications
1841
-            case false :
1842
-                if (
1843
-                    isset(
1844
-                        $this->_req_data['txn_reg_status_change'],
1845
-                        $this->_req_data['txn_reg_status_change']['send_notifications']
1846
-                    ) &&
1847
-                    filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1848
-                ) {
1849
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
1850
-                }
1851
-                break;
1852
-        }
1853
-    }
1854
-
1855
-
1856
-    /**
1857
-     * _send_payment_reminder
1858
-     *    generates HTML for the View Transaction Details Admin page
1859
-     *
1860
-     * @access protected
1861
-     * @return void
1862
-     */
1863
-    protected function _send_payment_reminder()
1864
-    {
1865
-        $TXN_ID      = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
1866
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
1867
-        $query_args  = isset($this->_req_data['redirect_to']) ? array(
1868
-            'action' => $this->_req_data['redirect_to'],
1869
-            'TXN_ID' => $this->_req_data['TXN_ID']
1870
-        ) : array();
1871
-        do_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
1872
-            $transaction);
1873
-        $this->_redirect_after_action(false, esc_html__('payment reminder', 'event_espresso'),
1874
-            esc_html__('sent', 'event_espresso'), $query_args, true);
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     *  get_transactions
1880
-     *    get transactions for given parameters (used by list table)
1881
-     *
1882
-     * @param  int     $perpage how many transactions displayed per page
1883
-     * @param  boolean $count   return the count or objects
1884
-     * @param string   $view
1885
-     *
1886
-     * @return mixed int = count || array of transaction objects
1887
-     */
1888
-    public function get_transactions($perpage, $count = false, $view = '')
1889
-    {
1890
-
1891
-        $TXN = EEM_Transaction::instance();
1892
-
1893
-        $start_date = isset($this->_req_data['txn-filter-start-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) : date('m/d/Y',
1894
-            strtotime('-10 year'));
1895
-        $end_date   = isset($this->_req_data['txn-filter-end-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) : date('m/d/Y');
1896
-
1897
-        //make sure our timestamps start and end right at the boundaries for each day
1898
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1899
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1900
-
1901
-
1902
-        //convert to timestamps
1903
-        $start_date = strtotime($start_date);
1904
-        $end_date   = strtotime($end_date);
1905
-
1906
-        //makes sure start date is the lowest value and vice versa
1907
-        $start_date = min($start_date, $end_date);
1908
-        $end_date   = max($start_date, $end_date);
1909
-
1910
-        //convert to correct format for query
1911
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1912
-            date('Y-m-d H:i:s', $start_date), 'Y-m-d H:i:s');
1913
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1914
-            date('Y-m-d H:i:s', $end_date), 'Y-m-d H:i:s');
1915
-
1916
-
1917
-        //set orderby
1918
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1919
-
1920
-        switch ($this->_req_data['orderby']) {
1921
-            case 'TXN_ID':
1922
-                $orderby = 'TXN_ID';
1923
-                break;
1924
-            case 'ATT_fname':
1925
-                $orderby = 'Registration.Attendee.ATT_fname';
1926
-                break;
1927
-            case 'event_name':
1928
-                $orderby = 'Registration.Event.EVT_name';
1929
-                break;
1930
-            default: //'TXN_timestamp'
1931
-                $orderby = 'TXN_timestamp';
1932
-        }
1933
-
1934
-        $sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'DESC';
1935
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
1936
-        $per_page     = isset($perpage) && ! empty($perpage) ? $perpage : 10;
1937
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
1938
-
1939
-        $offset = ($current_page - 1) * $per_page;
1940
-        $limit  = array($offset, $per_page);
1941
-
1942
-        $_where = array(
1943
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
1944
-            'Registration.REG_count' => 1
1945
-        );
1946
-
1947
-        if (isset($this->_req_data['EVT_ID'])) {
1948
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
1949
-        }
1950
-
1951
-        if (isset($this->_req_data['s'])) {
1952
-            $search_string = '%' . $this->_req_data['s'] . '%';
1953
-            $_where['OR']  = array(
1954
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
1955
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
1956
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
1957
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
1958
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
1959
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
1960
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
1961
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
1962
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
1963
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
1964
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
1965
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
1966
-                'Registration.REG_code'               => array('LIKE', $search_string),
1967
-                'Registration.REG_count'              => array('LIKE', $search_string),
1968
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
1969
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
1970
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
1971
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
1972
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
1973
-                'TXN_session_data'                    => array('LIKE', $search_string),
1974
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string)
1975
-            );
1976
-        }
1977
-
1978
-        //failed transactions
1979
-        $failed    = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'failed' && ! $count) || ($count && $view == 'failed') ? true : false;
1980
-        $abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'abandoned' && ! $count) || ($count && $view == 'abandoned') ? true : false;
1981
-
1982
-        if ($failed) {
1983
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
1984
-        } else if ($abandoned) {
1985
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
1986
-        } else {
1987
-            $_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
1988
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
1989
-        }
1990
-
1991
-        $query_params = array($_where, 'order_by' => array($orderby => $sort), 'limit' => $limit);
1992
-
1993
-        $transactions = $count ? $TXN->count(array($_where), 'TXN_ID', true) : $TXN->get_all($query_params);
1994
-
1995
-
1996
-        return $transactions;
1997
-
1998
-    }
807
+		// process payment details
808
+		$payments = $this->_transaction->get_many_related('Payment');
809
+		if ( ! empty($payments)) {
810
+			$this->_template_args['payments']              = $payments;
811
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
812
+		} else {
813
+			$this->_template_args['payments']              = false;
814
+			$this->_template_args['existing_reg_payments'] = array();
815
+		}
816
+
817
+		$this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
818
+		$this->_template_args['delete_payment_url'] = add_query_arg(array('action' => 'espresso_delete_payment'),
819
+			TXN_ADMIN_URL);
820
+
821
+		if (isset($txn_details['invoice_number'])) {
822
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
823
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__('Invoice Number',
824
+				'event_espresso');
825
+		}
826
+
827
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction->get_first_related('Registration')->get('REG_session');
828
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__('Registration Session',
829
+			'event_espresso');
830
+
831
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '';
832
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__('Transaction placed from IP',
833
+			'event_espresso');
834
+
835
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '';
836
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__('Registrant User Agent',
837
+			'event_espresso');
838
+
839
+		$reg_steps = '<ul>';
840
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
841
+			if ($reg_step_status === true) {
842
+				$reg_steps .= '<li style="color:#70cc50">' . sprintf(esc_html__('%1$s : Completed', 'event_espresso'),
843
+						ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
844
+			} else if (is_numeric($reg_step_status) && $reg_step_status !== false) {
845
+				$reg_steps .= '<li style="color:#2EA2CC">' . sprintf(
846
+						esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
847
+						ucwords(str_replace('_', ' ', $reg_step)),
848
+						date(get_option('date_format') . ' ' . get_option('time_format'),
849
+							($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)))
850
+					) . '</li>';
851
+			} else {
852
+				$reg_steps .= '<li style="color:#E76700">' . sprintf(esc_html__('%1$s : Never Initiated',
853
+						'event_espresso'), ucwords(str_replace('_', ' ', $reg_step))) . '</li>';
854
+			}
855
+		}
856
+		$reg_steps .= '</ul>';
857
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
858
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__('Registration Step Progress',
859
+			'event_espresso');
860
+
861
+
862
+		$this->_get_registrations_to_apply_payment_to();
863
+		$this->_get_payment_methods($payments);
864
+		$this->_get_payment_status_array();
865
+		$this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
866
+
867
+		$this->_template_args['transaction_form_url']    = add_query_arg(array(
868
+			'action'  => 'edit_transaction',
869
+			'process' => 'transaction'
870
+		), TXN_ADMIN_URL);
871
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(array(
872
+			'page'   => 'espresso_transactions',
873
+			'action' => 'espresso_apply_payment'
874
+		), WP_AJAX_URL);
875
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(array(
876
+			'page'   => 'espresso_transactions',
877
+			'action' => 'espresso_delete_payment'
878
+		), WP_AJAX_URL);
879
+
880
+		// 'espresso_delete_payment_nonce'
881
+
882
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
883
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
884
+
885
+	}
886
+
887
+
888
+	/**
889
+	 * _get_registration_payment_IDs
890
+	 *
891
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
892
+	 *
893
+	 * @access protected
894
+	 *
895
+	 * @param EE_Payment[] $payments
896
+	 *
897
+	 * @return array
898
+	 */
899
+	protected function _get_registration_payment_IDs($payments = array())
900
+	{
901
+		$existing_reg_payments = array();
902
+		// get all reg payments for these payments
903
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(array(
904
+			array(
905
+				'PAY_ID' => array(
906
+					'IN',
907
+					array_keys($payments)
908
+				)
909
+			)
910
+		));
911
+		if ( ! empty($reg_payments)) {
912
+			foreach ($payments as $payment) {
913
+				if ( ! $payment instanceof EE_Payment) {
914
+					continue;
915
+				} else if ( ! isset($existing_reg_payments[$payment->ID()])) {
916
+					$existing_reg_payments[$payment->ID()] = array();
917
+				}
918
+				foreach ($reg_payments as $reg_payment) {
919
+					if ($reg_payment instanceof EE_Registration_Payment && $reg_payment->payment_ID() === $payment->ID()) {
920
+						$existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
921
+					}
922
+				}
923
+			}
924
+		}
925
+
926
+		return $existing_reg_payments;
927
+	}
928
+
929
+
930
+	/**
931
+	 * _get_registrations_to_apply_payment_to
932
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
933
+	 * which allows the admin to only apply the payment to the specific registrations
934
+	 *
935
+	 * @access protected
936
+	 * @return void
937
+	 * @throws \EE_Error
938
+	 */
939
+	protected function _get_registrations_to_apply_payment_to()
940
+	{
941
+		// we want any registration with an active status (ie: not deleted or cancelled)
942
+		$query_params                      = array(
943
+			array(
944
+				'STS_ID' => array(
945
+					'IN',
946
+					array(
947
+						EEM_Registration::status_id_approved,
948
+						EEM_Registration::status_id_pending_payment,
949
+						EEM_Registration::status_id_not_approved,
950
+					)
951
+				)
952
+			)
953
+		);
954
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
955
+				'', 'txn-admin-apply-payment-to-registrations-dv', '', 'clear: both; margin: 1.5em 0 0; display: none;'
956
+			);
957
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
958
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
959
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
960
+			EEH_HTML::tr(
961
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
962
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
963
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
964
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
965
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
966
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
967
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
968
+			)
969
+		);
970
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
971
+		// get registrations for TXN
972
+		$registrations = $this->_transaction->registrations($query_params);
973
+		foreach ($registrations as $registration) {
974
+			if ($registration instanceof EE_Registration) {
975
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
976
+					? $registration->attendee()->full_name()
977
+					: esc_html__('Unknown Attendee', 'event_espresso');
978
+				$owing         = $registration->final_price() - $registration->paid();
979
+				$taxable       = $registration->ticket()->taxable()
980
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
981
+					: '';
982
+				$checked       = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
983
+					? ' checked="checked"'
984
+					: '';
985
+				$disabled      = $registration->final_price() > 0 ? '' : ' disabled';
986
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
987
+					EEH_HTML::td($registration->ID()) .
988
+					EEH_HTML::td($attendee_name) .
989
+					EEH_HTML::td(
990
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
991
+					) .
992
+					EEH_HTML::td($registration->event_name()) .
993
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
994
+					EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
995
+					EEH_HTML::td(
996
+						'<input type="checkbox" value="' . $registration->ID()
997
+						. '" name="txn_admin_payment[registrations]"'
998
+						. $checked . $disabled . '>',
999
+						'', 'jst-cntr'
1000
+					),
1001
+					'apply-payment-registration-row-' . $registration->ID()
1002
+				);
1003
+			}
1004
+		}
1005
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1006
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1007
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1008
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1009
+			esc_html__(
1010
+				'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.',
1011
+				'event_espresso'
1012
+			),
1013
+			'', 'clear description'
1014
+		);
1015
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1016
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * _get_reg_status_selection
1022
+	 *
1023
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1024
+	 *         instead of events.
1025
+	 * @access protected
1026
+	 * @return void
1027
+	 */
1028
+	protected function _get_reg_status_selection()
1029
+	{
1030
+		//first get all possible statuses
1031
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1032
+		//let's add a "don't change" option.
1033
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1034
+		$status_array                                        = array_merge($status_array, $statuses);
1035
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input('txn_reg_status_change[reg_status]',
1036
+			$status_array, 'NAN', 'id="txn-admin-payment-reg-status-inp"', 'txn-reg-status-change-reg-status');
1037
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input('delete_txn_reg_status_change[reg_status]',
1038
+			$status_array, 'NAN', 'delete-txn-admin-payment-reg-status-inp', 'delete-txn-reg-status-change-reg-status');
1039
+
1040
+	}
1041
+
1042
+
1043
+	/**
1044
+	 *    _get_payment_methods
1045
+	 * Gets all the payment methods available generally, or the ones that are already
1046
+	 * selected on these payments (in case their payment methods are no longer active).
1047
+	 * Has the side-effect of updating the template args' payment_methods item
1048
+	 * @access private
1049
+	 *
1050
+	 * @param EE_Payment[] to show on this page
1051
+	 *
1052
+	 * @return void
1053
+	 */
1054
+	private function _get_payment_methods($payments = array())
1055
+	{
1056
+		$payment_methods_of_payments = array();
1057
+		foreach ($payments as $payment) {
1058
+			if ($payment instanceof EE_Payment) {
1059
+				$payment_methods_of_payments[] = $payment->get('PMD_ID');
1060
+			}
1061
+		}
1062
+		if ($payment_methods_of_payments) {
1063
+			$query_args = array(
1064
+				array(
1065
+					'OR*payment_method_for_payment' => array(
1066
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1067
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')
1068
+					)
1069
+				)
1070
+			);
1071
+		} else {
1072
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1073
+		}
1074
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * txn_attendees_meta_box
1080
+	 *    generates HTML for the Attendees Transaction main meta box
1081
+	 *
1082
+	 * @access public
1083
+	 *
1084
+	 * @param WP_Post $post
1085
+	 * @param array   $metabox
1086
+	 *
1087
+	 * @return void
1088
+	 */
1089
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1090
+	{
1091
+
1092
+		extract($metabox['args']);
1093
+		$this->_template_args['post']            = $post;
1094
+		$this->_template_args['event_attendees'] = array();
1095
+		// process items in cart
1096
+		$line_items = $this->_transaction->get_many_related('Line_Item', array(array('LIN_type' => 'line-item')));
1097
+		if ( ! empty($line_items)) {
1098
+			foreach ($line_items as $item) {
1099
+				if ($item instanceof EE_Line_Item) {
1100
+					switch ($item->OBJ_type()) {
1101
+
1102
+						case 'Event' :
1103
+							break;
1104
+
1105
+						case 'Ticket' :
1106
+							$ticket = $item->ticket();
1107
+							//right now we're only handling tickets here.  Cause its expected that only tickets will have attendees right?
1108
+							if ( ! $ticket instanceof EE_Ticket) {
1109
+								continue;
1110
+							}
1111
+							try {
1112
+								$event_name = $ticket->get_event_name();
1113
+							} catch (Exception $e) {
1114
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1115
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1116
+							}
1117
+							$event_name .= ' - ' . $item->get('LIN_name');
1118
+							$ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1119
+							// now get all of the registrations for this transaction that use this ticket
1120
+							$registrations = $ticket->get_many_related('Registration',
1121
+								array(array('TXN_ID' => $this->_transaction->ID())));
1122
+							foreach ($registrations as $registration) {
1123
+								if ( ! $registration instanceof EE_Registration) {
1124
+									continue;
1125
+								}
1126
+								$this->_template_args['event_attendees'][$registration->ID()]['STS_ID']            = $registration->status_ID();
1127
+								$this->_template_args['event_attendees'][$registration->ID()]['att_num']           = $registration->count();
1128
+								$this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] = $event_name;
1129
+								$this->_template_args['event_attendees'][$registration->ID()]['ticket_price']      = $ticket_price;
1130
+								// attendee info
1131
+								$attendee = $registration->get_first_related('Attendee');
1132
+								if ($attendee instanceof EE_Attendee) {
1133
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = $attendee->ID();
1134
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = $attendee->full_name();
1135
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name . esc_html__(' Event',
1136
+											'event_espresso') . '">' . $attendee->email() . '</a>';
1137
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = EEH_Address::format($attendee,
1138
+										'inline', false, false);
1139
+								} else {
1140
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1141
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1142
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1143
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1144
+								}
1145
+							}
1146
+							break;
1147
+
1148
+					}
1149
+				}
1150
+			}
1151
+
1152
+			$this->_template_args['transaction_form_url'] = add_query_arg(array(
1153
+				'action'  => 'edit_transaction',
1154
+				'process' => 'attendees'
1155
+			), TXN_ADMIN_URL);
1156
+			echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1157
+				$this->_template_args, true);
1158
+
1159
+		} else {
1160
+			echo sprintf(
1161
+				esc_html__('%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1162
+					'event_espresso'),
1163
+				'<p class="important-notice">',
1164
+				'</p>'
1165
+			);
1166
+		}
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * txn_registrant_side_meta_box
1172
+	 * generates HTML for the Edit Transaction side meta box
1173
+	 *
1174
+	 * @access public
1175
+	 * @throws \EE_Error
1176
+	 * @return void
1177
+	 */
1178
+	public function txn_registrant_side_meta_box()
1179
+	{
1180
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration ? $this->_transaction->primary_registration()->get_first_related('Attendee') : null;
1181
+		if ( ! $primary_att instanceof EE_Attendee) {
1182
+			$this->_template_args['no_attendee_message'] = esc_html__('There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1183
+				'event_espresso');
1184
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1185
+		}
1186
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1187
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1188
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1189
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1190
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1191
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1192
+			'action' => 'edit_attendee',
1193
+			'post'   => $primary_att->ID()
1194
+		), REG_ADMIN_URL);
1195
+		// get formatted address for registrant
1196
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1197
+		echo EEH_Template::display_template(TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1198
+			$this->_template_args, true);
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * txn_billing_info_side_meta_box
1204
+	 *    generates HTML for the Edit Transaction side meta box
1205
+	 *
1206
+	 * @access public
1207
+	 * @return void
1208
+	 */
1209
+	public function txn_billing_info_side_meta_box()
1210
+	{
1211
+
1212
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1213
+		$this->_template_args['billing_form_url'] = add_query_arg(
1214
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1215
+			TXN_ADMIN_URL
1216
+		);
1217
+
1218
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1219
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * apply_payments_or_refunds
1225
+	 *    registers a payment or refund made towards a transaction
1226
+	 *
1227
+	 * @access public
1228
+	 * @return void
1229
+	 */
1230
+	public function apply_payments_or_refunds()
1231
+	{
1232
+		$json_response_data = array('return_data' => false);
1233
+		$valid_data         = $this->_validate_payment_request_data();
1234
+		if ( ! empty($valid_data)) {
1235
+			$PAY_ID = $valid_data['PAY_ID'];
1236
+			//save  the new payment
1237
+			$payment = $this->_create_payment_from_request_data($valid_data);
1238
+			// get the TXN for this payment
1239
+			$transaction = $payment->transaction();
1240
+			// verify transaction
1241
+			if ($transaction instanceof EE_Transaction) {
1242
+				// calculate_total_payments_and_update_status
1243
+				$this->_process_transaction_payments($transaction);
1244
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1245
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1246
+				// apply payment to registrations (if applicable)
1247
+				if ( ! empty($REG_IDs)) {
1248
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1249
+					$this->_maybe_send_notifications();
1250
+					// now process status changes for the same registrations
1251
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1252
+				}
1253
+				$this->_maybe_send_notifications($payment);
1254
+				//prepare to render page
1255
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1256
+				do_action('AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', $transaction,
1257
+					$payment);
1258
+			} else {
1259
+				EE_Error::add_error(
1260
+					esc_html__('A valid Transaction for this payment could not be retrieved.', 'event_espresso'),
1261
+					__FILE__, __FUNCTION__, __LINE__
1262
+				);
1263
+			}
1264
+		} else {
1265
+			EE_Error::add_error(esc_html__('The payment form data could not be processed. Please try again.',
1266
+				'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1267
+		}
1268
+
1269
+		$notices              = EE_Error::get_notices(false, false, false);
1270
+		$this->_template_args = array(
1271
+			'data'    => $json_response_data,
1272
+			'error'   => $notices['errors'],
1273
+			'success' => $notices['success']
1274
+		);
1275
+		$this->_return_json();
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * _validate_payment_request_data
1281
+	 *
1282
+	 * @return array
1283
+	 */
1284
+	protected function _validate_payment_request_data()
1285
+	{
1286
+		if ( ! isset($this->_req_data['txn_admin_payment'])) {
1287
+			return false;
1288
+		}
1289
+		$payment_form = $this->_generate_payment_form_section();
1290
+		try {
1291
+			if ($payment_form->was_submitted()) {
1292
+				$payment_form->receive_form_submission();
1293
+				if ( ! $payment_form->is_valid()) {
1294
+					$submission_error_messages = array();
1295
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1296
+						if ($validation_error instanceof EE_Validation_Error) {
1297
+							$submission_error_messages[] = sprintf(
1298
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1299
+								$validation_error->get_form_section()->html_label_text(),
1300
+								$validation_error->getMessage()
1301
+							);
1302
+						}
1303
+					}
1304
+					EE_Error::add_error(join('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1305
+
1306
+					return array();
1307
+				}
1308
+			}
1309
+		} catch (EE_Error $e) {
1310
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1311
+
1312
+			return array();
1313
+		}
1314
+
1315
+		return $payment_form->valid_data();
1316
+	}
1317
+
1318
+
1319
+	/**
1320
+	 * _generate_payment_form_section
1321
+	 *
1322
+	 * @return EE_Form_Section_Proper
1323
+	 */
1324
+	protected function _generate_payment_form_section()
1325
+	{
1326
+		return new EE_Form_Section_Proper(
1327
+			array(
1328
+				'name'        => 'txn_admin_payment',
1329
+				'subsections' => array(
1330
+					'PAY_ID'          => new EE_Text_Input(
1331
+						array(
1332
+							'default'               => 0,
1333
+							'required'              => false,
1334
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1335
+							'validation_strategies' => array(new EE_Int_Normalization())
1336
+						)
1337
+					),
1338
+					'TXN_ID'          => new EE_Text_Input(
1339
+						array(
1340
+							'default'               => 0,
1341
+							'required'              => true,
1342
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1343
+							'validation_strategies' => array(new EE_Int_Normalization())
1344
+						)
1345
+					),
1346
+					'type'            => new EE_Text_Input(
1347
+						array(
1348
+							'default'               => 1,
1349
+							'required'              => true,
1350
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1351
+							'validation_strategies' => array(new EE_Int_Normalization())
1352
+						)
1353
+					),
1354
+					'amount'          => new EE_Text_Input(
1355
+						array(
1356
+							'default'               => 0,
1357
+							'required'              => true,
1358
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1359
+							'validation_strategies' => array(new EE_Float_Normalization())
1360
+						)
1361
+					),
1362
+					'status'          => new EE_Text_Input(
1363
+						array(
1364
+							'default'         => EEM_Payment::status_id_approved,
1365
+							'required'        => true,
1366
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1367
+						)
1368
+					),
1369
+					'PMD_ID'          => new EE_Text_Input(
1370
+						array(
1371
+							'default'               => 2,
1372
+							'required'              => true,
1373
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1374
+							'validation_strategies' => array(new EE_Int_Normalization())
1375
+						)
1376
+					),
1377
+					'date'            => new EE_Text_Input(
1378
+						array(
1379
+							'default'         => time(),
1380
+							'required'        => true,
1381
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1382
+						)
1383
+					),
1384
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1385
+						array(
1386
+							'default'               => '',
1387
+							'required'              => false,
1388
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1389
+							'validation_strategies' => array(
1390
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1391
+									100),
1392
+							)
1393
+						)
1394
+					),
1395
+					'po_number'       => new EE_Text_Input(
1396
+						array(
1397
+							'default'               => '',
1398
+							'required'              => false,
1399
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1400
+							'validation_strategies' => array(
1401
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1402
+									100),
1403
+							)
1404
+						)
1405
+					),
1406
+					'accounting'      => new EE_Text_Input(
1407
+						array(
1408
+							'default'               => '',
1409
+							'required'              => false,
1410
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1411
+							'validation_strategies' => array(
1412
+								new EE_Max_Length_Validation_Strategy(esc_html__('Input too long', 'event_espresso'),
1413
+									100),
1414
+							)
1415
+						)
1416
+					),
1417
+				)
1418
+			)
1419
+		);
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * _create_payment_from_request_data
1425
+	 *
1426
+	 * @param array $valid_data
1427
+	 *
1428
+	 * @return EE_Payment
1429
+	 */
1430
+	protected function _create_payment_from_request_data($valid_data)
1431
+	{
1432
+		$PAY_ID = $valid_data['PAY_ID'];
1433
+		// get payment amount
1434
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1435
+		// payments have a type value of 1 and refunds have a type value of -1
1436
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1437
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1438
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1439
+		$date    = $valid_data['date'] ? preg_replace('/\s+/', ' ', $valid_data['date']) : date('Y-m-d g:i a',
1440
+			current_time('timestamp'));
1441
+		$payment = EE_Payment::new_instance(
1442
+			array(
1443
+				'TXN_ID'              => $valid_data['TXN_ID'],
1444
+				'STS_ID'              => $valid_data['status'],
1445
+				'PAY_timestamp'       => $date,
1446
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1447
+				'PMD_ID'              => $valid_data['PMD_ID'],
1448
+				'PAY_amount'          => $amount,
1449
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1450
+				'PAY_po_number'       => $valid_data['po_number'],
1451
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1452
+				'PAY_details'         => $valid_data,
1453
+				'PAY_ID'              => $PAY_ID
1454
+			),
1455
+			'',
1456
+			array('Y-m-d', 'g:i a')
1457
+		);
1458
+
1459
+		if ( ! $payment->save()) {
1460
+			EE_Error::add_error(
1461
+				sprintf(
1462
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1463
+					$payment->ID()
1464
+				),
1465
+				__FILE__, __FUNCTION__, __LINE__
1466
+			);
1467
+		}
1468
+
1469
+		return $payment;
1470
+	}
1471
+
1472
+
1473
+	/**
1474
+	 * _process_transaction_payments
1475
+	 *
1476
+	 * @param \EE_Transaction $transaction
1477
+	 *
1478
+	 * @return array
1479
+	 */
1480
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1481
+	{
1482
+		/** @type EE_Transaction_Payments $transaction_payments */
1483
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1484
+		//update the transaction with this payment
1485
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1486
+			EE_Error::add_success(esc_html__('The payment has been processed successfully.', 'event_espresso'),
1487
+				__FILE__, __FUNCTION__, __LINE__);
1488
+		} else {
1489
+			EE_Error::add_error(
1490
+				esc_html__('The payment was processed successfully but the amount paid for the transaction was not updated.',
1491
+					'event_espresso')
1492
+				, __FILE__, __FUNCTION__, __LINE__
1493
+			);
1494
+		}
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * _get_REG_IDs_to_apply_payment_to
1500
+	 *
1501
+	 * returns a list of registration IDs that the payment will apply to
1502
+	 *
1503
+	 * @param \EE_Payment $payment
1504
+	 *
1505
+	 * @return array
1506
+	 */
1507
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1508
+	{
1509
+		$REG_IDs = array();
1510
+		// grab array of IDs for specific registrations to apply changes to
1511
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1512
+			$REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1513
+		}
1514
+		//nothing specified ? then get all reg IDs
1515
+		if (empty($REG_IDs)) {
1516
+			$registrations = $payment->transaction()->registrations();
1517
+			$REG_IDs       = ! empty($registrations) ? array_keys($registrations) : $this->_get_existing_reg_payment_REG_IDs($payment);
1518
+		}
1519
+
1520
+		// ensure that REG_IDs are integers and NOT strings
1521
+		return array_map('intval', $REG_IDs);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * @return array
1527
+	 */
1528
+	public function existing_reg_payment_REG_IDs()
1529
+	{
1530
+		return $this->_existing_reg_payment_REG_IDs;
1531
+	}
1532
+
1533
+
1534
+	/**
1535
+	 * @param array $existing_reg_payment_REG_IDs
1536
+	 */
1537
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1538
+	{
1539
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1540
+	}
1541
+
1542
+
1543
+	/**
1544
+	 * _get_existing_reg_payment_REG_IDs
1545
+	 *
1546
+	 * returns a list of registration IDs that the payment is currently related to
1547
+	 * as recorded in the database
1548
+	 *
1549
+	 * @param \EE_Payment $payment
1550
+	 *
1551
+	 * @return array
1552
+	 */
1553
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1554
+	{
1555
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1556
+			// let's get any existing reg payment records for this payment
1557
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1558
+			// but we only want the REG IDs, so grab the array keys
1559
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) ? array_keys($existing_reg_payment_REG_IDs) : array();
1560
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1561
+		}
1562
+
1563
+		return $this->existing_reg_payment_REG_IDs();
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * _remove_existing_registration_payments
1569
+	 *
1570
+	 * this calculates the difference between existing relations
1571
+	 * to the supplied payment and the new list registration IDs,
1572
+	 * removes any related registrations that no longer apply,
1573
+	 * and then updates the registration paid fields
1574
+	 *
1575
+	 * @param \EE_Payment $payment
1576
+	 * @param int         $PAY_ID
1577
+	 *
1578
+	 * @return bool;
1579
+	 */
1580
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1581
+	{
1582
+		// newly created payments will have nothing recorded for $PAY_ID
1583
+		if ($PAY_ID == 0) {
1584
+			return false;
1585
+		}
1586
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1587
+		if (empty($existing_reg_payment_REG_IDs)) {
1588
+			return false;
1589
+		}
1590
+		/** @type EE_Transaction_Payments $transaction_payments */
1591
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1592
+
1593
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
1594
+			$payment,
1595
+			array(
1596
+				array(
1597
+					'PAY_ID' => $payment->ID(),
1598
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1599
+				)
1600
+			)
1601
+		);
1602
+	}
1603
+
1604
+
1605
+	/**
1606
+	 * _update_registration_payments
1607
+	 *
1608
+	 * this applies the payments to the selected registrations
1609
+	 * but only if they have not already been paid for
1610
+	 *
1611
+	 * @param  EE_Transaction $transaction
1612
+	 * @param \EE_Payment     $payment
1613
+	 * @param array           $REG_IDs
1614
+	 *
1615
+	 * @return bool
1616
+	 */
1617
+	protected function _update_registration_payments(
1618
+		EE_Transaction $transaction,
1619
+		EE_Payment $payment,
1620
+		$REG_IDs = array()
1621
+	) {
1622
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1623
+		// so let's do that using our set of REG_IDs from the form
1624
+		$registration_query_where_params = array(
1625
+			'REG_ID' => array('IN', $REG_IDs)
1626
+		);
1627
+		// but add in some conditions regarding payment,
1628
+		// so that we don't apply payments to registrations that are free or have already been paid for
1629
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1630
+		if ( ! $payment->is_a_refund()) {
1631
+			$registration_query_where_params['REG_final_price']  = array('!=', 0);
1632
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1633
+		}
1634
+		//EEH_Debug_Tools::printr( $registration_query_where_params, '$registration_query_where_params', __FILE__, __LINE__ );
1635
+		$registrations = $transaction->registrations(array($registration_query_where_params));
1636
+		if ( ! empty($registrations)) {
1637
+			/** @type EE_Payment_Processor $payment_processor */
1638
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1639
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
1640
+		}
1641
+	}
1642
+
1643
+
1644
+	/**
1645
+	 * _process_registration_status_change
1646
+	 *
1647
+	 * This processes requested registration status changes for all the registrations
1648
+	 * on a given transaction and (optionally) sends out notifications for the changes.
1649
+	 *
1650
+	 * @param  EE_Transaction $transaction
1651
+	 * @param array           $REG_IDs
1652
+	 *
1653
+	 * @return bool
1654
+	 */
1655
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1656
+	{
1657
+		// first if there is no change in status then we get out.
1658
+		if (
1659
+			! isset($this->_req_data['txn_reg_status_change'], $this->_req_data['txn_reg_status_change']['reg_status'])
1660
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] == 'NAN'
1661
+		) {
1662
+			//no error message, no change requested, just nothing to do man.
1663
+			return false;
1664
+		}
1665
+		/** @type EE_Transaction_Processor $transaction_processor */
1666
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1667
+
1668
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1669
+		return $transaction_processor->manually_update_registration_statuses(
1670
+			$transaction,
1671
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1672
+			array(array('REG_ID' => array('IN', $REG_IDs)))
1673
+		);
1674
+	}
1675
+
1676
+
1677
+	/**
1678
+	 * _build_payment_json_response
1679
+	 *
1680
+	 * @access public
1681
+	 *
1682
+	 * @param \EE_Payment $payment
1683
+	 * @param array       $REG_IDs
1684
+	 * @param bool | null $delete_txn_reg_status_change
1685
+	 *
1686
+	 * @return array
1687
+	 */
1688
+	protected function _build_payment_json_response(
1689
+		EE_Payment $payment,
1690
+		$REG_IDs = array(),
1691
+		$delete_txn_reg_status_change = null
1692
+	) {
1693
+		// was the payment deleted ?
1694
+		if (is_bool($delete_txn_reg_status_change)) {
1695
+			return array(
1696
+				'PAY_ID'                       => $payment->ID(),
1697
+				'amount'                       => $payment->amount(),
1698
+				'total_paid'                   => $payment->transaction()->paid(),
1699
+				'txn_status'                   => $payment->transaction()->status_ID(),
1700
+				'pay_status'                   => $payment->STS_ID(),
1701
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
1702
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
1703
+			);
1704
+		} else {
1705
+			$this->_get_payment_status_array();
1706
+
1707
+			return array(
1708
+				'amount'           => $payment->amount(),
1709
+				'total_paid'       => $payment->transaction()->paid(),
1710
+				'txn_status'       => $payment->transaction()->status_ID(),
1711
+				'pay_status'       => $payment->STS_ID(),
1712
+				'PAY_ID'           => $payment->ID(),
1713
+				'STS_ID'           => $payment->STS_ID(),
1714
+				'status'           => self::$_pay_status[$payment->STS_ID()],
1715
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
1716
+				'method'           => strtoupper($payment->source()),
1717
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
1718
+				'gateway'          => $payment->payment_method() ? $payment->payment_method()->admin_name() : esc_html__("Unknown",
1719
+					'event_espresso'),
1720
+				'gateway_response' => $payment->gateway_response(),
1721
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
1722
+				'po_number'        => $payment->po_number(),
1723
+				'extra_accntng'    => $payment->extra_accntng(),
1724
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
1725
+			);
1726
+		}
1727
+	}
1728
+
1729
+
1730
+	/**
1731
+	 * delete_payment
1732
+	 *    delete a payment or refund made towards a transaction
1733
+	 *
1734
+	 * @access public
1735
+	 * @return void
1736
+	 */
1737
+	public function delete_payment()
1738
+	{
1739
+		$json_response_data = array('return_data' => false);
1740
+		$PAY_ID             = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0;
1741
+		if ($PAY_ID) {
1742
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false;
1743
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
1744
+			if ($payment instanceof EE_Payment) {
1745
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1746
+				/** @type EE_Transaction_Payments $transaction_payments */
1747
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1748
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
1749
+					$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs,
1750
+						$delete_txn_reg_status_change);
1751
+					if ($delete_txn_reg_status_change) {
1752
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
1753
+						//MAKE sure we also add the delete_txn_req_status_change to the
1754
+						//$_REQUEST global because that's how messages will be looking for it.
1755
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
1756
+						$this->_maybe_send_notifications();
1757
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
1758
+					}
1759
+				}
1760
+			} else {
1761
+				EE_Error::add_error(
1762
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
1763
+					__FILE__, __FUNCTION__, __LINE__
1764
+				);
1765
+			}
1766
+		} else {
1767
+			EE_Error::add_error(
1768
+				esc_html__('A valid Payment ID was not received, therefore payment form data could not be loaded.',
1769
+					'event_espresso'),
1770
+				__FILE__, __FUNCTION__, __LINE__
1771
+			);
1772
+		}
1773
+		$notices              = EE_Error::get_notices(false, false, false);
1774
+		$this->_template_args = array(
1775
+			'data'      => $json_response_data,
1776
+			'success'   => $notices['success'],
1777
+			'error'     => $notices['errors'],
1778
+			'attention' => $notices['attention']
1779
+		);
1780
+		$this->_return_json();
1781
+	}
1782
+
1783
+
1784
+	/**
1785
+	 * _registration_payment_data_array
1786
+	 * adds info for 'owing' and 'paid' for each registration to the json response
1787
+	 *
1788
+	 * @access protected
1789
+	 *
1790
+	 * @param array $REG_IDs
1791
+	 *
1792
+	 * @return array
1793
+	 */
1794
+	protected function _registration_payment_data_array($REG_IDs)
1795
+	{
1796
+		$registration_payment_data = array();
1797
+		//if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
1798
+		if ( ! empty($REG_IDs)) {
1799
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
1800
+			foreach ($registrations as $registration) {
1801
+				if ($registration instanceof EE_Registration) {
1802
+					$registration_payment_data[$registration->ID()] = array(
1803
+						'paid'  => $registration->pretty_paid(),
1804
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
1805
+					);
1806
+				}
1807
+			}
1808
+		}
1809
+
1810
+		return $registration_payment_data;
1811
+	}
1812
+
1813
+
1814
+	/**
1815
+	 * _maybe_send_notifications
1816
+	 *
1817
+	 * determines whether or not the admin has indicated that notifications should be sent.
1818
+	 * If so, will toggle a filter switch for delivering registration notices.
1819
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
1820
+	 *
1821
+	 * @access protected
1822
+	 *
1823
+	 * @param \EE_Payment | null $payment
1824
+	 */
1825
+	protected function _maybe_send_notifications($payment = null)
1826
+	{
1827
+		switch ($payment instanceof EE_Payment) {
1828
+			// payment notifications
1829
+			case true :
1830
+				if (
1831
+					isset(
1832
+						$this->_req_data['txn_payments'],
1833
+						$this->_req_data['txn_payments']['send_notifications']
1834
+					) &&
1835
+					filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1836
+				) {
1837
+					$this->_process_payment_notification($payment);
1838
+				}
1839
+				break;
1840
+			// registration notifications
1841
+			case false :
1842
+				if (
1843
+					isset(
1844
+						$this->_req_data['txn_reg_status_change'],
1845
+						$this->_req_data['txn_reg_status_change']['send_notifications']
1846
+					) &&
1847
+					filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
1848
+				) {
1849
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
1850
+				}
1851
+				break;
1852
+		}
1853
+	}
1854
+
1855
+
1856
+	/**
1857
+	 * _send_payment_reminder
1858
+	 *    generates HTML for the View Transaction Details Admin page
1859
+	 *
1860
+	 * @access protected
1861
+	 * @return void
1862
+	 */
1863
+	protected function _send_payment_reminder()
1864
+	{
1865
+		$TXN_ID      = ( ! empty($this->_req_data['TXN_ID'])) ? absint($this->_req_data['TXN_ID']) : false;
1866
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
1867
+		$query_args  = isset($this->_req_data['redirect_to']) ? array(
1868
+			'action' => $this->_req_data['redirect_to'],
1869
+			'TXN_ID' => $this->_req_data['TXN_ID']
1870
+		) : array();
1871
+		do_action('AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
1872
+			$transaction);
1873
+		$this->_redirect_after_action(false, esc_html__('payment reminder', 'event_espresso'),
1874
+			esc_html__('sent', 'event_espresso'), $query_args, true);
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 *  get_transactions
1880
+	 *    get transactions for given parameters (used by list table)
1881
+	 *
1882
+	 * @param  int     $perpage how many transactions displayed per page
1883
+	 * @param  boolean $count   return the count or objects
1884
+	 * @param string   $view
1885
+	 *
1886
+	 * @return mixed int = count || array of transaction objects
1887
+	 */
1888
+	public function get_transactions($perpage, $count = false, $view = '')
1889
+	{
1890
+
1891
+		$TXN = EEM_Transaction::instance();
1892
+
1893
+		$start_date = isset($this->_req_data['txn-filter-start-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) : date('m/d/Y',
1894
+			strtotime('-10 year'));
1895
+		$end_date   = isset($this->_req_data['txn-filter-end-date']) ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) : date('m/d/Y');
1896
+
1897
+		//make sure our timestamps start and end right at the boundaries for each day
1898
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1899
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1900
+
1901
+
1902
+		//convert to timestamps
1903
+		$start_date = strtotime($start_date);
1904
+		$end_date   = strtotime($end_date);
1905
+
1906
+		//makes sure start date is the lowest value and vice versa
1907
+		$start_date = min($start_date, $end_date);
1908
+		$end_date   = max($start_date, $end_date);
1909
+
1910
+		//convert to correct format for query
1911
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1912
+			date('Y-m-d H:i:s', $start_date), 'Y-m-d H:i:s');
1913
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query('TXN_timestamp',
1914
+			date('Y-m-d H:i:s', $end_date), 'Y-m-d H:i:s');
1915
+
1916
+
1917
+		//set orderby
1918
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1919
+
1920
+		switch ($this->_req_data['orderby']) {
1921
+			case 'TXN_ID':
1922
+				$orderby = 'TXN_ID';
1923
+				break;
1924
+			case 'ATT_fname':
1925
+				$orderby = 'Registration.Attendee.ATT_fname';
1926
+				break;
1927
+			case 'event_name':
1928
+				$orderby = 'Registration.Event.EVT_name';
1929
+				break;
1930
+			default: //'TXN_timestamp'
1931
+				$orderby = 'TXN_timestamp';
1932
+		}
1933
+
1934
+		$sort         = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'DESC';
1935
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
1936
+		$per_page     = isset($perpage) && ! empty($perpage) ? $perpage : 10;
1937
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
1938
+
1939
+		$offset = ($current_page - 1) * $per_page;
1940
+		$limit  = array($offset, $per_page);
1941
+
1942
+		$_where = array(
1943
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
1944
+			'Registration.REG_count' => 1
1945
+		);
1946
+
1947
+		if (isset($this->_req_data['EVT_ID'])) {
1948
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
1949
+		}
1950
+
1951
+		if (isset($this->_req_data['s'])) {
1952
+			$search_string = '%' . $this->_req_data['s'] . '%';
1953
+			$_where['OR']  = array(
1954
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
1955
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
1956
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
1957
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
1958
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
1959
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
1960
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
1961
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
1962
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
1963
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
1964
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
1965
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
1966
+				'Registration.REG_code'               => array('LIKE', $search_string),
1967
+				'Registration.REG_count'              => array('LIKE', $search_string),
1968
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
1969
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
1970
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
1971
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
1972
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
1973
+				'TXN_session_data'                    => array('LIKE', $search_string),
1974
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string)
1975
+			);
1976
+		}
1977
+
1978
+		//failed transactions
1979
+		$failed    = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'failed' && ! $count) || ($count && $view == 'failed') ? true : false;
1980
+		$abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] == 'abandoned' && ! $count) || ($count && $view == 'abandoned') ? true : false;
1981
+
1982
+		if ($failed) {
1983
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
1984
+		} else if ($abandoned) {
1985
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
1986
+		} else {
1987
+			$_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
1988
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
1989
+		}
1990
+
1991
+		$query_params = array($_where, 'order_by' => array($orderby => $sort), 'limit' => $limit);
1992
+
1993
+		$transactions = $count ? $TXN->count(array($_where), 'TXN_ID', true) : $TXN->get_all($query_params);
1994
+
1995
+
1996
+		return $transactions;
1997
+
1998
+	}
1999 1999
 
2000 2000
 
2001 2001
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2689 added lines, -2689 removed lines patch added patch discarded remove patch
@@ -15,2696 +15,2696 @@
 block discarded – undo
15 15
 class Events_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17 17
 
18
-    /**
19
-     * This will hold the event object for event_details screen.
20
-     *
21
-     * @access protected
22
-     * @var EE_Event $_event
23
-     */
24
-    protected $_event;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var stdClass $_category
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This will hold the event model instance
37
-     *
38
-     * @var EEM_Event $_event_model
39
-     */
40
-    protected $_event_model;
41
-
42
-
43
-
44
-    /**
45
-     * @var EE_Event
46
-     */
47
-    protected $_cpt_model_obj = false;
48
-
49
-
50
-    /**
51
-     * Initialize page props for this admin page group.
52
-     */
53
-    protected function _init_page_props()
54
-    {
55
-        $this->page_slug = EVENTS_PG_SLUG;
56
-        $this->page_label = EVENTS_LABEL;
57
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
58
-        $this->_admin_base_path = EVENTS_ADMIN;
59
-        $this->_cpt_model_names = array(
60
-            'create_new' => 'EEM_Event',
61
-            'edit'       => 'EEM_Event',
62
-        );
63
-        $this->_cpt_edit_routes = array(
64
-            'espresso_events' => 'edit',
65
-        );
66
-        add_action(
67
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
-            array($this, 'verify_event_edit'), 10, 2
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * Sets the ajax hooks used for this admin page group.
75
-     */
76
-    protected function _ajax_hooks()
77
-    {
78
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
-    }
80
-
81
-
82
-    /**
83
-     * Sets the page properties for this admin page group.
84
-     */
85
-    protected function _define_page_props()
86
-    {
87
-        $this->_admin_page_title = EVENTS_LABEL;
88
-        $this->_labels = array(
89
-            'buttons'      => array(
90
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
91
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
-            ),
97
-            'editor_title' => array(
98
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
-            ),
100
-            'publishbox'   => array(
101
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
103
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
-            ),
107
-        );
108
-    }
109
-
110
-
111
-    /**
112
-     * Sets the page routes property for this admin page group.
113
-     */
114
-    protected function _set_page_routes()
115
-    {
116
-        //load formatter helper
117
-        //load field generator helper
118
-        //is there a evt_id in the request?
119
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
-            ? $this->_req_data['EVT_ID']
121
-            : 0;
122
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
-        $this->_page_routes = array(
124
-            'default'                       => array(
125
-                'func'       => '_events_overview_list_table',
126
-                'capability' => 'ee_read_events',
127
-            ),
128
-            'create_new'                    => array(
129
-                'func'       => '_create_new_cpt_item',
130
-                'capability' => 'ee_edit_events',
131
-            ),
132
-            'edit'                          => array(
133
-                'func'       => '_edit_cpt_item',
134
-                'capability' => 'ee_edit_event',
135
-                'obj_id'     => $evt_id,
136
-            ),
137
-            'copy_event'                    => array(
138
-                'func'       => '_copy_events',
139
-                'capability' => 'ee_edit_event',
140
-                'obj_id'     => $evt_id,
141
-                'noheader'   => true,
142
-            ),
143
-            'trash_event'                   => array(
144
-                'func'       => '_trash_or_restore_event',
145
-                'args'       => array('event_status' => 'trash'),
146
-                'capability' => 'ee_delete_event',
147
-                'obj_id'     => $evt_id,
148
-                'noheader'   => true,
149
-            ),
150
-            'trash_events'                  => array(
151
-                'func'       => '_trash_or_restore_events',
152
-                'args'       => array('event_status' => 'trash'),
153
-                'capability' => 'ee_delete_events',
154
-                'noheader'   => true,
155
-            ),
156
-            'restore_event'                 => array(
157
-                'func'       => '_trash_or_restore_event',
158
-                'args'       => array('event_status' => 'draft'),
159
-                'capability' => 'ee_delete_event',
160
-                'obj_id'     => $evt_id,
161
-                'noheader'   => true,
162
-            ),
163
-            'restore_events'                => array(
164
-                'func'       => '_trash_or_restore_events',
165
-                'args'       => array('event_status' => 'draft'),
166
-                'capability' => 'ee_delete_events',
167
-                'noheader'   => true,
168
-            ),
169
-            'delete_event'                  => array(
170
-                'func'       => '_delete_event',
171
-                'capability' => 'ee_delete_event',
172
-                'obj_id'     => $evt_id,
173
-                'noheader'   => true,
174
-            ),
175
-            'delete_events'                 => array(
176
-                'func'       => '_delete_events',
177
-                'capability' => 'ee_delete_events',
178
-                'noheader'   => true,
179
-            ),
180
-            'view_report'                   => array(
181
-                'func'      => '_view_report',
182
-                'capablity' => 'ee_edit_events',
183
-            ),
184
-            'default_event_settings'        => array(
185
-                'func'       => '_default_event_settings',
186
-                'capability' => 'manage_options',
187
-            ),
188
-            'update_default_event_settings' => array(
189
-                'func'       => '_update_default_event_settings',
190
-                'capability' => 'manage_options',
191
-                'noheader'   => true,
192
-            ),
193
-            'template_settings'             => array(
194
-                'func'       => '_template_settings',
195
-                'capability' => 'manage_options',
196
-            ),
197
-            //event category tab related
198
-            'add_category'                  => array(
199
-                'func'       => '_category_details',
200
-                'capability' => 'ee_edit_event_category',
201
-                'args'       => array('add'),
202
-            ),
203
-            'edit_category'                 => array(
204
-                'func'       => '_category_details',
205
-                'capability' => 'ee_edit_event_category',
206
-                'args'       => array('edit'),
207
-            ),
208
-            'delete_categories'             => array(
209
-                'func'       => '_delete_categories',
210
-                'capability' => 'ee_delete_event_category',
211
-                'noheader'   => true,
212
-            ),
213
-            'delete_category'               => array(
214
-                'func'       => '_delete_categories',
215
-                'capability' => 'ee_delete_event_category',
216
-                'noheader'   => true,
217
-            ),
218
-            'insert_category'               => array(
219
-                'func'       => '_insert_or_update_category',
220
-                'args'       => array('new_category' => true),
221
-                'capability' => 'ee_edit_event_category',
222
-                'noheader'   => true,
223
-            ),
224
-            'update_category'               => array(
225
-                'func'       => '_insert_or_update_category',
226
-                'args'       => array('new_category' => false),
227
-                'capability' => 'ee_edit_event_category',
228
-                'noheader'   => true,
229
-            ),
230
-            'category_list'                 => array(
231
-                'func'       => '_category_list_table',
232
-                'capability' => 'ee_manage_event_categories',
233
-            ),
234
-        );
235
-    }
236
-
237
-
238
-    /**
239
-     * Set the _page_config property for this admin page group.
240
-     */
241
-    protected function _set_page_config()
242
-    {
243
-        $this->_page_config = array(
244
-            'default'                => array(
245
-                'nav'           => array(
246
-                    'label' => esc_html__('Overview', 'event_espresso'),
247
-                    'order' => 10,
248
-                ),
249
-                'list_table'    => 'Events_Admin_List_Table',
250
-                'help_tabs'     => array(
251
-                    'events_overview_help_tab'                       => array(
252
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
253
-                        'filename' => 'events_overview',
254
-                    ),
255
-                    'events_overview_table_column_headings_help_tab' => array(
256
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
-                        'filename' => 'events_overview_table_column_headings',
258
-                    ),
259
-                    'events_overview_filters_help_tab'               => array(
260
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
-                        'filename' => 'events_overview_filters',
262
-                    ),
263
-                    'events_overview_view_help_tab'                  => array(
264
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
-                        'filename' => 'events_overview_views',
266
-                    ),
267
-                    'events_overview_other_help_tab'                 => array(
268
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
-                        'filename' => 'events_overview_other',
270
-                    ),
271
-                ),
272
-                'help_tour'     => array(
273
-                    'Event_Overview_Help_Tour',
274
-                    //'New_Features_Test_Help_Tour' for testing multiple help tour
275
-                ),
276
-                'qtips'         => array(
277
-                    'EE_Event_List_Table_Tips',
278
-                ),
279
-                'require_nonce' => false,
280
-            ),
281
-            'create_new'             => array(
282
-                'nav'           => array(
283
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
284
-                    'order'      => 5,
285
-                    'persistent' => false,
286
-                ),
287
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
-                'help_tabs'     => array(
289
-                    'event_editor_help_tab'                            => array(
290
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
291
-                        'filename' => 'event_editor',
292
-                    ),
293
-                    'event_editor_title_richtexteditor_help_tab'       => array(
294
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
-                        'filename' => 'event_editor_title_richtexteditor',
296
-                    ),
297
-                    'event_editor_venue_details_help_tab'              => array(
298
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
-                        'filename' => 'event_editor_venue_details',
300
-                    ),
301
-                    'event_editor_event_datetimes_help_tab'            => array(
302
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
-                        'filename' => 'event_editor_event_datetimes',
304
-                    ),
305
-                    'event_editor_event_tickets_help_tab'              => array(
306
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
-                        'filename' => 'event_editor_event_tickets',
308
-                    ),
309
-                    'event_editor_event_registration_options_help_tab' => array(
310
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
-                        'filename' => 'event_editor_event_registration_options',
312
-                    ),
313
-                    'event_editor_tags_categories_help_tab'            => array(
314
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
-                        'filename' => 'event_editor_tags_categories',
316
-                    ),
317
-                    'event_editor_questions_registrants_help_tab'      => array(
318
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
-                        'filename' => 'event_editor_questions_registrants',
320
-                    ),
321
-                    'event_editor_save_new_event_help_tab'             => array(
322
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
323
-                        'filename' => 'event_editor_save_new_event',
324
-                    ),
325
-                    'event_editor_other_help_tab'                      => array(
326
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
327
-                        'filename' => 'event_editor_other',
328
-                    ),
329
-                ),
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
-                /*'help_tour' => array(
18
+	/**
19
+	 * This will hold the event object for event_details screen.
20
+	 *
21
+	 * @access protected
22
+	 * @var EE_Event $_event
23
+	 */
24
+	protected $_event;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var stdClass $_category
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This will hold the event model instance
37
+	 *
38
+	 * @var EEM_Event $_event_model
39
+	 */
40
+	protected $_event_model;
41
+
42
+
43
+
44
+	/**
45
+	 * @var EE_Event
46
+	 */
47
+	protected $_cpt_model_obj = false;
48
+
49
+
50
+	/**
51
+	 * Initialize page props for this admin page group.
52
+	 */
53
+	protected function _init_page_props()
54
+	{
55
+		$this->page_slug = EVENTS_PG_SLUG;
56
+		$this->page_label = EVENTS_LABEL;
57
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
58
+		$this->_admin_base_path = EVENTS_ADMIN;
59
+		$this->_cpt_model_names = array(
60
+			'create_new' => 'EEM_Event',
61
+			'edit'       => 'EEM_Event',
62
+		);
63
+		$this->_cpt_edit_routes = array(
64
+			'espresso_events' => 'edit',
65
+		);
66
+		add_action(
67
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
68
+			array($this, 'verify_event_edit'), 10, 2
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * Sets the ajax hooks used for this admin page group.
75
+	 */
76
+	protected function _ajax_hooks()
77
+	{
78
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
79
+	}
80
+
81
+
82
+	/**
83
+	 * Sets the page properties for this admin page group.
84
+	 */
85
+	protected function _define_page_props()
86
+	{
87
+		$this->_admin_page_title = EVENTS_LABEL;
88
+		$this->_labels = array(
89
+			'buttons'      => array(
90
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
91
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
92
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
93
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
94
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
95
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
96
+			),
97
+			'editor_title' => array(
98
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
99
+			),
100
+			'publishbox'   => array(
101
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
102
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
103
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
104
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
105
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
106
+			),
107
+		);
108
+	}
109
+
110
+
111
+	/**
112
+	 * Sets the page routes property for this admin page group.
113
+	 */
114
+	protected function _set_page_routes()
115
+	{
116
+		//load formatter helper
117
+		//load field generator helper
118
+		//is there a evt_id in the request?
119
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
120
+			? $this->_req_data['EVT_ID']
121
+			: 0;
122
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
123
+		$this->_page_routes = array(
124
+			'default'                       => array(
125
+				'func'       => '_events_overview_list_table',
126
+				'capability' => 'ee_read_events',
127
+			),
128
+			'create_new'                    => array(
129
+				'func'       => '_create_new_cpt_item',
130
+				'capability' => 'ee_edit_events',
131
+			),
132
+			'edit'                          => array(
133
+				'func'       => '_edit_cpt_item',
134
+				'capability' => 'ee_edit_event',
135
+				'obj_id'     => $evt_id,
136
+			),
137
+			'copy_event'                    => array(
138
+				'func'       => '_copy_events',
139
+				'capability' => 'ee_edit_event',
140
+				'obj_id'     => $evt_id,
141
+				'noheader'   => true,
142
+			),
143
+			'trash_event'                   => array(
144
+				'func'       => '_trash_or_restore_event',
145
+				'args'       => array('event_status' => 'trash'),
146
+				'capability' => 'ee_delete_event',
147
+				'obj_id'     => $evt_id,
148
+				'noheader'   => true,
149
+			),
150
+			'trash_events'                  => array(
151
+				'func'       => '_trash_or_restore_events',
152
+				'args'       => array('event_status' => 'trash'),
153
+				'capability' => 'ee_delete_events',
154
+				'noheader'   => true,
155
+			),
156
+			'restore_event'                 => array(
157
+				'func'       => '_trash_or_restore_event',
158
+				'args'       => array('event_status' => 'draft'),
159
+				'capability' => 'ee_delete_event',
160
+				'obj_id'     => $evt_id,
161
+				'noheader'   => true,
162
+			),
163
+			'restore_events'                => array(
164
+				'func'       => '_trash_or_restore_events',
165
+				'args'       => array('event_status' => 'draft'),
166
+				'capability' => 'ee_delete_events',
167
+				'noheader'   => true,
168
+			),
169
+			'delete_event'                  => array(
170
+				'func'       => '_delete_event',
171
+				'capability' => 'ee_delete_event',
172
+				'obj_id'     => $evt_id,
173
+				'noheader'   => true,
174
+			),
175
+			'delete_events'                 => array(
176
+				'func'       => '_delete_events',
177
+				'capability' => 'ee_delete_events',
178
+				'noheader'   => true,
179
+			),
180
+			'view_report'                   => array(
181
+				'func'      => '_view_report',
182
+				'capablity' => 'ee_edit_events',
183
+			),
184
+			'default_event_settings'        => array(
185
+				'func'       => '_default_event_settings',
186
+				'capability' => 'manage_options',
187
+			),
188
+			'update_default_event_settings' => array(
189
+				'func'       => '_update_default_event_settings',
190
+				'capability' => 'manage_options',
191
+				'noheader'   => true,
192
+			),
193
+			'template_settings'             => array(
194
+				'func'       => '_template_settings',
195
+				'capability' => 'manage_options',
196
+			),
197
+			//event category tab related
198
+			'add_category'                  => array(
199
+				'func'       => '_category_details',
200
+				'capability' => 'ee_edit_event_category',
201
+				'args'       => array('add'),
202
+			),
203
+			'edit_category'                 => array(
204
+				'func'       => '_category_details',
205
+				'capability' => 'ee_edit_event_category',
206
+				'args'       => array('edit'),
207
+			),
208
+			'delete_categories'             => array(
209
+				'func'       => '_delete_categories',
210
+				'capability' => 'ee_delete_event_category',
211
+				'noheader'   => true,
212
+			),
213
+			'delete_category'               => array(
214
+				'func'       => '_delete_categories',
215
+				'capability' => 'ee_delete_event_category',
216
+				'noheader'   => true,
217
+			),
218
+			'insert_category'               => array(
219
+				'func'       => '_insert_or_update_category',
220
+				'args'       => array('new_category' => true),
221
+				'capability' => 'ee_edit_event_category',
222
+				'noheader'   => true,
223
+			),
224
+			'update_category'               => array(
225
+				'func'       => '_insert_or_update_category',
226
+				'args'       => array('new_category' => false),
227
+				'capability' => 'ee_edit_event_category',
228
+				'noheader'   => true,
229
+			),
230
+			'category_list'                 => array(
231
+				'func'       => '_category_list_table',
232
+				'capability' => 'ee_manage_event_categories',
233
+			),
234
+		);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Set the _page_config property for this admin page group.
240
+	 */
241
+	protected function _set_page_config()
242
+	{
243
+		$this->_page_config = array(
244
+			'default'                => array(
245
+				'nav'           => array(
246
+					'label' => esc_html__('Overview', 'event_espresso'),
247
+					'order' => 10,
248
+				),
249
+				'list_table'    => 'Events_Admin_List_Table',
250
+				'help_tabs'     => array(
251
+					'events_overview_help_tab'                       => array(
252
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
253
+						'filename' => 'events_overview',
254
+					),
255
+					'events_overview_table_column_headings_help_tab' => array(
256
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
257
+						'filename' => 'events_overview_table_column_headings',
258
+					),
259
+					'events_overview_filters_help_tab'               => array(
260
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
261
+						'filename' => 'events_overview_filters',
262
+					),
263
+					'events_overview_view_help_tab'                  => array(
264
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
265
+						'filename' => 'events_overview_views',
266
+					),
267
+					'events_overview_other_help_tab'                 => array(
268
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
269
+						'filename' => 'events_overview_other',
270
+					),
271
+				),
272
+				'help_tour'     => array(
273
+					'Event_Overview_Help_Tour',
274
+					//'New_Features_Test_Help_Tour' for testing multiple help tour
275
+				),
276
+				'qtips'         => array(
277
+					'EE_Event_List_Table_Tips',
278
+				),
279
+				'require_nonce' => false,
280
+			),
281
+			'create_new'             => array(
282
+				'nav'           => array(
283
+					'label'      => esc_html__('Add Event', 'event_espresso'),
284
+					'order'      => 5,
285
+					'persistent' => false,
286
+				),
287
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
288
+				'help_tabs'     => array(
289
+					'event_editor_help_tab'                            => array(
290
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
291
+						'filename' => 'event_editor',
292
+					),
293
+					'event_editor_title_richtexteditor_help_tab'       => array(
294
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
295
+						'filename' => 'event_editor_title_richtexteditor',
296
+					),
297
+					'event_editor_venue_details_help_tab'              => array(
298
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
299
+						'filename' => 'event_editor_venue_details',
300
+					),
301
+					'event_editor_event_datetimes_help_tab'            => array(
302
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
303
+						'filename' => 'event_editor_event_datetimes',
304
+					),
305
+					'event_editor_event_tickets_help_tab'              => array(
306
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
307
+						'filename' => 'event_editor_event_tickets',
308
+					),
309
+					'event_editor_event_registration_options_help_tab' => array(
310
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
311
+						'filename' => 'event_editor_event_registration_options',
312
+					),
313
+					'event_editor_tags_categories_help_tab'            => array(
314
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
315
+						'filename' => 'event_editor_tags_categories',
316
+					),
317
+					'event_editor_questions_registrants_help_tab'      => array(
318
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
319
+						'filename' => 'event_editor_questions_registrants',
320
+					),
321
+					'event_editor_save_new_event_help_tab'             => array(
322
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
323
+						'filename' => 'event_editor_save_new_event',
324
+					),
325
+					'event_editor_other_help_tab'                      => array(
326
+						'title'    => esc_html__('Event Other', 'event_espresso'),
327
+						'filename' => 'event_editor_other',
328
+					),
329
+				),
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
+				/*'help_tour' => array(
392 392
 					'Event_Edit_Help_Tour'
393 393
 				),*/
394
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
-                'require_nonce' => false,
396
-            ),
397
-            'default_event_settings' => array(
398
-                'nav'           => array(
399
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
400
-                    'order' => 40,
401
-                ),
402
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
-                'labels'        => array(
404
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
-                ),
406
-                'help_tabs'     => array(
407
-                    'default_settings_help_tab'        => array(
408
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
-                        'filename' => 'events_default_settings',
410
-                    ),
411
-                    'default_settings_status_help_tab' => array(
412
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
-                        'filename' => 'events_default_settings_status',
414
-                    ),
415
-                    'default_maximum_tickets_help_tab' => array(
416
-                        'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
-                        'filename' => 'events_default_settings_max_tickets',
418
-                    )
419
-                ),
420
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
-                'require_nonce' => false,
422
-            ),
423
-            //template settings
424
-            'template_settings'      => array(
425
-                'nav'           => array(
426
-                    'label' => esc_html__('Templates', 'event_espresso'),
427
-                    'order' => 30,
428
-                ),
429
-                'metaboxes'     => $this->_default_espresso_metaboxes,
430
-                'help_tabs'     => array(
431
-                    'general_settings_templates_help_tab' => array(
432
-                        'title'    => esc_html__('Templates', 'event_espresso'),
433
-                        'filename' => 'general_settings_templates',
434
-                    ),
435
-                ),
436
-                'help_tour'     => array('Templates_Help_Tour'),
437
-                'require_nonce' => false,
438
-            ),
439
-            //event category stuff
440
-            'add_category'           => array(
441
-                'nav'           => array(
442
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
443
-                    'order'      => 15,
444
-                    'persistent' => false,
445
-                ),
446
-                'help_tabs'     => array(
447
-                    'add_category_help_tab' => array(
448
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
-                        'filename' => 'events_add_category',
450
-                    ),
451
-                ),
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
-                'help_tour'     => array(
503
-                    'Event_Categories_Help_Tour',
504
-                ),
505
-                'metaboxes'     => $this->_default_espresso_metaboxes,
506
-                'require_nonce' => false,
507
-            ),
508
-        );
509
-    }
510
-
511
-
512
-    /**
513
-     * Used to register any global screen options if necessary for every route in this admin page group.
514
-     */
515
-    protected function _add_screen_options()
516
-    {
517
-    }
518
-
519
-
520
-    /**
521
-     * Implementing the screen options for the 'default' route.
522
-     */
523
-    protected function _add_screen_options_default()
524
-    {
525
-        $this->_per_page_screen_option();
526
-    }
527
-
528
-
529
-    /**
530
-     * Implementing screen options for the category list route.
531
-     */
532
-    protected function _add_screen_options_category_list()
533
-    {
534
-        $page_title = $this->_admin_page_title;
535
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
-        $this->_per_page_screen_option();
537
-        $this->_admin_page_title = $page_title;
538
-    }
539
-
540
-
541
-    /**
542
-     * Used to register any global feature pointers for the admin page group.
543
-     */
544
-    protected function _add_feature_pointers()
545
-    {
546
-    }
547
-
548
-
549
-    /**
550
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
551
-     */
552
-    public function load_scripts_styles()
553
-    {
554
-        wp_register_style(
555
-            'events-admin-css',
556
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
557
-            array(),
558
-            EVENT_ESPRESSO_VERSION
559
-        );
560
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
-        wp_enqueue_style('events-admin-css');
562
-        wp_enqueue_style('ee-cat-admin');
563
-        //todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
-        //registers for all views
565
-        //scripts
566
-        wp_register_script(
567
-            'event_editor_js',
568
-            EVENTS_ASSETS_URL . 'event_editor.js',
569
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
-            EVENT_ESPRESSO_VERSION,
571
-            true
572
-        );
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
-    /**
588
-     * Enqueuing scripts and styles specific to this view
589
-     */
590
-    public function load_scripts_styles_edit()
591
-    {
592
-        //styles
593
-        wp_enqueue_style('espresso-ui-theme');
594
-        wp_register_style(
595
-            'event-editor-css',
596
-            EVENTS_ASSETS_URL . 'event-editor.css',
597
-            array('ee-admin-css'),
598
-            EVENT_ESPRESSO_VERSION
599
-        );
600
-        wp_enqueue_style('event-editor-css');
601
-        //scripts
602
-        wp_register_script(
603
-            'event-datetime-metabox',
604
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
-            array('event_editor_js', 'ee-datepicker'),
606
-            EVENT_ESPRESSO_VERSION
607
-        );
608
-        wp_enqueue_script('event-datetime-metabox');
609
-    }
610
-
611
-
612
-    /**
613
-     * Populating the _views property for the category list table view.
614
-     */
615
-    protected function _set_list_table_views_category_list()
616
-    {
617
-        $this->_views = array(
618
-            'all' => array(
619
-                'slug'        => 'all',
620
-                'label'       => esc_html__('All', 'event_espresso'),
621
-                'count'       => 0,
622
-                'bulk_action' => array(
623
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
-                ),
625
-            ),
626
-        );
627
-    }
628
-
629
-
630
-    /**
631
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
-     */
633
-    public function admin_init()
634
-    {
635
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
-            'event_espresso'
638
-        );
639
-    }
640
-
641
-
642
-    /**
643
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page 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
-    /**
661
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
-     * warning (via EE_Error::add_error());
663
-     *
664
-     * @param  EE_Event $event Event object
665
-     * @param string    $req_type
666
-     * @return void
667
-     * @throws EE_Error
668
-     * @access public
669
-     */
670
-    public function verify_event_edit($event = null, $req_type = '')
671
-    {
672
-        // don't need to do this when processing
673
-        if(!empty($req_type)) {
674
-            return;
675
-        }
676
-        // no event?
677
-        if (empty($event)) {
678
-            // set event
679
-            $event = $this->_cpt_model_obj;
680
-        }
681
-        // STILL no event?
682
-        if (! $event instanceof EE_Event) {
683
-            return;
684
-        }
685
-        $orig_status = $event->status();
686
-        // first check if event is active.
687
-        if (
688
-            $orig_status === EEM_Event::cancelled
689
-            || $orig_status === EEM_Event::postponed
690
-            || $event->is_expired()
691
-            || $event->is_inactive()
692
-        ) {
693
-            return;
694
-        }
695
-        //made it here so it IS active... next check that any of the tickets are sold.
696
-        if ($event->is_sold_out(true)) {
697
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
-                EE_Error::add_attention(
699
-                    sprintf(
700
-                        esc_html__(
701
-                            '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.',
702
-                            'event_espresso'
703
-                        ),
704
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
-                    )
706
-                );
707
-            }
708
-            return;
709
-        } else if ($orig_status === EEM_Event::sold_out) {
710
-            EE_Error::add_attention(
711
-                sprintf(
712
-                    esc_html__(
713
-                        '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.',
714
-                        'event_espresso'
715
-                    ),
716
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
717
-                )
718
-            );
719
-        }
720
-        //now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
-        if ( ! $event->tickets_on_sale()) {
722
-            return;
723
-        }
724
-        //made it here so show warning
725
-        $this->_edit_event_warning();
726
-    }
727
-
728
-
729
-
730
-    /**
731
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
732
-     * When needed, hook this into a EE_Error::add_error() notice.
733
-     *
734
-     * @access protected
735
-     * @return void
736
-     */
737
-    protected function _edit_event_warning()
738
-    {
739
-        // we don't want to add warnings during these requests
740
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
-            return;
742
-        }
743
-        EE_Error::add_attention(
744
-            esc_html__(
745
-                'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
-                'event_espresso'
747
-            )
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
-    /**
826
-     * Provides the legend item array for the default list table view.
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
-    /**
883
-     * @return EEM_Event
884
-     */
885
-    private function _event_model()
886
-    {
887
-        if ( ! $this->_event_model instanceof EEM_Event) {
888
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
889
-        }
890
-        return $this->_event_model;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * Adds extra buttons to the WP CPT permalink field row.
897
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
-     *
899
-     * @param  string $return    the current html
900
-     * @param  int    $id        the post id for the page
901
-     * @param  string $new_title What the title is
902
-     * @param  string $new_slug  what the slug is
903
-     * @return string            The new html string for the permalink area
904
-     */
905
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
-    {
907
-        //make sure this is only when editing
908
-        if ( ! empty($id)) {
909
-            $post = get_post($id);
910
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
-                       . esc_html__('Shortcode', 'event_espresso')
912
-                       . '</a> ';
913
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
-                       . $post->ID
915
-                       . ']">';
916
-        }
917
-        return $return;
918
-    }
919
-
920
-
921
-
922
-    /**
923
-     * _events_overview_list_table
924
-     * This contains the logic for showing the events_overview list
925
-     *
926
-     * @access protected
927
-     * @return void
928
-     * @throws \EE_Error
929
-     */
930
-    protected function _events_overview_list_table()
931
-    {
932
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
-            ? (array)$this->_template_args['after_list_table']
935
-            : array();
936
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
-                                                                              . EEH_Template::get_button_or_link(
938
-                get_post_type_archive_link('espresso_events'),
939
-                esc_html__("View Event Archive Page", "event_espresso"),
940
-                'button'
941
-            );
942
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
-                'create_new',
945
-                'add',
946
-                array(),
947
-                'add-new-h2'
948
-            );
949
-        $this->display_admin_list_table_page_with_no_sidebar();
950
-    }
951
-
952
-
953
-
954
-    /**
955
-     * this allows for extra misc actions in the default WP publish box
956
-     *
957
-     * @return void
958
-     */
959
-    public function extra_misc_actions_publish_box()
960
-    {
961
-        $this->_generate_publish_box_extra_content();
962
-    }
963
-
964
-
965
-
966
-    /**
967
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
-     * Typically you would use this to save any additional data.
969
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
-     * ALSO very important.  When a post transitions from scheduled to published,
971
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
-     * So MAKE sure that you handle this accordingly.
973
-     *
974
-     * @access protected
975
-     * @abstract
976
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
-     * @param  object $post    The post object of the cpt that was saved.
978
-     * @return void
979
-     * @throws \EE_Error
980
-     */
981
-    protected function _insert_update_cpt_item($post_id, $post)
982
-    {
983
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
-            //get out we're not processing an event save.
985
-            return;
986
-        }
987
-        $event_values = array(
988
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
-            'EVT_additional_limit'            => min(
991
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
-            ),
994
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
-                ? $this->_req_data['EVT_default_registration_status']
996
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
997
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
-                ? $this->_req_data['timezone_string'] : null,
1001
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
-                ? $this->_req_data['externalURL'] : null,
1003
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
-                ? $this->_req_data['event_phone'] : null,
1005
-        );
1006
-        //update event
1007
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
-        //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!
1009
-        $get_one_where = array(
1010
-            $this->_event_model()->primary_key_name() => $post_id,
1011
-            'OR' => array(
1012
-                'status' => $post->post_status,
1013
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
-                // but the returned object here has a status of "publish", so use the original post status as well
1015
-                'status*1' => $this->_req_data['original_post_status'],
1016
-            )
1017
-        );
1018
-        $event = $this->_event_model()->get_one(array($get_one_where));
1019
-        //the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
-        $event_update_callbacks = apply_filters(
1021
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
-            array(
1023
-                array($this, '_default_venue_update'),
1024
-                array($this, '_default_tickets_update')
1025
-            )
1026
-        );
1027
-        $att_success = true;
1028
-        foreach ($event_update_callbacks as $e_callback) {
1029
-            $_success = is_callable($e_callback)
1030
-                ? call_user_func($e_callback, $event, $this->_req_data)
1031
-                : false;
1032
-            //if ANY of these updates fail then we want the appropriate global error message
1033
-            $att_success = ! $att_success ? $att_success : $_success;
1034
-        }
1035
-        //any errors?
1036
-        if ($success && false === $att_success) {
1037
-            EE_Error::add_error(
1038
-                esc_html__(
1039
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1040
-                    'event_espresso'
1041
-                ),
1042
-                __FILE__,
1043
-                __FUNCTION__,
1044
-                __LINE__
1045
-            );
1046
-        } else if ($success === false) {
1047
-            EE_Error::add_error(
1048
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
-                __FILE__,
1050
-                __FUNCTION__,
1051
-                __LINE__
1052
-            );
1053
-        }
1054
-    }
1055
-
1056
-
1057
-
1058
-    /**
1059
-     * @see parent::restore_item()
1060
-     * @param int $post_id
1061
-     * @param int $revision_id
1062
-     */
1063
-    protected function _restore_cpt_item($post_id, $revision_id)
1064
-    {
1065
-        //copy existing event meta to new post
1066
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
-        if ($post_evt instanceof EE_Event) {
1068
-            //meta revision restore
1069
-            $post_evt->restore_revision($revision_id);
1070
-            //related objs restore
1071
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
-        }
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * Attach the venue to the Event
1079
-     *
1080
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1081
-     * @param  array     $data   The request data from the form
1082
-     * @return bool           Success or fail.
1083
-     */
1084
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
-    {
1086
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1088
-        $rows_affected = null;
1089
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
-        // very important.  If we don't have a venue name...
1091
-        // then we'll get out because not necessary to create empty venue
1092
-        if (empty($data['venue_title'])) {
1093
-            return false;
1094
-        }
1095
-        $venue_array = array(
1096
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
-                : null,
1102
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
-            'status'              => 'publish',
1115
-        );
1116
-        //if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
-        if ( ! empty($venue_id)) {
1118
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1119
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1120
-            //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.
1121
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1122
-            return $rows_affected > 0 ? true : false;
1123
-        } else {
1124
-            //we insert the venue
1125
-            $venue_id = $venue_model->insert($venue_array);
1126
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1127
-            return ! empty($venue_id) ? true : false;
1128
-        }
1129
-        //when we have the ancestor come in it's already been handled by the revision save.
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
-     *
1137
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1138
-     * @param  array    $data   The request data from the form
1139
-     * @return array
1140
-     */
1141
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
-    {
1143
-        $success = true;
1144
-        $saved_dtt = null;
1145
-        $saved_tickets = array();
1146
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1147
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
-            //trim all values to ensure any excess whitespace is removed.
1149
-            $dtt = array_map('trim', $dtt);
1150
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
-                : $dtt['DTT_EVT_start'];
1152
-            $datetime_values = array(
1153
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
-                'DTT_order'     => $row,
1158
-            );
1159
-            //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.
1160
-            if ( ! empty($dtt['DTT_ID'])) {
1161
-                $DTM = EE_Registry::instance()
1162
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1164
-                $DTM->set_date_format($incoming_date_formats[0]);
1165
-                $DTM->set_time_format($incoming_date_formats[1]);
1166
-                foreach ($datetime_values as $field => $value) {
1167
-                    $DTM->set($field, $value);
1168
-                }
1169
-                //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.
1170
-                $saved_dtts[$DTM->ID()] = $DTM;
1171
-            } else {
1172
-                $DTM = EE_Registry::instance()->load_class(
1173
-                    'Datetime',
1174
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
-                    false,
1176
-                    false
1177
-                );
1178
-                foreach ($datetime_values as $field => $value) {
1179
-                    $DTM->set($field, $value);
1180
-                }
1181
-            }
1182
-            $DTM->save();
1183
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
-            //load DTT helper
1185
-            //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.
1186
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
-                $DTT->save();
1190
-            }
1191
-            //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.
1192
-            $saved_dtt = $DTT;
1193
-            $success = ! $success ? $success : $DTT;
1194
-            //if ANY of these updates fail then we want the appropriate global error message.
1195
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1196
-        }
1197
-        //no dtts get deleted so we don't do any of that logic here.
1198
-        //update tickets next
1199
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1201
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1202
-            $update_prices = false;
1203
-            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
-                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
-            // trim inputs to ensure any excess whitespace is removed.
1206
-            $tkt = array_map('trim', $tkt);
1207
-            if (empty($tkt['TKT_start_date'])) {
1208
-                //let's use now in the set timezone.
1209
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
-            }
1212
-            if (empty($tkt['TKT_end_date'])) {
1213
-                //use the start date of the first datetime
1214
-                $dtt = $evtobj->first_datetime();
1215
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
-                    $incoming_date_formats[0],
1217
-                    $incoming_date_formats[1]
1218
-                );
1219
-            }
1220
-            $TKT_values = array(
1221
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1226
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1227
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
-                'TKT_row'         => $row,
1232
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
-                'TKT_price'       => $ticket_price,
1234
-            );
1235
-            //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.
1236
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
-                $TKT_values['TKT_ID'] = 0;
1238
-                $TKT_values['TKT_is_default'] = 0;
1239
-                $TKT_values['TKT_price'] = $ticket_price;
1240
-                $update_prices = true;
1241
-            }
1242
-            //if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
-            //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.
1244
-            //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.
1245
-            if ( ! empty($tkt['TKT_ID'])) {
1246
-                $TKT = EE_Registry::instance()
1247
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1249
-                if ($TKT instanceof EE_Ticket) {
1250
-                    $ticket_sold = $TKT->count_related(
1251
-                        'Registration',
1252
-                        array(
1253
-                            array(
1254
-                                'STS_ID' => array(
1255
-                                    'NOT IN',
1256
-                                    array(EEM_Registration::status_id_incomplete),
1257
-                                ),
1258
-                            ),
1259
-                        )
1260
-                    ) > 0 ? true : false;
1261
-                    //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.
1262
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
-                                      && ! $TKT->get(
1264
-                        'TKT_deleted'
1265
-                    ) ? true : false;
1266
-                    $TKT->set_date_format($incoming_date_formats[0]);
1267
-                    $TKT->set_time_format($incoming_date_formats[1]);
1268
-                    //set new values
1269
-                    foreach ($TKT_values as $field => $value) {
1270
-                        if ($field == 'TKT_qty') {
1271
-                            $TKT->set_qty($value);
1272
-                        } else {
1273
-                            $TKT->set($field, $value);
1274
-                        }
1275
-                    }
1276
-                    //if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
-                    if ($create_new_TKT) {
1278
-                        //archive the old ticket first
1279
-                        $TKT->set('TKT_deleted', 1);
1280
-                        $TKT->save();
1281
-                        //make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
-                        $saved_tickets[$TKT->ID()] = $TKT;
1283
-                        //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.
1284
-                        $TKT = clone $TKT;
1285
-                        $TKT->set('TKT_ID', 0);
1286
-                        $TKT->set('TKT_deleted', 0);
1287
-                        $TKT->set('TKT_price', $ticket_price);
1288
-                        $TKT->set('TKT_sold', 0);
1289
-                        //now we need to make sure that $new prices are created as well and attached to new ticket.
1290
-                        $update_prices = true;
1291
-                    }
1292
-                    //make sure price is set if it hasn't been already
1293
-                    $TKT->set('TKT_price', $ticket_price);
1294
-                }
1295
-            } else {
1296
-                //no TKT_id so a new TKT
1297
-                $TKT_values['TKT_price'] = $ticket_price;
1298
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
-                if ($TKT instanceof EE_Ticket) {
1300
-                    //need to reset values to properly account for the date formats
1301
-                    $TKT->set_date_format($incoming_date_formats[0]);
1302
-                    $TKT->set_time_format($incoming_date_formats[1]);
1303
-                    $TKT->set_timezone($evtobj->get_timezone());
1304
-                    //set new values
1305
-                    foreach ($TKT_values as $field => $value) {
1306
-                        if ($field == 'TKT_qty') {
1307
-                            $TKT->set_qty($value);
1308
-                        } else {
1309
-                            $TKT->set($field, $value);
1310
-                        }
1311
-                    }
1312
-                    $update_prices = true;
1313
-                }
1314
-            }
1315
-            // cap ticket qty by datetime reg limits
1316
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
-            //update ticket.
1318
-            $TKT->save();
1319
-            //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.
1320
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
-                $TKT->save();
1324
-            }
1325
-            //initially let's add the ticket to the dtt
1326
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
-            $saved_tickets[$TKT->ID()] = $TKT;
1328
-            //add prices to ticket
1329
-            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
-        }
1331
-        //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.
1332
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
-        foreach ($tickets_removed as $id) {
1335
-            $id = absint($id);
1336
-            //get the ticket for this id
1337
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
-            //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)
1339
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1340
-            foreach ($dtts as $dtt) {
1341
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
-            }
1343
-            //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))
1344
-            $tkt_to_remove->delete_related_permanently('Price');
1345
-            //finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
-            $tkt_to_remove->delete_permanently();
1347
-        }
1348
-        return array($saved_dtt, $saved_tickets);
1349
-    }
1350
-
1351
-
1352
-
1353
-    /**
1354
-     * This attaches a list of given prices to a ticket.
1355
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
-     * price info and prices are automatically "archived" via the ticket.
1358
-     *
1359
-     * @access  private
1360
-     * @param array     $prices     Array of prices from the form.
1361
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
-     * @return  void
1364
-     */
1365
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
-    {
1367
-        foreach ($prices as $row => $prc) {
1368
-            $PRC_values = array(
1369
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
-                'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
-                'PRC_order'      => $row,
1376
-            );
1377
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
-                $PRC_values['PRC_ID'] = 0;
1379
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
-            } else {
1381
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
-                //update this price with new values
1383
-                foreach ($PRC_values as $field => $newprc) {
1384
-                    $PRC->set($field, $newprc);
1385
-                }
1386
-                $PRC->save();
1387
-            }
1388
-            $ticket->_add_relation_to($PRC, 'Price');
1389
-        }
1390
-    }
1391
-
1392
-
1393
-
1394
-    /**
1395
-     * Add in our autosave ajax handlers
1396
-     *
1397
-     */
1398
-    protected function _ee_autosave_create_new()
1399
-    {
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * More autosave handlers.
1405
-     */
1406
-    protected function _ee_autosave_edit()
1407
-    {
1408
-        return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
-    }
1410
-
1411
-
1412
-
1413
-    /**
1414
-     *    _generate_publish_box_extra_content
1415
-     */
1416
-    private function _generate_publish_box_extra_content()
1417
-    {
1418
-        //load formatter helper
1419
-        //args for getting related registrations
1420
-        $approved_query_args = array(
1421
-            array(
1422
-                'REG_deleted' => 0,
1423
-                'STS_ID'      => EEM_Registration::status_id_approved,
1424
-            ),
1425
-        );
1426
-        $not_approved_query_args = array(
1427
-            array(
1428
-                'REG_deleted' => 0,
1429
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
-            ),
1431
-        );
1432
-        $pending_payment_query_args = array(
1433
-            array(
1434
-                'REG_deleted' => 0,
1435
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
-            ),
1437
-        );
1438
-        // publish box
1439
-        $publish_box_extra_args = array(
1440
-            'view_approved_reg_url'        => add_query_arg(
1441
-                array(
1442
-                    'action'      => 'default',
1443
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1444
-                    '_reg_status' => EEM_Registration::status_id_approved,
1445
-                ),
1446
-                REG_ADMIN_URL
1447
-            ),
1448
-            'view_not_approved_reg_url'    => add_query_arg(
1449
-                array(
1450
-                    'action'      => 'default',
1451
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1452
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1453
-                ),
1454
-                REG_ADMIN_URL
1455
-            ),
1456
-            'view_pending_payment_reg_url' => add_query_arg(
1457
-                array(
1458
-                    'action'      => 'default',
1459
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1460
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1461
-                ),
1462
-                REG_ADMIN_URL
1463
-            ),
1464
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
-                'Registration',
1466
-                $approved_query_args
1467
-            ),
1468
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
-                'Registration',
1470
-                $not_approved_query_args
1471
-            ),
1472
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
-                'Registration',
1474
-                $pending_payment_query_args
1475
-            ),
1476
-            'misc_pub_section_class'       => apply_filters(
1477
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
-                'misc-pub-section'
1479
-            ),
1480
-        );
1481
-        ob_start();
1482
-        do_action(
1483
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
-            $this->_cpt_model_obj
1485
-        );
1486
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
-        // load template
1488
-        EEH_Template::display_template(
1489
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
-            $publish_box_extra_args
1491
-        );
1492
-    }
1493
-
1494
-
1495
-
1496
-    /**
1497
-     * @return EE_Event
1498
-     */
1499
-    public function get_event_object()
1500
-    {
1501
-        return $this->_cpt_model_obj;
1502
-    }
1503
-
1504
-
1505
-
1506
-
1507
-    /** METABOXES * */
1508
-    /**
1509
-     * _register_event_editor_meta_boxes
1510
-     * add all metaboxes related to the event_editor
1511
-     *
1512
-     * @return void
1513
-     */
1514
-    protected function _register_event_editor_meta_boxes()
1515
-    {
1516
-        $this->verify_cpt_object();
1517
-        add_meta_box(
1518
-            'espresso_event_editor_tickets',
1519
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
-            array($this, 'ticket_metabox'),
1521
-            $this->page_slug,
1522
-            'normal',
1523
-            'high'
1524
-        );
1525
-        add_meta_box(
1526
-            'espresso_event_editor_event_options',
1527
-            esc_html__('Event Registration Options', 'event_espresso'),
1528
-            array($this, 'registration_options_meta_box'),
1529
-            $this->page_slug,
1530
-            'side',
1531
-            'default'
1532
-        );
1533
-        // NOTE: if you're looking for other metaboxes in here,
1534
-        // where a metabox has a related management page in the admin
1535
-        // you will find it setup in the related management page's "_Hooks" file.
1536
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
-    }
1538
-
1539
-
1540
-    /**
1541
-     * @throws DomainException
1542
-     * @throws EE_Error
1543
-     */
1544
-    public function ticket_metabox()
1545
-    {
1546
-        $existing_datetime_ids = $existing_ticket_ids = array();
1547
-        //defaults for template args
1548
-        $template_args = array(
1549
-            'existing_datetime_ids'    => '',
1550
-            'event_datetime_help_link' => '',
1551
-            'ticket_options_help_link' => '',
1552
-            'time'                     => null,
1553
-            'ticket_rows'              => '',
1554
-            'existing_ticket_ids'      => '',
1555
-            'total_ticket_rows'        => 1,
1556
-            'ticket_js_structure'      => '',
1557
-            'trash_icon'               => 'ee-lock-icon',
1558
-            'disabled'                 => '',
1559
-        );
1560
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
-        /**
1563
-         * 1. Start with retrieving Datetimes
1564
-         * 2. Fore each datetime get related tickets
1565
-         * 3. For each ticket get related prices
1566
-         */
1567
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
-        /** @type EE_Datetime $first_datetime */
1569
-        $first_datetime = reset($times);
1570
-        //do we get related tickets?
1571
-        if ($first_datetime instanceof EE_Datetime
1572
-            && $first_datetime->ID() !== 0
1573
-        ) {
1574
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
-            $template_args['time'] = $first_datetime;
1576
-            $related_tickets = $first_datetime->tickets(
1577
-                array(
1578
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
-                    'default_where_conditions' => 'none',
1580
-                )
1581
-            );
1582
-            if ( ! empty($related_tickets)) {
1583
-                $template_args['total_ticket_rows'] = count($related_tickets);
1584
-                $row = 0;
1585
-                foreach ($related_tickets as $ticket) {
1586
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
-                    $row++;
1589
-                }
1590
-            } else {
1591
-                $template_args['total_ticket_rows'] = 1;
1592
-                /** @type EE_Ticket $ticket */
1593
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
-            }
1596
-        } else {
1597
-            $template_args['time'] = $times[0];
1598
-            /** @type EE_Ticket $ticket */
1599
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
-            // NOTE: we're just sending the first default row
1602
-            // (decaf can't manage default tickets so this should be sufficient);
1603
-        }
1604
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
-            'event_editor_event_datetimes_help_tab'
1606
-        );
1607
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
-            true
1613
-        );
1614
-        $template = apply_filters(
1615
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
-        );
1618
-        EEH_Template::display_template($template, $template_args);
1619
-    }
1620
-
1621
-
1622
-
1623
-    /**
1624
-     * Setup an individual ticket form for the decaf event editor page
1625
-     *
1626
-     * @access private
1627
-     * @param  EE_Ticket $ticket   the ticket object
1628
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
-     * @param int        $row
1630
-     * @return string generated html for the ticket row.
1631
-     */
1632
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
-    {
1634
-        $template_args = array(
1635
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
-                : '',
1638
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1640
-            'TKT_name'            => $ticket->get('TKT_name'),
1641
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
-            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
-                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
-            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
-                : ' disabled=disabled',
1652
-        );
1653
-        $price = $ticket->ID() !== 0
1654
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1656
-        $price_args = array(
1657
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
-            'PRC_amount'            => $price->get('PRC_amount'),
1659
-            'PRT_ID'                => $price->get('PRT_ID'),
1660
-            'PRC_ID'                => $price->get('PRC_ID'),
1661
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1662
-        );
1663
-        //make sure we have default start and end dates if skeleton
1664
-        //handle rows that should NOT be empty
1665
-        if (empty($template_args['TKT_start_date'])) {
1666
-            //if empty then the start date will be now.
1667
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
-        }
1669
-        if (empty($template_args['TKT_end_date'])) {
1670
-            //get the earliest datetime (if present);
1671
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
-                ? $this->_cpt_model_obj->get_first_related(
1673
-                    'Datetime',
1674
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
-                )
1676
-                : null;
1677
-            if ( ! empty($earliest_dtt)) {
1678
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
-            } else {
1680
-                $template_args['TKT_end_date'] = date(
1681
-                    'Y-m-d h:i a',
1682
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
-                );
1684
-            }
1685
-        }
1686
-        $template_args = array_merge($template_args, $price_args);
1687
-        $template = apply_filters(
1688
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
-            $ticket
1691
-        );
1692
-        return EEH_Template::display_template($template, $template_args, true);
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @throws DomainException
1698
-     */
1699
-    public function registration_options_meta_box()
1700
-    {
1701
-        $yes_no_values = array(
1702
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
-        );
1705
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1706
-            array(
1707
-                EEM_Registration::status_id_cancelled,
1708
-                EEM_Registration::status_id_declined,
1709
-                EEM_Registration::status_id_incomplete,
1710
-            ),
1711
-            true
1712
-        );
1713
-        //$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
-        $template_args['_event'] = $this->_cpt_model_obj;
1715
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
-            'default_reg_status',
1719
-            $default_reg_status_values,
1720
-            $this->_cpt_model_obj->default_registration_status()
1721
-        );
1722
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1723
-            'display_desc',
1724
-            $yes_no_values,
1725
-            $this->_cpt_model_obj->display_description()
1726
-        );
1727
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
-            'display_ticket_selector',
1729
-            $yes_no_values,
1730
-            $this->_cpt_model_obj->display_ticket_selector(),
1731
-            '',
1732
-            '',
1733
-            false
1734
-        );
1735
-        $template_args['additional_registration_options'] = apply_filters(
1736
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
-            '',
1738
-            $template_args,
1739
-            $yes_no_values,
1740
-            $default_reg_status_values
1741
-        );
1742
-        EEH_Template::display_template(
1743
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
-            $template_args
1745
-        );
1746
-    }
1747
-
1748
-
1749
-
1750
-    /**
1751
-     * _get_events()
1752
-     * This method simply returns all the events (for the given _view and paging)
1753
-     *
1754
-     * @access public
1755
-     * @param int  $per_page     count of items per page (20 default);
1756
-     * @param int  $current_page what is the current page being viewed.
1757
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
-     *                           If FALSE then we return an array of event objects
1759
-     *                           that match the given _view and paging parameters.
1760
-     * @return array an array of event objects.
1761
-     */
1762
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
-    {
1764
-        $EEME = $this->_event_model();
1765
-        $offset = ($current_page - 1) * $per_page;
1766
-        $limit = $count ? null : $offset . ',' . $per_page;
1767
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
-        if (isset($this->_req_data['month_range'])) {
1770
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
-            //simulate the FIRST day of the month, that fixes issues for months like February
1772
-            //where PHP doesn't know what to assume for date.
1773
-            //@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
-        }
1777
-        $where = array();
1778
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
-        //determine what post_status our condition will have for the query.
1780
-        switch ($status) {
1781
-            case 'month' :
1782
-            case 'today' :
1783
-            case null :
1784
-            case 'all' :
1785
-                break;
1786
-            case 'draft' :
1787
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1788
-                break;
1789
-            default :
1790
-                $where['status'] = $status;
1791
-        }
1792
-        //categories?
1793
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
-            ? $this->_req_data['EVT_CAT'] : null;
1795
-        if ( ! empty ($category)) {
1796
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
-            $where['Term_Taxonomy.term_id'] = $category;
1798
-        }
1799
-        //date where conditions
1800
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
-            $DateTime = new DateTime(
1803
-                $year_r . '-' . $month_r . '-01 00:00:00',
1804
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
-            );
1806
-            $start = $DateTime->format(implode(' ', $start_formats));
1807
-            $end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
-                ->format('t'))->setTime(23, 59, 59)
1809
-                            ->format(implode(' ', $start_formats));
1810
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
-        } else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
-            $now = date('Y-m-01');
1818
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
-                            ->setTime(23, 59, 59)
1822
-                            ->format(implode(' ', $start_formats));
1823
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
-        }
1825
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
-            $where['EVT_wp_user'] = get_current_user_id();
1827
-        } else {
1828
-            if ( ! isset($where['status'])) {
1829
-                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
-                    $where['OR'] = array(
1831
-                        'status*restrict_private' => array('!=', 'private'),
1832
-                        'AND'                     => array(
1833
-                            'status*inclusive' => array('=', 'private'),
1834
-                            'EVT_wp_user'      => get_current_user_id(),
1835
-                        ),
1836
-                    );
1837
-                }
1838
-            }
1839
-        }
1840
-        if (isset($this->_req_data['EVT_wp_user'])) {
1841
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
-            ) {
1844
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
-            }
1846
-        }
1847
-        //search query handling
1848
-        if (isset($this->_req_data['s'])) {
1849
-            $search_string = '%' . $this->_req_data['s'] . '%';
1850
-            $where['OR'] = array(
1851
-                'EVT_name'       => array('LIKE', $search_string),
1852
-                'EVT_desc'       => array('LIKE', $search_string),
1853
-                'EVT_short_desc' => array('LIKE', $search_string),
1854
-            );
1855
-        }
1856
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
-        $query_params = apply_filters(
1858
-            'FHEE__Events_Admin_Page__get_events__query_params',
1859
-            array(
1860
-                $where,
1861
-                'limit'    => $limit,
1862
-                'order_by' => $orderby,
1863
-                'order'    => $order,
1864
-                'group_by' => 'EVT_ID',
1865
-            ),
1866
-            $this->_req_data
1867
-        );
1868
-        //let's first check if we have special requests coming in.
1869
-        if (isset($this->_req_data['active_status'])) {
1870
-            switch ($this->_req_data['active_status']) {
1871
-                case 'upcoming' :
1872
-                    return $EEME->get_upcoming_events($query_params, $count);
1873
-                    break;
1874
-                case 'expired' :
1875
-                    return $EEME->get_expired_events($query_params, $count);
1876
-                    break;
1877
-                case 'active' :
1878
-                    return $EEME->get_active_events($query_params, $count);
1879
-                    break;
1880
-                case 'inactive' :
1881
-                    return $EEME->get_inactive_events($query_params, $count);
1882
-                    break;
1883
-            }
1884
-        }
1885
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
-        return $events;
1887
-    }
1888
-
1889
-
1890
-
1891
-    /**
1892
-     * handling for WordPress CPT actions (trash, restore, delete)
1893
-     *
1894
-     * @param string $post_id
1895
-     */
1896
-    public function trash_cpt_item($post_id)
1897
-    {
1898
-        $this->_req_data['EVT_ID'] = $post_id;
1899
-        $this->_trash_or_restore_event('trash', false);
1900
-    }
1901
-
1902
-
1903
-
1904
-    /**
1905
-     * @param string $post_id
1906
-     */
1907
-    public function restore_cpt_item($post_id)
1908
-    {
1909
-        $this->_req_data['EVT_ID'] = $post_id;
1910
-        $this->_trash_or_restore_event('draft', false);
1911
-    }
1912
-
1913
-
1914
-
1915
-    /**
1916
-     * @param string $post_id
1917
-     */
1918
-    public function delete_cpt_item($post_id)
1919
-    {
1920
-        $this->_req_data['EVT_ID'] = $post_id;
1921
-        $this->_delete_event(false);
1922
-    }
1923
-
1924
-
1925
-
1926
-    /**
1927
-     * _trash_or_restore_event
1928
-     *
1929
-     * @access protected
1930
-     * @param  string $event_status
1931
-     * @param bool    $redirect_after
1932
-     */
1933
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
-    {
1935
-        //determine the event id and set to array.
1936
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
-        // loop thru events
1938
-        if ($EVT_ID) {
1939
-            // clean status
1940
-            $event_status = sanitize_key($event_status);
1941
-            // grab status
1942
-            if ( ! empty($event_status)) {
1943
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1944
-            } else {
1945
-                $success = false;
1946
-                $msg = esc_html__(
1947
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
-                    'event_espresso'
1949
-                );
1950
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
-            }
1952
-        } else {
1953
-            $success = false;
1954
-            $msg = esc_html__(
1955
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
-                'event_espresso'
1957
-            );
1958
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
-        }
1960
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
-        if ($redirect_after) {
1962
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
-        }
1964
-    }
1965
-
1966
-
1967
-
1968
-    /**
1969
-     * _trash_or_restore_events
1970
-     *
1971
-     * @access protected
1972
-     * @param  string $event_status
1973
-     * @return void
1974
-     */
1975
-    protected function _trash_or_restore_events($event_status = 'trash')
1976
-    {
1977
-        // clean status
1978
-        $event_status = sanitize_key($event_status);
1979
-        // grab status
1980
-        if ( ! empty($event_status)) {
1981
-            $success = true;
1982
-            //determine the event id and set to array.
1983
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
-            // loop thru events
1985
-            foreach ($EVT_IDs as $EVT_ID) {
1986
-                if ($EVT_ID = absint($EVT_ID)) {
1987
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1988
-                    $success = $results !== false ? $success : false;
1989
-                } else {
1990
-                    $msg = sprintf(
1991
-                        esc_html__(
1992
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
-                            'event_espresso'
1994
-                        ),
1995
-                        $EVT_ID
1996
-                    );
1997
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
-                    $success = false;
1999
-                }
2000
-            }
2001
-        } else {
2002
-            $success = false;
2003
-            $msg = esc_html__(
2004
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
-                'event_espresso'
2006
-            );
2007
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
-        }
2009
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2010
-        $success = $success ? 2 : false;
2011
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
-    }
2014
-
2015
-
2016
-
2017
-    /**
2018
-     * _trash_or_restore_events
2019
-     *
2020
-     * @access  private
2021
-     * @param  int    $EVT_ID
2022
-     * @param  string $event_status
2023
-     * @return bool
2024
-     */
2025
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
-    {
2027
-        // grab event id
2028
-        if ( ! $EVT_ID) {
2029
-            $msg = esc_html__(
2030
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2031
-                'event_espresso'
2032
-            );
2033
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
-            return false;
2035
-        }
2036
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
-        // clean status
2038
-        $event_status = sanitize_key($event_status);
2039
-        // grab status
2040
-        if (empty($event_status)) {
2041
-            $msg = esc_html__(
2042
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2043
-                'event_espresso'
2044
-            );
2045
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
-            return false;
2047
-        }
2048
-        // was event trashed or restored ?
2049
-        switch ($event_status) {
2050
-            case 'draft' :
2051
-                $action = 'restored from the trash';
2052
-                $hook = 'AHEE_event_restored_from_trash';
2053
-                break;
2054
-            case 'trash' :
2055
-                $action = 'moved to the trash';
2056
-                $hook = 'AHEE_event_moved_to_trash';
2057
-                break;
2058
-            default :
2059
-                $action = 'updated';
2060
-                $hook = false;
2061
-        }
2062
-        //use class to change status
2063
-        $this->_cpt_model_obj->set_status($event_status);
2064
-        $success = $this->_cpt_model_obj->save();
2065
-        if ($success === false) {
2066
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
-            return false;
2069
-        }
2070
-        if ($hook) {
2071
-            do_action($hook);
2072
-        }
2073
-        return true;
2074
-    }
2075
-
2076
-
2077
-
2078
-    /**
2079
-     * _delete_event
2080
-     *
2081
-     * @access protected
2082
-     * @param bool $redirect_after
2083
-     */
2084
-    protected function _delete_event($redirect_after = true)
2085
-    {
2086
-        //determine the event id and set to array.
2087
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
-        // loop thru events
2090
-        if ($EVT_ID) {
2091
-            $success = $this->_permanently_delete_event($EVT_ID);
2092
-            // get list of events with no prices
2093
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
-            // remove this event from the list of events with no prices
2095
-            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2097
-            }
2098
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
-        } else {
2100
-            $success = false;
2101
-            $msg = esc_html__(
2102
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
-                'event_espresso'
2104
-            );
2105
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
-        }
2107
-        if ($redirect_after) {
2108
-            $this->_redirect_after_action(
2109
-                $success,
2110
-                'Event',
2111
-                'deleted',
2112
-                array('action' => 'default', 'status' => 'trash')
2113
-            );
2114
-        }
2115
-    }
2116
-
2117
-
2118
-
2119
-    /**
2120
-     * _delete_events
2121
-     *
2122
-     * @access protected
2123
-     * @return void
2124
-     */
2125
-    protected function _delete_events()
2126
-    {
2127
-        $success = true;
2128
-        // get list of events with no prices
2129
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
-        //determine the event id and set to array.
2131
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
-        // loop thru events
2133
-        foreach ($EVT_IDs as $EVT_ID) {
2134
-            $EVT_ID = absint($EVT_ID);
2135
-            if ($EVT_ID) {
2136
-                $results = $this->_permanently_delete_event($EVT_ID);
2137
-                $success = $results !== false ? $success : false;
2138
-                // remove this event from the list of events with no prices
2139
-                unset($espresso_no_ticket_prices[$EVT_ID]);
2140
-            } else {
2141
-                $success = false;
2142
-                $msg = esc_html__(
2143
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
-                    'event_espresso'
2145
-                );
2146
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
-            }
2148
-        }
2149
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2151
-        $success = $success ? 2 : false;
2152
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
-    }
2154
-
2155
-
2156
-
2157
-    /**
2158
-     * _permanently_delete_event
2159
-     *
2160
-     * @access  private
2161
-     * @param  int $EVT_ID
2162
-     * @return bool
2163
-     */
2164
-    private function _permanently_delete_event($EVT_ID = 0)
2165
-    {
2166
-        // grab event id
2167
-        if ( ! $EVT_ID) {
2168
-            $msg = esc_html__(
2169
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2170
-                'event_espresso'
2171
-            );
2172
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
-            return false;
2174
-        }
2175
-        if (
2176
-            ! $this->_cpt_model_obj instanceof EE_Event
2177
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2178
-        ) {
2179
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
-        }
2181
-        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
-            return false;
2183
-        }
2184
-        //need to delete related tickets and prices first.
2185
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
-        foreach ($datetimes as $datetime) {
2187
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
-            $tickets = $datetime->get_many_related('Ticket');
2189
-            foreach ($tickets as $ticket) {
2190
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2191
-                $ticket->delete_related_permanently('Price');
2192
-                $ticket->delete_permanently();
2193
-            }
2194
-            $datetime->delete();
2195
-        }
2196
-        //what about related venues or terms?
2197
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
-        foreach ($venues as $venue) {
2199
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
-        }
2201
-        //any attached question groups?
2202
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
-        if ( ! empty($question_groups)) {
2204
-            foreach ($question_groups as $question_group) {
2205
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
-            }
2207
-        }
2208
-        //Message Template Groups
2209
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
-        foreach ($term_taxonomies as $term_taxonomy) {
2213
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
-        }
2215
-        $success = $this->_cpt_model_obj->delete_permanently();
2216
-        // did it all go as planned ?
2217
-        if ($success) {
2218
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
-            EE_Error::add_success($msg);
2220
-        } else {
2221
-            $msg = sprintf(
2222
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
-                $EVT_ID
2224
-            );
2225
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
-            return false;
2227
-        }
2228
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
-        return true;
2230
-    }
2231
-
2232
-
2233
-
2234
-    /**
2235
-     * get total number of events
2236
-     *
2237
-     * @access public
2238
-     * @return int
2239
-     */
2240
-    public function total_events()
2241
-    {
2242
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
-        return $count;
2244
-    }
2245
-
2246
-
2247
-
2248
-    /**
2249
-     * get total number of draft events
2250
-     *
2251
-     * @access public
2252
-     * @return int
2253
-     */
2254
-    public function total_events_draft()
2255
-    {
2256
-        $where = array(
2257
-            'status' => array('IN', array('draft', 'auto-draft')),
2258
-        );
2259
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
-        return $count;
2261
-    }
2262
-
2263
-
2264
-
2265
-    /**
2266
-     * get total number of trashed events
2267
-     *
2268
-     * @access public
2269
-     * @return int
2270
-     */
2271
-    public function total_trashed_events()
2272
-    {
2273
-        $where = array(
2274
-            'status' => 'trash',
2275
-        );
2276
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
-        return $count;
2278
-    }
2279
-
2280
-
2281
-    /**
2282
-     *    _default_event_settings
2283
-     *    This generates the Default Settings Tab
2284
-     *
2285
-     * @return void
2286
-     * @throws EE_Error
2287
-     */
2288
-    protected function _default_event_settings()
2289
-    {
2290
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2291
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2292
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
-        $this->display_admin_page_with_sidebar();
2294
-    }
2295
-
2296
-
2297
-    /**
2298
-     * Return the form for event settings.
2299
-     * @return EE_Form_Section_Proper
2300
-     */
2301
-    protected function _default_event_settings_form()
2302
-    {
2303
-        $registration_config = EE_Registry::instance()->CFG->registration;
2304
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
-        //exclude
2306
-            array(
2307
-                EEM_Registration::status_id_cancelled,
2308
-                EEM_Registration::status_id_declined,
2309
-                EEM_Registration::status_id_incomplete,
2310
-                EEM_Registration::status_id_wait_list,
2311
-            ),
2312
-            true
2313
-        );
2314
-        return new EE_Form_Section_Proper(
2315
-            array(
2316
-                'name' => 'update_default_event_settings',
2317
-                'html_id' => 'update_default_event_settings',
2318
-                'html_class' => 'form-table',
2319
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
-                'subsections' => apply_filters(
2321
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
-                    array(
2323
-                        'default_reg_status' => new EE_Select_Input(
2324
-                            $registration_stati_for_selection,
2325
-                            array(
2326
-                                'default' => isset($registration_config->default_STS_ID)
2327
-                                             && array_key_exists(
2328
-                                                $registration_config->default_STS_ID,
2329
-                                                $registration_stati_for_selection
2330
-                                             )
2331
-                                            ? sanitize_text_field($registration_config->default_STS_ID)
2332
-                                            : EEM_Registration::status_id_pending_payment,
2333
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
-                                                    . EEH_Template::get_help_tab_link(
2335
-                                                        'default_settings_status_help_tab'
2336
-                                                    ),
2337
-                                'html_help_text' => esc_html__(
2338
-                                    '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.',
2339
-                                    'event_espresso'
2340
-                                )
2341
-                            )
2342
-                        ),
2343
-                        'default_max_tickets' => new EE_Integer_Input(
2344
-                            array(
2345
-                                'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
-                                    ? $registration_config->default_maximum_number_of_tickets
2347
-                                    : EEM_Event::get_default_additional_limit(),
2348
-                                'html_label_text' => esc_html__(
2349
-                                    'Default Maximum Tickets Allowed Per Order:',
2350
-                                    'event_espresso'
2351
-                                ) . EEH_Template::get_help_tab_link(
2352
-                                    'default_maximum_tickets_help_tab"'
2353
-                                    ),
2354
-                                'html_help_text' => esc_html__(
2355
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
-                                    'event_espresso'
2357
-                                )
2358
-                            )
2359
-                        )
2360
-                    )
2361
-                )
2362
-            )
2363
-        );
2364
-    }
2365
-
2366
-
2367
-    /**
2368
-     * _update_default_event_settings
2369
-     *
2370
-     * @access protected
2371
-     * @return void
2372
-     * @throws EE_Error
2373
-     */
2374
-    protected function _update_default_event_settings()
2375
-    {
2376
-        $registration_config = EE_Registry::instance()->CFG->registration;
2377
-        $form = $this->_default_event_settings_form();
2378
-        if ($form->was_submitted()) {
2379
-            $form->receive_form_submission();
2380
-            if ($form->is_valid()) {
2381
-                $valid_data = $form->valid_data();
2382
-                if (isset($valid_data['default_reg_status'])) {
2383
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
-                }
2385
-                if (isset($valid_data['default_max_tickets'])) {
2386
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
-                }
2388
-                //update because data was valid!
2389
-                EE_Registry::instance()->CFG->update_espresso_config();
2390
-                EE_Error::overwrite_success();
2391
-                EE_Error::add_success(
2392
-                    __('Default Event Settings were updated', 'event_espresso')
2393
-                );
2394
-            }
2395
-        }
2396
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
-    }
2398
-
2399
-
2400
-
2401
-    /*************        Templates        *************/
2402
-    protected function _template_settings()
2403
-    {
2404
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
-        $this->_template_args['preview_img'] = '<img src="'
2406
-                                               . EVENTS_ASSETS_URL
2407
-                                               . DS
2408
-                                               . 'images'
2409
-                                               . DS
2410
-                                               . 'caffeinated_template_features.jpg" alt="'
2411
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
-                                               . '" />';
2413
-        $this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
-                '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.',
2415
-                'event_espresso'
2416
-            ) . '</strong>';
2417
-        $this->display_admin_caf_preview_page('template_settings_tab');
2418
-    }
2419
-
2420
-
2421
-    /** Event Category Stuff **/
2422
-    /**
2423
-     * set the _category property with the category object for the loaded page.
2424
-     *
2425
-     * @access private
2426
-     * @return void
2427
-     */
2428
-    private function _set_category_object()
2429
-    {
2430
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
-            return;
2432
-        } //already have the category object so get out.
2433
-        //set default category object
2434
-        $this->_set_empty_category_object();
2435
-        //only set if we've got an id
2436
-        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
-            return;
2438
-        }
2439
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
-        $term = get_term($category_id, 'espresso_event_categories');
2441
-        if ( ! empty($term)) {
2442
-            $this->_category->category_name = $term->name;
2443
-            $this->_category->category_identifier = $term->slug;
2444
-            $this->_category->category_desc = $term->description;
2445
-            $this->_category->id = $term->term_id;
2446
-            $this->_category->parent = $term->parent;
2447
-        }
2448
-    }
2449
-
2450
-
2451
-    /**
2452
-     * Clears out category properties.
2453
-     */
2454
-    private function _set_empty_category_object()
2455
-    {
2456
-        $this->_category = new stdClass();
2457
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
-        $this->_category->id = $this->_category->parent = 0;
2459
-    }
2460
-
2461
-
2462
-    /**
2463
-     * @throws EE_Error
2464
-     */
2465
-    protected function _category_list_table()
2466
-    {
2467
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
-                'add_category',
2471
-                'add_category',
2472
-                array(),
2473
-                'add-new-h2'
2474
-            );
2475
-        $this->display_admin_list_table_page_with_sidebar();
2476
-    }
2477
-
2478
-
2479
-
2480
-    /**
2481
-     * Output category details view.
2482
-     */
2483
-    protected function _category_details($view)
2484
-    {
2485
-        //load formatter helper
2486
-        //load field generator helper
2487
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
-        $this->_set_add_edit_form_tags($route);
2489
-        $this->_set_category_object();
2490
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
-        $delete_action = 'delete_category';
2492
-        //custom redirect
2493
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
-            array('action' => 'category_list'),
2495
-            $this->_admin_base_url
2496
-        );
2497
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
-        //take care of contents
2499
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
-        $this->display_admin_page_with_sidebar();
2501
-    }
2502
-
2503
-
2504
-
2505
-    /**
2506
-     * Output category details content.
2507
-     */
2508
-    protected function _category_details_content()
2509
-    {
2510
-        $editor_args['category_desc'] = array(
2511
-            'type'          => 'wp_editor',
2512
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
-            'class'         => 'my_editor_custom',
2514
-            'wpeditor_args' => array('media_buttons' => false),
2515
-        );
2516
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
-        $all_terms = get_terms(
2518
-            array('espresso_event_categories'),
2519
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
-        );
2521
-        //setup category select for term parents.
2522
-        $category_select_values[] = array(
2523
-            'text' => esc_html__('No Parent', 'event_espresso'),
2524
-            'id'   => 0,
2525
-        );
2526
-        foreach ($all_terms as $term) {
2527
-            $category_select_values[] = array(
2528
-                'text' => $term->name,
2529
-                'id'   => $term->term_id,
2530
-            );
2531
-        }
2532
-        $category_select = EEH_Form_Fields::select_input(
2533
-            'category_parent',
2534
-            $category_select_values,
2535
-            $this->_category->parent
2536
-        );
2537
-        $template_args = array(
2538
-            'category'                 => $this->_category,
2539
-            'category_select'          => $category_select,
2540
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
-            'disable'                  => '',
2543
-            'disabled_message'         => false,
2544
-        );
2545
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
-        return EEH_Template::display_template($template, $template_args, true);
2547
-    }
2548
-
2549
-
2550
-    /**
2551
-     * Handles deleting categories.
2552
-     */
2553
-    protected function _delete_categories()
2554
-    {
2555
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
-            : (array)$this->_req_data['category_id'];
2557
-        foreach ($cat_ids as $cat_id) {
2558
-            $this->_delete_category($cat_id);
2559
-        }
2560
-        //doesn't matter what page we're coming from... we're going to the same place after delete.
2561
-        $query_args = array(
2562
-            'action' => 'category_list',
2563
-        );
2564
-        $this->_redirect_after_action(0, '', '', $query_args);
2565
-    }
2566
-
2567
-
2568
-
2569
-    /**
2570
-     * Handles deleting specific category.
2571
-     * @param int $cat_id
2572
-     */
2573
-    protected function _delete_category($cat_id)
2574
-    {
2575
-        $cat_id = absint($cat_id);
2576
-        wp_delete_term($cat_id, 'espresso_event_categories');
2577
-    }
2578
-
2579
-
2580
-
2581
-    /**
2582
-     * Handles triggering the update or insertion of a new category.
2583
-     * @param bool $new_category  true means we're triggering the insert of a new category.
2584
-     */
2585
-    protected function _insert_or_update_category($new_category)
2586
-    {
2587
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
-        $success = 0; //we already have a success message so lets not send another.
2589
-        if ($cat_id) {
2590
-            $query_args = array(
2591
-                'action'     => 'edit_category',
2592
-                'EVT_CAT_ID' => $cat_id,
2593
-            );
2594
-        } else {
2595
-            $query_args = array('action' => 'add_category');
2596
-        }
2597
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2598
-    }
2599
-
2600
-
2601
-
2602
-    /**
2603
-     * Inserts or updates category
2604
-     * @param bool $update (true indicates we're updating a category).
2605
-     * @return bool|mixed|string
2606
-     */
2607
-    private function _insert_category($update = false)
2608
-    {
2609
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
-        if (empty($category_name)) {
2614
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
-            return false;
2617
-        }
2618
-        $term_args = array(
2619
-            'name'        => $category_name,
2620
-            'description' => $category_desc,
2621
-            'parent'      => $category_parent,
2622
-        );
2623
-        //was the category_identifier input disabled?
2624
-        if (isset($this->_req_data['category_identifier'])) {
2625
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2626
-        }
2627
-        $insert_ids = $update
2628
-            ? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
-            : wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
-        if ( ! is_array($insert_ids)) {
2631
-            $msg = esc_html__(
2632
-                'An error occurred and the category has not been saved to the database.',
2633
-                'event_espresso'
2634
-            );
2635
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
-        } else {
2637
-            $cat_id = $insert_ids['term_id'];
2638
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
-            EE_Error::add_success($msg);
2640
-        }
2641
-        return $cat_id;
2642
-    }
2643
-
2644
-
2645
-
2646
-    /**
2647
-     * Gets categories or count of categories matching the arguments in the request.
2648
-     * @param int  $per_page
2649
-     * @param int  $current_page
2650
-     * @param bool $count
2651
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
-     */
2653
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
-    {
2655
-        //testing term stuff
2656
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
-        $limit = ($current_page - 1) * $per_page;
2659
-        $where = array('taxonomy' => 'espresso_event_categories');
2660
-        if (isset($this->_req_data['s'])) {
2661
-            $sstr = '%' . $this->_req_data['s'] . '%';
2662
-            $where['OR'] = array(
2663
-                'Term.name'   => array('LIKE', $sstr),
2664
-                'description' => array('LIKE', $sstr),
2665
-            );
2666
-        }
2667
-        $query_params = array(
2668
-            $where,
2669
-            'order_by'   => array($orderby => $order),
2670
-            'limit'      => $limit . ',' . $per_page,
2671
-            'force_join' => array('Term'),
2672
-        );
2673
-        $categories = $count
2674
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
-        return $categories;
2677
-    }
2678
-
2679
-    /* end category stuff */
2680
-    /**************/
2681
-
2682
-
2683
-    /**
2684
-     * Callback for the `ee_save_timezone_setting` ajax action.
2685
-     * @throws EE_Error
2686
-     */
2687
-    public function save_timezonestring_setting()
2688
-    {
2689
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2690
-            ? $this->_req_data['timezone_selected']
2691
-            : '';
2692
-        if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
-        {
2694
-            EE_Error::add_error(
2695
-                esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
-                __FILE__, __FUNCTION__, __LINE__
2697
-            );
2698
-            $this->_template_args['error'] = true;
2699
-            $this->_return_json();
2700
-        }
2701
-
2702
-        update_option('timezone_string', $timezone_string);
2703
-        EE_Error::add_success(
2704
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2705
-        );
2706
-        $this->_template_args['success'] = true;
2707
-        $this->_return_json(true, array('action' => 'create_new'));
2708
-    }
394
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
395
+				'require_nonce' => false,
396
+			),
397
+			'default_event_settings' => array(
398
+				'nav'           => array(
399
+					'label' => esc_html__('Default Settings', 'event_espresso'),
400
+					'order' => 40,
401
+				),
402
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
403
+				'labels'        => array(
404
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
405
+				),
406
+				'help_tabs'     => array(
407
+					'default_settings_help_tab'        => array(
408
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
409
+						'filename' => 'events_default_settings',
410
+					),
411
+					'default_settings_status_help_tab' => array(
412
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
413
+						'filename' => 'events_default_settings_status',
414
+					),
415
+					'default_maximum_tickets_help_tab' => array(
416
+						'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
417
+						'filename' => 'events_default_settings_max_tickets',
418
+					)
419
+				),
420
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
421
+				'require_nonce' => false,
422
+			),
423
+			//template settings
424
+			'template_settings'      => array(
425
+				'nav'           => array(
426
+					'label' => esc_html__('Templates', 'event_espresso'),
427
+					'order' => 30,
428
+				),
429
+				'metaboxes'     => $this->_default_espresso_metaboxes,
430
+				'help_tabs'     => array(
431
+					'general_settings_templates_help_tab' => array(
432
+						'title'    => esc_html__('Templates', 'event_espresso'),
433
+						'filename' => 'general_settings_templates',
434
+					),
435
+				),
436
+				'help_tour'     => array('Templates_Help_Tour'),
437
+				'require_nonce' => false,
438
+			),
439
+			//event category stuff
440
+			'add_category'           => array(
441
+				'nav'           => array(
442
+					'label'      => esc_html__('Add Category', 'event_espresso'),
443
+					'order'      => 15,
444
+					'persistent' => false,
445
+				),
446
+				'help_tabs'     => array(
447
+					'add_category_help_tab' => array(
448
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
449
+						'filename' => 'events_add_category',
450
+					),
451
+				),
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
+				'help_tour'     => array(
503
+					'Event_Categories_Help_Tour',
504
+				),
505
+				'metaboxes'     => $this->_default_espresso_metaboxes,
506
+				'require_nonce' => false,
507
+			),
508
+		);
509
+	}
510
+
511
+
512
+	/**
513
+	 * Used to register any global screen options if necessary for every route in this admin page group.
514
+	 */
515
+	protected function _add_screen_options()
516
+	{
517
+	}
518
+
519
+
520
+	/**
521
+	 * Implementing the screen options for the 'default' route.
522
+	 */
523
+	protected function _add_screen_options_default()
524
+	{
525
+		$this->_per_page_screen_option();
526
+	}
527
+
528
+
529
+	/**
530
+	 * Implementing screen options for the category list route.
531
+	 */
532
+	protected function _add_screen_options_category_list()
533
+	{
534
+		$page_title = $this->_admin_page_title;
535
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
536
+		$this->_per_page_screen_option();
537
+		$this->_admin_page_title = $page_title;
538
+	}
539
+
540
+
541
+	/**
542
+	 * Used to register any global feature pointers for the admin page group.
543
+	 */
544
+	protected function _add_feature_pointers()
545
+	{
546
+	}
547
+
548
+
549
+	/**
550
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
551
+	 */
552
+	public function load_scripts_styles()
553
+	{
554
+		wp_register_style(
555
+			'events-admin-css',
556
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
557
+			array(),
558
+			EVENT_ESPRESSO_VERSION
559
+		);
560
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
561
+		wp_enqueue_style('events-admin-css');
562
+		wp_enqueue_style('ee-cat-admin');
563
+		//todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
564
+		//registers for all views
565
+		//scripts
566
+		wp_register_script(
567
+			'event_editor_js',
568
+			EVENTS_ASSETS_URL . 'event_editor.js',
569
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
570
+			EVENT_ESPRESSO_VERSION,
571
+			true
572
+		);
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
+	/**
588
+	 * Enqueuing scripts and styles specific to this view
589
+	 */
590
+	public function load_scripts_styles_edit()
591
+	{
592
+		//styles
593
+		wp_enqueue_style('espresso-ui-theme');
594
+		wp_register_style(
595
+			'event-editor-css',
596
+			EVENTS_ASSETS_URL . 'event-editor.css',
597
+			array('ee-admin-css'),
598
+			EVENT_ESPRESSO_VERSION
599
+		);
600
+		wp_enqueue_style('event-editor-css');
601
+		//scripts
602
+		wp_register_script(
603
+			'event-datetime-metabox',
604
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
605
+			array('event_editor_js', 'ee-datepicker'),
606
+			EVENT_ESPRESSO_VERSION
607
+		);
608
+		wp_enqueue_script('event-datetime-metabox');
609
+	}
610
+
611
+
612
+	/**
613
+	 * Populating the _views property for the category list table view.
614
+	 */
615
+	protected function _set_list_table_views_category_list()
616
+	{
617
+		$this->_views = array(
618
+			'all' => array(
619
+				'slug'        => 'all',
620
+				'label'       => esc_html__('All', 'event_espresso'),
621
+				'count'       => 0,
622
+				'bulk_action' => array(
623
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
624
+				),
625
+			),
626
+		);
627
+	}
628
+
629
+
630
+	/**
631
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
632
+	 */
633
+	public function admin_init()
634
+	{
635
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
636
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
637
+			'event_espresso'
638
+		);
639
+	}
640
+
641
+
642
+	/**
643
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page 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
+	/**
661
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
662
+	 * warning (via EE_Error::add_error());
663
+	 *
664
+	 * @param  EE_Event $event Event object
665
+	 * @param string    $req_type
666
+	 * @return void
667
+	 * @throws EE_Error
668
+	 * @access public
669
+	 */
670
+	public function verify_event_edit($event = null, $req_type = '')
671
+	{
672
+		// don't need to do this when processing
673
+		if(!empty($req_type)) {
674
+			return;
675
+		}
676
+		// no event?
677
+		if (empty($event)) {
678
+			// set event
679
+			$event = $this->_cpt_model_obj;
680
+		}
681
+		// STILL no event?
682
+		if (! $event instanceof EE_Event) {
683
+			return;
684
+		}
685
+		$orig_status = $event->status();
686
+		// first check if event is active.
687
+		if (
688
+			$orig_status === EEM_Event::cancelled
689
+			|| $orig_status === EEM_Event::postponed
690
+			|| $event->is_expired()
691
+			|| $event->is_inactive()
692
+		) {
693
+			return;
694
+		}
695
+		//made it here so it IS active... next check that any of the tickets are sold.
696
+		if ($event->is_sold_out(true)) {
697
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
698
+				EE_Error::add_attention(
699
+					sprintf(
700
+						esc_html__(
701
+							'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.',
702
+							'event_espresso'
703
+						),
704
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
705
+					)
706
+				);
707
+			}
708
+			return;
709
+		} else if ($orig_status === EEM_Event::sold_out) {
710
+			EE_Error::add_attention(
711
+				sprintf(
712
+					esc_html__(
713
+						'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.',
714
+						'event_espresso'
715
+					),
716
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
717
+				)
718
+			);
719
+		}
720
+		//now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
721
+		if ( ! $event->tickets_on_sale()) {
722
+			return;
723
+		}
724
+		//made it here so show warning
725
+		$this->_edit_event_warning();
726
+	}
727
+
728
+
729
+
730
+	/**
731
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
732
+	 * When needed, hook this into a EE_Error::add_error() notice.
733
+	 *
734
+	 * @access protected
735
+	 * @return void
736
+	 */
737
+	protected function _edit_event_warning()
738
+	{
739
+		// we don't want to add warnings during these requests
740
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
741
+			return;
742
+		}
743
+		EE_Error::add_attention(
744
+			esc_html__(
745
+				'Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.',
746
+				'event_espresso'
747
+			)
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
+	/**
826
+	 * Provides the legend item array for the default list table view.
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
+	/**
883
+	 * @return EEM_Event
884
+	 */
885
+	private function _event_model()
886
+	{
887
+		if ( ! $this->_event_model instanceof EEM_Event) {
888
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
889
+		}
890
+		return $this->_event_model;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * Adds extra buttons to the WP CPT permalink field row.
897
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
898
+	 *
899
+	 * @param  string $return    the current html
900
+	 * @param  int    $id        the post id for the page
901
+	 * @param  string $new_title What the title is
902
+	 * @param  string $new_slug  what the slug is
903
+	 * @return string            The new html string for the permalink area
904
+	 */
905
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
906
+	{
907
+		//make sure this is only when editing
908
+		if ( ! empty($id)) {
909
+			$post = get_post($id);
910
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
911
+					   . esc_html__('Shortcode', 'event_espresso')
912
+					   . '</a> ';
913
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
914
+					   . $post->ID
915
+					   . ']">';
916
+		}
917
+		return $return;
918
+	}
919
+
920
+
921
+
922
+	/**
923
+	 * _events_overview_list_table
924
+	 * This contains the logic for showing the events_overview list
925
+	 *
926
+	 * @access protected
927
+	 * @return void
928
+	 * @throws \EE_Error
929
+	 */
930
+	protected function _events_overview_list_table()
931
+	{
932
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
933
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
934
+			? (array)$this->_template_args['after_list_table']
935
+			: array();
936
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
937
+																			  . EEH_Template::get_button_or_link(
938
+				get_post_type_archive_link('espresso_events'),
939
+				esc_html__("View Event Archive Page", "event_espresso"),
940
+				'button'
941
+			);
942
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
943
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
944
+				'create_new',
945
+				'add',
946
+				array(),
947
+				'add-new-h2'
948
+			);
949
+		$this->display_admin_list_table_page_with_no_sidebar();
950
+	}
951
+
952
+
953
+
954
+	/**
955
+	 * this allows for extra misc actions in the default WP publish box
956
+	 *
957
+	 * @return void
958
+	 */
959
+	public function extra_misc_actions_publish_box()
960
+	{
961
+		$this->_generate_publish_box_extra_content();
962
+	}
963
+
964
+
965
+
966
+	/**
967
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been saved.
968
+	 * Typically you would use this to save any additional data.
969
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
970
+	 * ALSO very important.  When a post transitions from scheduled to published,
971
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from other meta saves.
972
+	 * So MAKE sure that you handle this accordingly.
973
+	 *
974
+	 * @access protected
975
+	 * @abstract
976
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
977
+	 * @param  object $post    The post object of the cpt that was saved.
978
+	 * @return void
979
+	 * @throws \EE_Error
980
+	 */
981
+	protected function _insert_update_cpt_item($post_id, $post)
982
+	{
983
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
984
+			//get out we're not processing an event save.
985
+			return;
986
+		}
987
+		$event_values = array(
988
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
989
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
990
+			'EVT_additional_limit'            => min(
991
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
992
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
993
+			),
994
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
995
+				? $this->_req_data['EVT_default_registration_status']
996
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
997
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
998
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
999
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1000
+				? $this->_req_data['timezone_string'] : null,
1001
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1002
+				? $this->_req_data['externalURL'] : null,
1003
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1004
+				? $this->_req_data['event_phone'] : null,
1005
+		);
1006
+		//update event
1007
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1008
+		//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!
1009
+		$get_one_where = array(
1010
+			$this->_event_model()->primary_key_name() => $post_id,
1011
+			'OR' => array(
1012
+				'status' => $post->post_status,
1013
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1014
+				// but the returned object here has a status of "publish", so use the original post status as well
1015
+				'status*1' => $this->_req_data['original_post_status'],
1016
+			)
1017
+		);
1018
+		$event = $this->_event_model()->get_one(array($get_one_where));
1019
+		//the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1020
+		$event_update_callbacks = apply_filters(
1021
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1022
+			array(
1023
+				array($this, '_default_venue_update'),
1024
+				array($this, '_default_tickets_update')
1025
+			)
1026
+		);
1027
+		$att_success = true;
1028
+		foreach ($event_update_callbacks as $e_callback) {
1029
+			$_success = is_callable($e_callback)
1030
+				? call_user_func($e_callback, $event, $this->_req_data)
1031
+				: false;
1032
+			//if ANY of these updates fail then we want the appropriate global error message
1033
+			$att_success = ! $att_success ? $att_success : $_success;
1034
+		}
1035
+		//any errors?
1036
+		if ($success && false === $att_success) {
1037
+			EE_Error::add_error(
1038
+				esc_html__(
1039
+					'Event Details saved successfully but something went wrong with saving attachments.',
1040
+					'event_espresso'
1041
+				),
1042
+				__FILE__,
1043
+				__FUNCTION__,
1044
+				__LINE__
1045
+			);
1046
+		} else if ($success === false) {
1047
+			EE_Error::add_error(
1048
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1049
+				__FILE__,
1050
+				__FUNCTION__,
1051
+				__LINE__
1052
+			);
1053
+		}
1054
+	}
1055
+
1056
+
1057
+
1058
+	/**
1059
+	 * @see parent::restore_item()
1060
+	 * @param int $post_id
1061
+	 * @param int $revision_id
1062
+	 */
1063
+	protected function _restore_cpt_item($post_id, $revision_id)
1064
+	{
1065
+		//copy existing event meta to new post
1066
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1067
+		if ($post_evt instanceof EE_Event) {
1068
+			//meta revision restore
1069
+			$post_evt->restore_revision($revision_id);
1070
+			//related objs restore
1071
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1072
+		}
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * Attach the venue to the Event
1079
+	 *
1080
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1081
+	 * @param  array     $data   The request data from the form
1082
+	 * @return bool           Success or fail.
1083
+	 */
1084
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1085
+	{
1086
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1087
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1088
+		$rows_affected = null;
1089
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1090
+		// very important.  If we don't have a venue name...
1091
+		// then we'll get out because not necessary to create empty venue
1092
+		if (empty($data['venue_title'])) {
1093
+			return false;
1094
+		}
1095
+		$venue_array = array(
1096
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1097
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1098
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1099
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1100
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1101
+				: null,
1102
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1103
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1104
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1105
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1106
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1107
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1108
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1109
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1110
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1111
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1112
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1113
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1114
+			'status'              => 'publish',
1115
+		);
1116
+		//if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1117
+		if ( ! empty($venue_id)) {
1118
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1119
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1120
+			//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.
1121
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1122
+			return $rows_affected > 0 ? true : false;
1123
+		} else {
1124
+			//we insert the venue
1125
+			$venue_id = $venue_model->insert($venue_array);
1126
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1127
+			return ! empty($venue_id) ? true : false;
1128
+		}
1129
+		//when we have the ancestor come in it's already been handled by the revision save.
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1136
+	 *
1137
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1138
+	 * @param  array    $data   The request data from the form
1139
+	 * @return array
1140
+	 */
1141
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1142
+	{
1143
+		$success = true;
1144
+		$saved_dtt = null;
1145
+		$saved_tickets = array();
1146
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1147
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1148
+			//trim all values to ensure any excess whitespace is removed.
1149
+			$dtt = array_map('trim', $dtt);
1150
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1151
+				: $dtt['DTT_EVT_start'];
1152
+			$datetime_values = array(
1153
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1154
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1155
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1156
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1157
+				'DTT_order'     => $row,
1158
+			);
1159
+			//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.
1160
+			if ( ! empty($dtt['DTT_ID'])) {
1161
+				$DTM = EE_Registry::instance()
1162
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1163
+								  ->get_one_by_ID($dtt['DTT_ID']);
1164
+				$DTM->set_date_format($incoming_date_formats[0]);
1165
+				$DTM->set_time_format($incoming_date_formats[1]);
1166
+				foreach ($datetime_values as $field => $value) {
1167
+					$DTM->set($field, $value);
1168
+				}
1169
+				//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.
1170
+				$saved_dtts[$DTM->ID()] = $DTM;
1171
+			} else {
1172
+				$DTM = EE_Registry::instance()->load_class(
1173
+					'Datetime',
1174
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1175
+					false,
1176
+					false
1177
+				);
1178
+				foreach ($datetime_values as $field => $value) {
1179
+					$DTM->set($field, $value);
1180
+				}
1181
+			}
1182
+			$DTM->save();
1183
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1184
+			//load DTT helper
1185
+			//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.
1186
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1187
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1188
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1189
+				$DTT->save();
1190
+			}
1191
+			//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.
1192
+			$saved_dtt = $DTT;
1193
+			$success = ! $success ? $success : $DTT;
1194
+			//if ANY of these updates fail then we want the appropriate global error message.
1195
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1196
+		}
1197
+		//no dtts get deleted so we don't do any of that logic here.
1198
+		//update tickets next
1199
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1200
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1201
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1202
+			$update_prices = false;
1203
+			$ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1204
+				? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1205
+			// trim inputs to ensure any excess whitespace is removed.
1206
+			$tkt = array_map('trim', $tkt);
1207
+			if (empty($tkt['TKT_start_date'])) {
1208
+				//let's use now in the set timezone.
1209
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1210
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1211
+			}
1212
+			if (empty($tkt['TKT_end_date'])) {
1213
+				//use the start date of the first datetime
1214
+				$dtt = $evtobj->first_datetime();
1215
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1216
+					$incoming_date_formats[0],
1217
+					$incoming_date_formats[1]
1218
+				);
1219
+			}
1220
+			$TKT_values = array(
1221
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1222
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1223
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1224
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1225
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1226
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1227
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1228
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1229
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1230
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1231
+				'TKT_row'         => $row,
1232
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1233
+				'TKT_price'       => $ticket_price,
1234
+			);
1235
+			//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.
1236
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1237
+				$TKT_values['TKT_ID'] = 0;
1238
+				$TKT_values['TKT_is_default'] = 0;
1239
+				$TKT_values['TKT_price'] = $ticket_price;
1240
+				$update_prices = true;
1241
+			}
1242
+			//if we have a TKT_ID then we need to get that existing TKT_obj and update it
1243
+			//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.
1244
+			//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.
1245
+			if ( ! empty($tkt['TKT_ID'])) {
1246
+				$TKT = EE_Registry::instance()
1247
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1248
+								  ->get_one_by_ID($tkt['TKT_ID']);
1249
+				if ($TKT instanceof EE_Ticket) {
1250
+					$ticket_sold = $TKT->count_related(
1251
+						'Registration',
1252
+						array(
1253
+							array(
1254
+								'STS_ID' => array(
1255
+									'NOT IN',
1256
+									array(EEM_Registration::status_id_incomplete),
1257
+								),
1258
+							),
1259
+						)
1260
+					) > 0 ? true : false;
1261
+					//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.
1262
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1263
+									  && ! $TKT->get(
1264
+						'TKT_deleted'
1265
+					) ? true : false;
1266
+					$TKT->set_date_format($incoming_date_formats[0]);
1267
+					$TKT->set_time_format($incoming_date_formats[1]);
1268
+					//set new values
1269
+					foreach ($TKT_values as $field => $value) {
1270
+						if ($field == 'TKT_qty') {
1271
+							$TKT->set_qty($value);
1272
+						} else {
1273
+							$TKT->set($field, $value);
1274
+						}
1275
+					}
1276
+					//if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1277
+					if ($create_new_TKT) {
1278
+						//archive the old ticket first
1279
+						$TKT->set('TKT_deleted', 1);
1280
+						$TKT->save();
1281
+						//make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1282
+						$saved_tickets[$TKT->ID()] = $TKT;
1283
+						//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.
1284
+						$TKT = clone $TKT;
1285
+						$TKT->set('TKT_ID', 0);
1286
+						$TKT->set('TKT_deleted', 0);
1287
+						$TKT->set('TKT_price', $ticket_price);
1288
+						$TKT->set('TKT_sold', 0);
1289
+						//now we need to make sure that $new prices are created as well and attached to new ticket.
1290
+						$update_prices = true;
1291
+					}
1292
+					//make sure price is set if it hasn't been already
1293
+					$TKT->set('TKT_price', $ticket_price);
1294
+				}
1295
+			} else {
1296
+				//no TKT_id so a new TKT
1297
+				$TKT_values['TKT_price'] = $ticket_price;
1298
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1299
+				if ($TKT instanceof EE_Ticket) {
1300
+					//need to reset values to properly account for the date formats
1301
+					$TKT->set_date_format($incoming_date_formats[0]);
1302
+					$TKT->set_time_format($incoming_date_formats[1]);
1303
+					$TKT->set_timezone($evtobj->get_timezone());
1304
+					//set new values
1305
+					foreach ($TKT_values as $field => $value) {
1306
+						if ($field == 'TKT_qty') {
1307
+							$TKT->set_qty($value);
1308
+						} else {
1309
+							$TKT->set($field, $value);
1310
+						}
1311
+					}
1312
+					$update_prices = true;
1313
+				}
1314
+			}
1315
+			// cap ticket qty by datetime reg limits
1316
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1317
+			//update ticket.
1318
+			$TKT->save();
1319
+			//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.
1320
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1321
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1322
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1323
+				$TKT->save();
1324
+			}
1325
+			//initially let's add the ticket to the dtt
1326
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1327
+			$saved_tickets[$TKT->ID()] = $TKT;
1328
+			//add prices to ticket
1329
+			$this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1330
+		}
1331
+		//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.
1332
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1333
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1334
+		foreach ($tickets_removed as $id) {
1335
+			$id = absint($id);
1336
+			//get the ticket for this id
1337
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1338
+			//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)
1339
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1340
+			foreach ($dtts as $dtt) {
1341
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1342
+			}
1343
+			//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))
1344
+			$tkt_to_remove->delete_related_permanently('Price');
1345
+			//finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1346
+			$tkt_to_remove->delete_permanently();
1347
+		}
1348
+		return array($saved_dtt, $saved_tickets);
1349
+	}
1350
+
1351
+
1352
+
1353
+	/**
1354
+	 * This attaches a list of given prices to a ticket.
1355
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1356
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1357
+	 * price info and prices are automatically "archived" via the ticket.
1358
+	 *
1359
+	 * @access  private
1360
+	 * @param array     $prices     Array of prices from the form.
1361
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1362
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1363
+	 * @return  void
1364
+	 */
1365
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1366
+	{
1367
+		foreach ($prices as $row => $prc) {
1368
+			$PRC_values = array(
1369
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1370
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1371
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1372
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1373
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1374
+				'PRC_is_default' => 0, //make sure prices are NOT set as default from this context
1375
+				'PRC_order'      => $row,
1376
+			);
1377
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1378
+				$PRC_values['PRC_ID'] = 0;
1379
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1380
+			} else {
1381
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1382
+				//update this price with new values
1383
+				foreach ($PRC_values as $field => $newprc) {
1384
+					$PRC->set($field, $newprc);
1385
+				}
1386
+				$PRC->save();
1387
+			}
1388
+			$ticket->_add_relation_to($PRC, 'Price');
1389
+		}
1390
+	}
1391
+
1392
+
1393
+
1394
+	/**
1395
+	 * Add in our autosave ajax handlers
1396
+	 *
1397
+	 */
1398
+	protected function _ee_autosave_create_new()
1399
+	{
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * More autosave handlers.
1405
+	 */
1406
+	protected function _ee_autosave_edit()
1407
+	{
1408
+		return; //TEMPORARILY EXITING CAUSE THIS IS A TODO
1409
+	}
1410
+
1411
+
1412
+
1413
+	/**
1414
+	 *    _generate_publish_box_extra_content
1415
+	 */
1416
+	private function _generate_publish_box_extra_content()
1417
+	{
1418
+		//load formatter helper
1419
+		//args for getting related registrations
1420
+		$approved_query_args = array(
1421
+			array(
1422
+				'REG_deleted' => 0,
1423
+				'STS_ID'      => EEM_Registration::status_id_approved,
1424
+			),
1425
+		);
1426
+		$not_approved_query_args = array(
1427
+			array(
1428
+				'REG_deleted' => 0,
1429
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1430
+			),
1431
+		);
1432
+		$pending_payment_query_args = array(
1433
+			array(
1434
+				'REG_deleted' => 0,
1435
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1436
+			),
1437
+		);
1438
+		// publish box
1439
+		$publish_box_extra_args = array(
1440
+			'view_approved_reg_url'        => add_query_arg(
1441
+				array(
1442
+					'action'      => 'default',
1443
+					'event_id'    => $this->_cpt_model_obj->ID(),
1444
+					'_reg_status' => EEM_Registration::status_id_approved,
1445
+				),
1446
+				REG_ADMIN_URL
1447
+			),
1448
+			'view_not_approved_reg_url'    => add_query_arg(
1449
+				array(
1450
+					'action'      => 'default',
1451
+					'event_id'    => $this->_cpt_model_obj->ID(),
1452
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1453
+				),
1454
+				REG_ADMIN_URL
1455
+			),
1456
+			'view_pending_payment_reg_url' => add_query_arg(
1457
+				array(
1458
+					'action'      => 'default',
1459
+					'event_id'    => $this->_cpt_model_obj->ID(),
1460
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1461
+				),
1462
+				REG_ADMIN_URL
1463
+			),
1464
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1465
+				'Registration',
1466
+				$approved_query_args
1467
+			),
1468
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1469
+				'Registration',
1470
+				$not_approved_query_args
1471
+			),
1472
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1473
+				'Registration',
1474
+				$pending_payment_query_args
1475
+			),
1476
+			'misc_pub_section_class'       => apply_filters(
1477
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1478
+				'misc-pub-section'
1479
+			),
1480
+		);
1481
+		ob_start();
1482
+		do_action(
1483
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1484
+			$this->_cpt_model_obj
1485
+		);
1486
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1487
+		// load template
1488
+		EEH_Template::display_template(
1489
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1490
+			$publish_box_extra_args
1491
+		);
1492
+	}
1493
+
1494
+
1495
+
1496
+	/**
1497
+	 * @return EE_Event
1498
+	 */
1499
+	public function get_event_object()
1500
+	{
1501
+		return $this->_cpt_model_obj;
1502
+	}
1503
+
1504
+
1505
+
1506
+
1507
+	/** METABOXES * */
1508
+	/**
1509
+	 * _register_event_editor_meta_boxes
1510
+	 * add all metaboxes related to the event_editor
1511
+	 *
1512
+	 * @return void
1513
+	 */
1514
+	protected function _register_event_editor_meta_boxes()
1515
+	{
1516
+		$this->verify_cpt_object();
1517
+		add_meta_box(
1518
+			'espresso_event_editor_tickets',
1519
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1520
+			array($this, 'ticket_metabox'),
1521
+			$this->page_slug,
1522
+			'normal',
1523
+			'high'
1524
+		);
1525
+		add_meta_box(
1526
+			'espresso_event_editor_event_options',
1527
+			esc_html__('Event Registration Options', 'event_espresso'),
1528
+			array($this, 'registration_options_meta_box'),
1529
+			$this->page_slug,
1530
+			'side',
1531
+			'default'
1532
+		);
1533
+		// NOTE: if you're looking for other metaboxes in here,
1534
+		// where a metabox has a related management page in the admin
1535
+		// you will find it setup in the related management page's "_Hooks" file.
1536
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1537
+	}
1538
+
1539
+
1540
+	/**
1541
+	 * @throws DomainException
1542
+	 * @throws EE_Error
1543
+	 */
1544
+	public function ticket_metabox()
1545
+	{
1546
+		$existing_datetime_ids = $existing_ticket_ids = array();
1547
+		//defaults for template args
1548
+		$template_args = array(
1549
+			'existing_datetime_ids'    => '',
1550
+			'event_datetime_help_link' => '',
1551
+			'ticket_options_help_link' => '',
1552
+			'time'                     => null,
1553
+			'ticket_rows'              => '',
1554
+			'existing_ticket_ids'      => '',
1555
+			'total_ticket_rows'        => 1,
1556
+			'ticket_js_structure'      => '',
1557
+			'trash_icon'               => 'ee-lock-icon',
1558
+			'disabled'                 => '',
1559
+		);
1560
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1561
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1562
+		/**
1563
+		 * 1. Start with retrieving Datetimes
1564
+		 * 2. Fore each datetime get related tickets
1565
+		 * 3. For each ticket get related prices
1566
+		 */
1567
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1568
+		/** @type EE_Datetime $first_datetime */
1569
+		$first_datetime = reset($times);
1570
+		//do we get related tickets?
1571
+		if ($first_datetime instanceof EE_Datetime
1572
+			&& $first_datetime->ID() !== 0
1573
+		) {
1574
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1575
+			$template_args['time'] = $first_datetime;
1576
+			$related_tickets = $first_datetime->tickets(
1577
+				array(
1578
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1579
+					'default_where_conditions' => 'none',
1580
+				)
1581
+			);
1582
+			if ( ! empty($related_tickets)) {
1583
+				$template_args['total_ticket_rows'] = count($related_tickets);
1584
+				$row = 0;
1585
+				foreach ($related_tickets as $ticket) {
1586
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1587
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1588
+					$row++;
1589
+				}
1590
+			} else {
1591
+				$template_args['total_ticket_rows'] = 1;
1592
+				/** @type EE_Ticket $ticket */
1593
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1594
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1595
+			}
1596
+		} else {
1597
+			$template_args['time'] = $times[0];
1598
+			/** @type EE_Ticket $ticket */
1599
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1600
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1601
+			// NOTE: we're just sending the first default row
1602
+			// (decaf can't manage default tickets so this should be sufficient);
1603
+		}
1604
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1605
+			'event_editor_event_datetimes_help_tab'
1606
+		);
1607
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1608
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1609
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1610
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1611
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1612
+			true
1613
+		);
1614
+		$template = apply_filters(
1615
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1616
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1617
+		);
1618
+		EEH_Template::display_template($template, $template_args);
1619
+	}
1620
+
1621
+
1622
+
1623
+	/**
1624
+	 * Setup an individual ticket form for the decaf event editor page
1625
+	 *
1626
+	 * @access private
1627
+	 * @param  EE_Ticket $ticket   the ticket object
1628
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1629
+	 * @param int        $row
1630
+	 * @return string generated html for the ticket row.
1631
+	 */
1632
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1633
+	{
1634
+		$template_args = array(
1635
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1636
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1637
+				: '',
1638
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1639
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1640
+			'TKT_name'            => $ticket->get('TKT_name'),
1641
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1642
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1643
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1644
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1645
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1646
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1647
+			'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1648
+									 && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1649
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1650
+			'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1651
+				: ' disabled=disabled',
1652
+		);
1653
+		$price = $ticket->ID() !== 0
1654
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1655
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1656
+		$price_args = array(
1657
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1658
+			'PRC_amount'            => $price->get('PRC_amount'),
1659
+			'PRT_ID'                => $price->get('PRT_ID'),
1660
+			'PRC_ID'                => $price->get('PRC_ID'),
1661
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1662
+		);
1663
+		//make sure we have default start and end dates if skeleton
1664
+		//handle rows that should NOT be empty
1665
+		if (empty($template_args['TKT_start_date'])) {
1666
+			//if empty then the start date will be now.
1667
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1668
+		}
1669
+		if (empty($template_args['TKT_end_date'])) {
1670
+			//get the earliest datetime (if present);
1671
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1672
+				? $this->_cpt_model_obj->get_first_related(
1673
+					'Datetime',
1674
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1675
+				)
1676
+				: null;
1677
+			if ( ! empty($earliest_dtt)) {
1678
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1679
+			} else {
1680
+				$template_args['TKT_end_date'] = date(
1681
+					'Y-m-d h:i a',
1682
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1683
+				);
1684
+			}
1685
+		}
1686
+		$template_args = array_merge($template_args, $price_args);
1687
+		$template = apply_filters(
1688
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1689
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1690
+			$ticket
1691
+		);
1692
+		return EEH_Template::display_template($template, $template_args, true);
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @throws DomainException
1698
+	 */
1699
+	public function registration_options_meta_box()
1700
+	{
1701
+		$yes_no_values = array(
1702
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1703
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1704
+		);
1705
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1706
+			array(
1707
+				EEM_Registration::status_id_cancelled,
1708
+				EEM_Registration::status_id_declined,
1709
+				EEM_Registration::status_id_incomplete,
1710
+			),
1711
+			true
1712
+		);
1713
+		//$template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1714
+		$template_args['_event'] = $this->_cpt_model_obj;
1715
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1716
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1717
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1718
+			'default_reg_status',
1719
+			$default_reg_status_values,
1720
+			$this->_cpt_model_obj->default_registration_status()
1721
+		);
1722
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1723
+			'display_desc',
1724
+			$yes_no_values,
1725
+			$this->_cpt_model_obj->display_description()
1726
+		);
1727
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1728
+			'display_ticket_selector',
1729
+			$yes_no_values,
1730
+			$this->_cpt_model_obj->display_ticket_selector(),
1731
+			'',
1732
+			'',
1733
+			false
1734
+		);
1735
+		$template_args['additional_registration_options'] = apply_filters(
1736
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1737
+			'',
1738
+			$template_args,
1739
+			$yes_no_values,
1740
+			$default_reg_status_values
1741
+		);
1742
+		EEH_Template::display_template(
1743
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1744
+			$template_args
1745
+		);
1746
+	}
1747
+
1748
+
1749
+
1750
+	/**
1751
+	 * _get_events()
1752
+	 * This method simply returns all the events (for the given _view and paging)
1753
+	 *
1754
+	 * @access public
1755
+	 * @param int  $per_page     count of items per page (20 default);
1756
+	 * @param int  $current_page what is the current page being viewed.
1757
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1758
+	 *                           If FALSE then we return an array of event objects
1759
+	 *                           that match the given _view and paging parameters.
1760
+	 * @return array an array of event objects.
1761
+	 */
1762
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1763
+	{
1764
+		$EEME = $this->_event_model();
1765
+		$offset = ($current_page - 1) * $per_page;
1766
+		$limit = $count ? null : $offset . ',' . $per_page;
1767
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1768
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1769
+		if (isset($this->_req_data['month_range'])) {
1770
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1771
+			//simulate the FIRST day of the month, that fixes issues for months like February
1772
+			//where PHP doesn't know what to assume for date.
1773
+			//@see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1774
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1775
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1776
+		}
1777
+		$where = array();
1778
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1779
+		//determine what post_status our condition will have for the query.
1780
+		switch ($status) {
1781
+			case 'month' :
1782
+			case 'today' :
1783
+			case null :
1784
+			case 'all' :
1785
+				break;
1786
+			case 'draft' :
1787
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1788
+				break;
1789
+			default :
1790
+				$where['status'] = $status;
1791
+		}
1792
+		//categories?
1793
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1794
+			? $this->_req_data['EVT_CAT'] : null;
1795
+		if ( ! empty ($category)) {
1796
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1797
+			$where['Term_Taxonomy.term_id'] = $category;
1798
+		}
1799
+		//date where conditions
1800
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1801
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1802
+			$DateTime = new DateTime(
1803
+				$year_r . '-' . $month_r . '-01 00:00:00',
1804
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1805
+			);
1806
+			$start = $DateTime->format(implode(' ', $start_formats));
1807
+			$end = $DateTime->setDate($year_r, $month_r, $DateTime
1808
+				->format('t'))->setTime(23, 59, 59)
1809
+							->format(implode(' ', $start_formats));
1810
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1811
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1812
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1813
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1814
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1815
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1816
+		} else if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1817
+			$now = date('Y-m-01');
1818
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1819
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1820
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1821
+							->setTime(23, 59, 59)
1822
+							->format(implode(' ', $start_formats));
1823
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1824
+		}
1825
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1826
+			$where['EVT_wp_user'] = get_current_user_id();
1827
+		} else {
1828
+			if ( ! isset($where['status'])) {
1829
+				if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1830
+					$where['OR'] = array(
1831
+						'status*restrict_private' => array('!=', 'private'),
1832
+						'AND'                     => array(
1833
+							'status*inclusive' => array('=', 'private'),
1834
+							'EVT_wp_user'      => get_current_user_id(),
1835
+						),
1836
+					);
1837
+				}
1838
+			}
1839
+		}
1840
+		if (isset($this->_req_data['EVT_wp_user'])) {
1841
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1842
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1843
+			) {
1844
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1845
+			}
1846
+		}
1847
+		//search query handling
1848
+		if (isset($this->_req_data['s'])) {
1849
+			$search_string = '%' . $this->_req_data['s'] . '%';
1850
+			$where['OR'] = array(
1851
+				'EVT_name'       => array('LIKE', $search_string),
1852
+				'EVT_desc'       => array('LIKE', $search_string),
1853
+				'EVT_short_desc' => array('LIKE', $search_string),
1854
+			);
1855
+		}
1856
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1857
+		$query_params = apply_filters(
1858
+			'FHEE__Events_Admin_Page__get_events__query_params',
1859
+			array(
1860
+				$where,
1861
+				'limit'    => $limit,
1862
+				'order_by' => $orderby,
1863
+				'order'    => $order,
1864
+				'group_by' => 'EVT_ID',
1865
+			),
1866
+			$this->_req_data
1867
+		);
1868
+		//let's first check if we have special requests coming in.
1869
+		if (isset($this->_req_data['active_status'])) {
1870
+			switch ($this->_req_data['active_status']) {
1871
+				case 'upcoming' :
1872
+					return $EEME->get_upcoming_events($query_params, $count);
1873
+					break;
1874
+				case 'expired' :
1875
+					return $EEME->get_expired_events($query_params, $count);
1876
+					break;
1877
+				case 'active' :
1878
+					return $EEME->get_active_events($query_params, $count);
1879
+					break;
1880
+				case 'inactive' :
1881
+					return $EEME->get_inactive_events($query_params, $count);
1882
+					break;
1883
+			}
1884
+		}
1885
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1886
+		return $events;
1887
+	}
1888
+
1889
+
1890
+
1891
+	/**
1892
+	 * handling for WordPress CPT actions (trash, restore, delete)
1893
+	 *
1894
+	 * @param string $post_id
1895
+	 */
1896
+	public function trash_cpt_item($post_id)
1897
+	{
1898
+		$this->_req_data['EVT_ID'] = $post_id;
1899
+		$this->_trash_or_restore_event('trash', false);
1900
+	}
1901
+
1902
+
1903
+
1904
+	/**
1905
+	 * @param string $post_id
1906
+	 */
1907
+	public function restore_cpt_item($post_id)
1908
+	{
1909
+		$this->_req_data['EVT_ID'] = $post_id;
1910
+		$this->_trash_or_restore_event('draft', false);
1911
+	}
1912
+
1913
+
1914
+
1915
+	/**
1916
+	 * @param string $post_id
1917
+	 */
1918
+	public function delete_cpt_item($post_id)
1919
+	{
1920
+		$this->_req_data['EVT_ID'] = $post_id;
1921
+		$this->_delete_event(false);
1922
+	}
1923
+
1924
+
1925
+
1926
+	/**
1927
+	 * _trash_or_restore_event
1928
+	 *
1929
+	 * @access protected
1930
+	 * @param  string $event_status
1931
+	 * @param bool    $redirect_after
1932
+	 */
1933
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1934
+	{
1935
+		//determine the event id and set to array.
1936
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1937
+		// loop thru events
1938
+		if ($EVT_ID) {
1939
+			// clean status
1940
+			$event_status = sanitize_key($event_status);
1941
+			// grab status
1942
+			if ( ! empty($event_status)) {
1943
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1944
+			} else {
1945
+				$success = false;
1946
+				$msg = esc_html__(
1947
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1948
+					'event_espresso'
1949
+				);
1950
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1951
+			}
1952
+		} else {
1953
+			$success = false;
1954
+			$msg = esc_html__(
1955
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1956
+				'event_espresso'
1957
+			);
1958
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1959
+		}
1960
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1961
+		if ($redirect_after) {
1962
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1963
+		}
1964
+	}
1965
+
1966
+
1967
+
1968
+	/**
1969
+	 * _trash_or_restore_events
1970
+	 *
1971
+	 * @access protected
1972
+	 * @param  string $event_status
1973
+	 * @return void
1974
+	 */
1975
+	protected function _trash_or_restore_events($event_status = 'trash')
1976
+	{
1977
+		// clean status
1978
+		$event_status = sanitize_key($event_status);
1979
+		// grab status
1980
+		if ( ! empty($event_status)) {
1981
+			$success = true;
1982
+			//determine the event id and set to array.
1983
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
1984
+			// loop thru events
1985
+			foreach ($EVT_IDs as $EVT_ID) {
1986
+				if ($EVT_ID = absint($EVT_ID)) {
1987
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1988
+					$success = $results !== false ? $success : false;
1989
+				} else {
1990
+					$msg = sprintf(
1991
+						esc_html__(
1992
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1993
+							'event_espresso'
1994
+						),
1995
+						$EVT_ID
1996
+					);
1997
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1998
+					$success = false;
1999
+				}
2000
+			}
2001
+		} else {
2002
+			$success = false;
2003
+			$msg = esc_html__(
2004
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2005
+				'event_espresso'
2006
+			);
2007
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2008
+		}
2009
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2010
+		$success = $success ? 2 : false;
2011
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2012
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2013
+	}
2014
+
2015
+
2016
+
2017
+	/**
2018
+	 * _trash_or_restore_events
2019
+	 *
2020
+	 * @access  private
2021
+	 * @param  int    $EVT_ID
2022
+	 * @param  string $event_status
2023
+	 * @return bool
2024
+	 */
2025
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2026
+	{
2027
+		// grab event id
2028
+		if ( ! $EVT_ID) {
2029
+			$msg = esc_html__(
2030
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2031
+				'event_espresso'
2032
+			);
2033
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2034
+			return false;
2035
+		}
2036
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2037
+		// clean status
2038
+		$event_status = sanitize_key($event_status);
2039
+		// grab status
2040
+		if (empty($event_status)) {
2041
+			$msg = esc_html__(
2042
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2043
+				'event_espresso'
2044
+			);
2045
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2046
+			return false;
2047
+		}
2048
+		// was event trashed or restored ?
2049
+		switch ($event_status) {
2050
+			case 'draft' :
2051
+				$action = 'restored from the trash';
2052
+				$hook = 'AHEE_event_restored_from_trash';
2053
+				break;
2054
+			case 'trash' :
2055
+				$action = 'moved to the trash';
2056
+				$hook = 'AHEE_event_moved_to_trash';
2057
+				break;
2058
+			default :
2059
+				$action = 'updated';
2060
+				$hook = false;
2061
+		}
2062
+		//use class to change status
2063
+		$this->_cpt_model_obj->set_status($event_status);
2064
+		$success = $this->_cpt_model_obj->save();
2065
+		if ($success === false) {
2066
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2067
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2068
+			return false;
2069
+		}
2070
+		if ($hook) {
2071
+			do_action($hook);
2072
+		}
2073
+		return true;
2074
+	}
2075
+
2076
+
2077
+
2078
+	/**
2079
+	 * _delete_event
2080
+	 *
2081
+	 * @access protected
2082
+	 * @param bool $redirect_after
2083
+	 */
2084
+	protected function _delete_event($redirect_after = true)
2085
+	{
2086
+		//determine the event id and set to array.
2087
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2088
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2089
+		// loop thru events
2090
+		if ($EVT_ID) {
2091
+			$success = $this->_permanently_delete_event($EVT_ID);
2092
+			// get list of events with no prices
2093
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2094
+			// remove this event from the list of events with no prices
2095
+			if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2096
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2097
+			}
2098
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2099
+		} else {
2100
+			$success = false;
2101
+			$msg = esc_html__(
2102
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2103
+				'event_espresso'
2104
+			);
2105
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2106
+		}
2107
+		if ($redirect_after) {
2108
+			$this->_redirect_after_action(
2109
+				$success,
2110
+				'Event',
2111
+				'deleted',
2112
+				array('action' => 'default', 'status' => 'trash')
2113
+			);
2114
+		}
2115
+	}
2116
+
2117
+
2118
+
2119
+	/**
2120
+	 * _delete_events
2121
+	 *
2122
+	 * @access protected
2123
+	 * @return void
2124
+	 */
2125
+	protected function _delete_events()
2126
+	{
2127
+		$success = true;
2128
+		// get list of events with no prices
2129
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2130
+		//determine the event id and set to array.
2131
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array)$this->_req_data['EVT_IDs'] : array();
2132
+		// loop thru events
2133
+		foreach ($EVT_IDs as $EVT_ID) {
2134
+			$EVT_ID = absint($EVT_ID);
2135
+			if ($EVT_ID) {
2136
+				$results = $this->_permanently_delete_event($EVT_ID);
2137
+				$success = $results !== false ? $success : false;
2138
+				// remove this event from the list of events with no prices
2139
+				unset($espresso_no_ticket_prices[$EVT_ID]);
2140
+			} else {
2141
+				$success = false;
2142
+				$msg = esc_html__(
2143
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2144
+					'event_espresso'
2145
+				);
2146
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2147
+			}
2148
+		}
2149
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2150
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2151
+		$success = $success ? 2 : false;
2152
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2153
+	}
2154
+
2155
+
2156
+
2157
+	/**
2158
+	 * _permanently_delete_event
2159
+	 *
2160
+	 * @access  private
2161
+	 * @param  int $EVT_ID
2162
+	 * @return bool
2163
+	 */
2164
+	private function _permanently_delete_event($EVT_ID = 0)
2165
+	{
2166
+		// grab event id
2167
+		if ( ! $EVT_ID) {
2168
+			$msg = esc_html__(
2169
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2170
+				'event_espresso'
2171
+			);
2172
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2173
+			return false;
2174
+		}
2175
+		if (
2176
+			! $this->_cpt_model_obj instanceof EE_Event
2177
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2178
+		) {
2179
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2180
+		}
2181
+		if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2182
+			return false;
2183
+		}
2184
+		//need to delete related tickets and prices first.
2185
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2186
+		foreach ($datetimes as $datetime) {
2187
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2188
+			$tickets = $datetime->get_many_related('Ticket');
2189
+			foreach ($tickets as $ticket) {
2190
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2191
+				$ticket->delete_related_permanently('Price');
2192
+				$ticket->delete_permanently();
2193
+			}
2194
+			$datetime->delete();
2195
+		}
2196
+		//what about related venues or terms?
2197
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2198
+		foreach ($venues as $venue) {
2199
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2200
+		}
2201
+		//any attached question groups?
2202
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2203
+		if ( ! empty($question_groups)) {
2204
+			foreach ($question_groups as $question_group) {
2205
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2206
+			}
2207
+		}
2208
+		//Message Template Groups
2209
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2210
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2211
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2212
+		foreach ($term_taxonomies as $term_taxonomy) {
2213
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2214
+		}
2215
+		$success = $this->_cpt_model_obj->delete_permanently();
2216
+		// did it all go as planned ?
2217
+		if ($success) {
2218
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2219
+			EE_Error::add_success($msg);
2220
+		} else {
2221
+			$msg = sprintf(
2222
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2223
+				$EVT_ID
2224
+			);
2225
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
+			return false;
2227
+		}
2228
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2229
+		return true;
2230
+	}
2231
+
2232
+
2233
+
2234
+	/**
2235
+	 * get total number of events
2236
+	 *
2237
+	 * @access public
2238
+	 * @return int
2239
+	 */
2240
+	public function total_events()
2241
+	{
2242
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2243
+		return $count;
2244
+	}
2245
+
2246
+
2247
+
2248
+	/**
2249
+	 * get total number of draft events
2250
+	 *
2251
+	 * @access public
2252
+	 * @return int
2253
+	 */
2254
+	public function total_events_draft()
2255
+	{
2256
+		$where = array(
2257
+			'status' => array('IN', array('draft', 'auto-draft')),
2258
+		);
2259
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2260
+		return $count;
2261
+	}
2262
+
2263
+
2264
+
2265
+	/**
2266
+	 * get total number of trashed events
2267
+	 *
2268
+	 * @access public
2269
+	 * @return int
2270
+	 */
2271
+	public function total_trashed_events()
2272
+	{
2273
+		$where = array(
2274
+			'status' => 'trash',
2275
+		);
2276
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2277
+		return $count;
2278
+	}
2279
+
2280
+
2281
+	/**
2282
+	 *    _default_event_settings
2283
+	 *    This generates the Default Settings Tab
2284
+	 *
2285
+	 * @return void
2286
+	 * @throws EE_Error
2287
+	 */
2288
+	protected function _default_event_settings()
2289
+	{
2290
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2291
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2292
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2293
+		$this->display_admin_page_with_sidebar();
2294
+	}
2295
+
2296
+
2297
+	/**
2298
+	 * Return the form for event settings.
2299
+	 * @return EE_Form_Section_Proper
2300
+	 */
2301
+	protected function _default_event_settings_form()
2302
+	{
2303
+		$registration_config = EE_Registry::instance()->CFG->registration;
2304
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2305
+		//exclude
2306
+			array(
2307
+				EEM_Registration::status_id_cancelled,
2308
+				EEM_Registration::status_id_declined,
2309
+				EEM_Registration::status_id_incomplete,
2310
+				EEM_Registration::status_id_wait_list,
2311
+			),
2312
+			true
2313
+		);
2314
+		return new EE_Form_Section_Proper(
2315
+			array(
2316
+				'name' => 'update_default_event_settings',
2317
+				'html_id' => 'update_default_event_settings',
2318
+				'html_class' => 'form-table',
2319
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2320
+				'subsections' => apply_filters(
2321
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2322
+					array(
2323
+						'default_reg_status' => new EE_Select_Input(
2324
+							$registration_stati_for_selection,
2325
+							array(
2326
+								'default' => isset($registration_config->default_STS_ID)
2327
+											 && array_key_exists(
2328
+												$registration_config->default_STS_ID,
2329
+												$registration_stati_for_selection
2330
+											 )
2331
+											? sanitize_text_field($registration_config->default_STS_ID)
2332
+											: EEM_Registration::status_id_pending_payment,
2333
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2334
+													. EEH_Template::get_help_tab_link(
2335
+														'default_settings_status_help_tab'
2336
+													),
2337
+								'html_help_text' => esc_html__(
2338
+									'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.',
2339
+									'event_espresso'
2340
+								)
2341
+							)
2342
+						),
2343
+						'default_max_tickets' => new EE_Integer_Input(
2344
+							array(
2345
+								'default' => isset($registration_config->default_maximum_number_of_tickets)
2346
+									? $registration_config->default_maximum_number_of_tickets
2347
+									: EEM_Event::get_default_additional_limit(),
2348
+								'html_label_text' => esc_html__(
2349
+									'Default Maximum Tickets Allowed Per Order:',
2350
+									'event_espresso'
2351
+								) . EEH_Template::get_help_tab_link(
2352
+									'default_maximum_tickets_help_tab"'
2353
+									),
2354
+								'html_help_text' => esc_html__(
2355
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2356
+									'event_espresso'
2357
+								)
2358
+							)
2359
+						)
2360
+					)
2361
+				)
2362
+			)
2363
+		);
2364
+	}
2365
+
2366
+
2367
+	/**
2368
+	 * _update_default_event_settings
2369
+	 *
2370
+	 * @access protected
2371
+	 * @return void
2372
+	 * @throws EE_Error
2373
+	 */
2374
+	protected function _update_default_event_settings()
2375
+	{
2376
+		$registration_config = EE_Registry::instance()->CFG->registration;
2377
+		$form = $this->_default_event_settings_form();
2378
+		if ($form->was_submitted()) {
2379
+			$form->receive_form_submission();
2380
+			if ($form->is_valid()) {
2381
+				$valid_data = $form->valid_data();
2382
+				if (isset($valid_data['default_reg_status'])) {
2383
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2384
+				}
2385
+				if (isset($valid_data['default_max_tickets'])) {
2386
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2387
+				}
2388
+				//update because data was valid!
2389
+				EE_Registry::instance()->CFG->update_espresso_config();
2390
+				EE_Error::overwrite_success();
2391
+				EE_Error::add_success(
2392
+					__('Default Event Settings were updated', 'event_espresso')
2393
+				);
2394
+			}
2395
+		}
2396
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2397
+	}
2398
+
2399
+
2400
+
2401
+	/*************        Templates        *************/
2402
+	protected function _template_settings()
2403
+	{
2404
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2405
+		$this->_template_args['preview_img'] = '<img src="'
2406
+											   . EVENTS_ASSETS_URL
2407
+											   . DS
2408
+											   . 'images'
2409
+											   . DS
2410
+											   . 'caffeinated_template_features.jpg" alt="'
2411
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2412
+											   . '" />';
2413
+		$this->_template_args['preview_text'] = '<strong>' . esc_html__(
2414
+				'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.',
2415
+				'event_espresso'
2416
+			) . '</strong>';
2417
+		$this->display_admin_caf_preview_page('template_settings_tab');
2418
+	}
2419
+
2420
+
2421
+	/** Event Category Stuff **/
2422
+	/**
2423
+	 * set the _category property with the category object for the loaded page.
2424
+	 *
2425
+	 * @access private
2426
+	 * @return void
2427
+	 */
2428
+	private function _set_category_object()
2429
+	{
2430
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2431
+			return;
2432
+		} //already have the category object so get out.
2433
+		//set default category object
2434
+		$this->_set_empty_category_object();
2435
+		//only set if we've got an id
2436
+		if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2437
+			return;
2438
+		}
2439
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2440
+		$term = get_term($category_id, 'espresso_event_categories');
2441
+		if ( ! empty($term)) {
2442
+			$this->_category->category_name = $term->name;
2443
+			$this->_category->category_identifier = $term->slug;
2444
+			$this->_category->category_desc = $term->description;
2445
+			$this->_category->id = $term->term_id;
2446
+			$this->_category->parent = $term->parent;
2447
+		}
2448
+	}
2449
+
2450
+
2451
+	/**
2452
+	 * Clears out category properties.
2453
+	 */
2454
+	private function _set_empty_category_object()
2455
+	{
2456
+		$this->_category = new stdClass();
2457
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2458
+		$this->_category->id = $this->_category->parent = 0;
2459
+	}
2460
+
2461
+
2462
+	/**
2463
+	 * @throws EE_Error
2464
+	 */
2465
+	protected function _category_list_table()
2466
+	{
2467
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2468
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2469
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2470
+				'add_category',
2471
+				'add_category',
2472
+				array(),
2473
+				'add-new-h2'
2474
+			);
2475
+		$this->display_admin_list_table_page_with_sidebar();
2476
+	}
2477
+
2478
+
2479
+
2480
+	/**
2481
+	 * Output category details view.
2482
+	 */
2483
+	protected function _category_details($view)
2484
+	{
2485
+		//load formatter helper
2486
+		//load field generator helper
2487
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2488
+		$this->_set_add_edit_form_tags($route);
2489
+		$this->_set_category_object();
2490
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2491
+		$delete_action = 'delete_category';
2492
+		//custom redirect
2493
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2494
+			array('action' => 'category_list'),
2495
+			$this->_admin_base_url
2496
+		);
2497
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2498
+		//take care of contents
2499
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2500
+		$this->display_admin_page_with_sidebar();
2501
+	}
2502
+
2503
+
2504
+
2505
+	/**
2506
+	 * Output category details content.
2507
+	 */
2508
+	protected function _category_details_content()
2509
+	{
2510
+		$editor_args['category_desc'] = array(
2511
+			'type'          => 'wp_editor',
2512
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2513
+			'class'         => 'my_editor_custom',
2514
+			'wpeditor_args' => array('media_buttons' => false),
2515
+		);
2516
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2517
+		$all_terms = get_terms(
2518
+			array('espresso_event_categories'),
2519
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2520
+		);
2521
+		//setup category select for term parents.
2522
+		$category_select_values[] = array(
2523
+			'text' => esc_html__('No Parent', 'event_espresso'),
2524
+			'id'   => 0,
2525
+		);
2526
+		foreach ($all_terms as $term) {
2527
+			$category_select_values[] = array(
2528
+				'text' => $term->name,
2529
+				'id'   => $term->term_id,
2530
+			);
2531
+		}
2532
+		$category_select = EEH_Form_Fields::select_input(
2533
+			'category_parent',
2534
+			$category_select_values,
2535
+			$this->_category->parent
2536
+		);
2537
+		$template_args = array(
2538
+			'category'                 => $this->_category,
2539
+			'category_select'          => $category_select,
2540
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2541
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2542
+			'disable'                  => '',
2543
+			'disabled_message'         => false,
2544
+		);
2545
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2546
+		return EEH_Template::display_template($template, $template_args, true);
2547
+	}
2548
+
2549
+
2550
+	/**
2551
+	 * Handles deleting categories.
2552
+	 */
2553
+	protected function _delete_categories()
2554
+	{
2555
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array)$this->_req_data['EVT_CAT_ID']
2556
+			: (array)$this->_req_data['category_id'];
2557
+		foreach ($cat_ids as $cat_id) {
2558
+			$this->_delete_category($cat_id);
2559
+		}
2560
+		//doesn't matter what page we're coming from... we're going to the same place after delete.
2561
+		$query_args = array(
2562
+			'action' => 'category_list',
2563
+		);
2564
+		$this->_redirect_after_action(0, '', '', $query_args);
2565
+	}
2566
+
2567
+
2568
+
2569
+	/**
2570
+	 * Handles deleting specific category.
2571
+	 * @param int $cat_id
2572
+	 */
2573
+	protected function _delete_category($cat_id)
2574
+	{
2575
+		$cat_id = absint($cat_id);
2576
+		wp_delete_term($cat_id, 'espresso_event_categories');
2577
+	}
2578
+
2579
+
2580
+
2581
+	/**
2582
+	 * Handles triggering the update or insertion of a new category.
2583
+	 * @param bool $new_category  true means we're triggering the insert of a new category.
2584
+	 */
2585
+	protected function _insert_or_update_category($new_category)
2586
+	{
2587
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2588
+		$success = 0; //we already have a success message so lets not send another.
2589
+		if ($cat_id) {
2590
+			$query_args = array(
2591
+				'action'     => 'edit_category',
2592
+				'EVT_CAT_ID' => $cat_id,
2593
+			);
2594
+		} else {
2595
+			$query_args = array('action' => 'add_category');
2596
+		}
2597
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2598
+	}
2599
+
2600
+
2601
+
2602
+	/**
2603
+	 * Inserts or updates category
2604
+	 * @param bool $update (true indicates we're updating a category).
2605
+	 * @return bool|mixed|string
2606
+	 */
2607
+	private function _insert_category($update = false)
2608
+	{
2609
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2610
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2611
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2612
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2613
+		if (empty($category_name)) {
2614
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2615
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2616
+			return false;
2617
+		}
2618
+		$term_args = array(
2619
+			'name'        => $category_name,
2620
+			'description' => $category_desc,
2621
+			'parent'      => $category_parent,
2622
+		);
2623
+		//was the category_identifier input disabled?
2624
+		if (isset($this->_req_data['category_identifier'])) {
2625
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2626
+		}
2627
+		$insert_ids = $update
2628
+			? wp_update_term($cat_id, 'espresso_event_categories', $term_args)
2629
+			: wp_insert_term($category_name, 'espresso_event_categories', $term_args);
2630
+		if ( ! is_array($insert_ids)) {
2631
+			$msg = esc_html__(
2632
+				'An error occurred and the category has not been saved to the database.',
2633
+				'event_espresso'
2634
+			);
2635
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2636
+		} else {
2637
+			$cat_id = $insert_ids['term_id'];
2638
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2639
+			EE_Error::add_success($msg);
2640
+		}
2641
+		return $cat_id;
2642
+	}
2643
+
2644
+
2645
+
2646
+	/**
2647
+	 * Gets categories or count of categories matching the arguments in the request.
2648
+	 * @param int  $per_page
2649
+	 * @param int  $current_page
2650
+	 * @param bool $count
2651
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2652
+	 */
2653
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2654
+	{
2655
+		//testing term stuff
2656
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2657
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2658
+		$limit = ($current_page - 1) * $per_page;
2659
+		$where = array('taxonomy' => 'espresso_event_categories');
2660
+		if (isset($this->_req_data['s'])) {
2661
+			$sstr = '%' . $this->_req_data['s'] . '%';
2662
+			$where['OR'] = array(
2663
+				'Term.name'   => array('LIKE', $sstr),
2664
+				'description' => array('LIKE', $sstr),
2665
+			);
2666
+		}
2667
+		$query_params = array(
2668
+			$where,
2669
+			'order_by'   => array($orderby => $order),
2670
+			'limit'      => $limit . ',' . $per_page,
2671
+			'force_join' => array('Term'),
2672
+		);
2673
+		$categories = $count
2674
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2675
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2676
+		return $categories;
2677
+	}
2678
+
2679
+	/* end category stuff */
2680
+	/**************/
2681
+
2682
+
2683
+	/**
2684
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2685
+	 * @throws EE_Error
2686
+	 */
2687
+	public function save_timezonestring_setting()
2688
+	{
2689
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2690
+			? $this->_req_data['timezone_selected']
2691
+			: '';
2692
+		if  (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false))
2693
+		{
2694
+			EE_Error::add_error(
2695
+				esc_html('An invalid timezone string submitted.', 'event_espresso'),
2696
+				__FILE__, __FUNCTION__, __LINE__
2697
+			);
2698
+			$this->_template_args['error'] = true;
2699
+			$this->_return_json();
2700
+		}
2701
+
2702
+		update_option('timezone_string', $timezone_string);
2703
+		EE_Error::add_success(
2704
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2705
+		);
2706
+		$this->_template_args['success'] = true;
2707
+		$this->_return_json(true, array('action' => 'create_new'));
2708
+	}
2709 2709
 }
2710 2710
 //end class Events_Admin_Page
Please login to merge, or discard this patch.
admin_pages/maintenance/Maintenance_Admin_Page.core.php 2 patches
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -261,13 +261,13 @@  discard block
 block discarded – undo
261 261
                 && $most_recent_migration->is_broken()
262 262
             )
263 263
         ) {
264
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
264
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_was_borked_page.template.php';
265 265
             $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266 266
             $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267 267
                                                                                         'success' => '0',
268 268
             ), EE_MAINTENANCE_ADMIN_URL);
269 269
         } elseif ($addons_should_be_upgraded_first) {
270
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
270
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_upgrade_addons_before_migrating.template.php';
271 271
         } else {
272 272
             if ($most_recent_migration
273 273
                 && $most_recent_migration instanceof EE_Data_Migration_Script_Base
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
                 $this->_template_args['current_db_state'] = null;
298 298
                 $this->_template_args['next_db_state'] = null;
299 299
             }
300
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
300
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_page.template.php';
301 301
             $this->_template_args = array_merge(
302 302
                 $this->_template_args,
303 303
                 array(
@@ -336,13 +336,13 @@  discard block
 block discarded – undo
336 336
                 'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337 337
             ));
338 338
         }
339
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
339
+        $this->_template_args['most_recent_migration'] = $most_recent_migration; //the actual most recently ran migration
340 340
         //now render the migration options part, and put it in a variable
341 341
         $migration_options_template_file = apply_filters(
342 342
             'FHEE__ee_migration_page__migration_options_template',
343
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
343
+            EE_MAINTENANCE_TEMPLATE_PATH.'migration_options_from_ee4.template.php'
344 344
         );
345
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
345
+        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args, true);
346 346
         $this->_template_args['migration_options_html'] = $migration_options_html;
347 347
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348 348
             $this->_template_args, true);
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
      */
402 402
     public function _data_reset_and_delete()
403 403
     {
404
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
404
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_data_reset_and_delete.template.php';
405 405
         $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406 406
             'reset_reservations',
407 407
             'reset_reservations',
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
 
439 439
     protected function _reset_reservations()
440 440
     {
441
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
441
+        if (\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442 442
             EE_Error::add_success(
443 443
                 __(
444 444
                     'Ticket and datetime reserved counts have been successfully reset.',
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
      */
487 487
     public function _system_status()
488 488
     {
489
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
489
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_system_stati_page.template.php';
490 490
         $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491 491
         $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492 492
             array(
@@ -505,11 +505,11 @@  discard block
 block discarded – undo
505 505
     public function _download_system_status()
506 506
     {
507 507
         $status_info = EEM_System_Status::instance()->get_system_stati();
508
-        header( 'Content-Disposition: attachment' );
509
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
508
+        header('Content-Disposition: attachment');
509
+        header("Content-Disposition: attachment; filename=system_status_".sanitize_key(site_url()).".html");
510 510
         echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
-        echo "<h1>System Information for " . site_url() . "</h1>";
512
-        echo EEH_Template::layout_array_as_table( $status_info );
511
+        echo "<h1>System Information for ".site_url()."</h1>";
512
+        echo EEH_Template::layout_array_as_table($status_info);
513 513
         die;
514 514
     }
515 515
 
@@ -523,7 +523,7 @@  discard block
 block discarded – undo
523 523
         try {
524 524
             $success = wp_mail(EE_SUPPORT_EMAIL,
525 525
                 'Migration Crash Report',
526
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
526
+                $body."/r/n<br>".print_r(EEM_System_Status::instance()->get_system_stati(), true),
527 527
                 array(
528 528
                     "from:$from_name<$from>",
529 529
                     //					'content-type:text/html charset=UTF-8'
@@ -558,7 +558,7 @@  discard block
 block discarded – undo
558 558
             EE_MAINTENANCE_ADMIN_URL);
559 559
         $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560 560
             EE_MAINTENANCE_ADMIN_URL);
561
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
561
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_confirm_migration_crash_report_sent.template.php';
562 562
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563 563
             $this->_template_args, true);
564 564
         $this->display_admin_page_with_sidebar();
@@ -659,9 +659,9 @@  discard block
 block discarded – undo
659 659
         wp_enqueue_script('ee_admin_js');
660 660
 //		wp_enqueue_media();
661 661
 //		wp_enqueue_script('media-upload');
662
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
662
+        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL.'/ee-maintenance.js', array('jquery'),
663 663
             EVENT_ESPRESSO_VERSION, true);
664
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
664
+        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.css', array(),
665 665
             EVENT_ESPRESSO_VERSION);
666 666
         wp_enqueue_style('espresso_maintenance');
667 667
     }
@@ -698,8 +698,8 @@  discard block
 block discarded – undo
698 698
 
699 699
     protected function _get_datetime_offset_fix_form()
700 700
     {
701
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
701
+        if ( ! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
+            $this->datetime_fix_offset_form = new EE_Form_Section_Proper(
703 703
                 array(
704 704
                     'name' => 'datetime_offset_fix_option',
705 705
                     'layout_strategy' => new EE_Admin_Two_Column_Layout(),
Please login to merge, or discard this patch.
Indentation   +736 added lines, -736 removed lines patch added patch discarded remove patch
@@ -28,755 +28,755 @@
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * @var EE_Datetime_Offset_Fix_Form
33
-     */
34
-    protected $datetime_fix_offset_form;
35
-
36
-
37
-
38
-    protected function _init_page_props()
39
-    {
40
-        $this->page_slug = EE_MAINTENANCE_PG_SLUG;
41
-        $this->page_label = EE_MAINTENANCE_LABEL;
42
-        $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
43
-        $this->_admin_base_path = EE_MAINTENANCE_ADMIN;
44
-    }
45
-
46
-
47
-
48
-    protected function _ajax_hooks()
49
-    {
50
-        add_action('wp_ajax_migration_step', array($this, 'migration_step'));
51
-        add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
52
-    }
53
-
54
-
55
-
56
-    protected function _define_page_props()
57
-    {
58
-        $this->_admin_page_title = EE_MAINTENANCE_LABEL;
59
-        $this->_labels = array(
60
-            'buttons' => array(
61
-                'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
62
-                'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
63
-            ),
64
-        );
65
-    }
66
-
67
-
68
-
69
-    protected function _set_page_routes()
70
-    {
71
-        $this->_page_routes = array(
72
-            'default'                             => array(
73
-                'func'       => '_maintenance',
74
-                'capability' => 'manage_options',
75
-            ),
76
-            'change_maintenance_level'            => array(
77
-                'func'       => '_change_maintenance_level',
78
-                'capability' => 'manage_options',
79
-                'noheader'   => true,
80
-            ),
81
-            'system_status'                       => array(
82
-                'func'       => '_system_status',
83
-                'capability' => 'manage_options',
84
-            ),
85
-            'download_system_status' => array(
86
-                'func'       => '_download_system_status',
87
-                'capability' => 'manage_options',
88
-                'noheader'   => true,
89
-            ),
90
-            'send_migration_crash_report'         => array(
91
-                'func'       => '_send_migration_crash_report',
92
-                'capability' => 'manage_options',
93
-                'noheader'   => true,
94
-            ),
95
-            'confirm_migration_crash_report_sent' => array(
96
-                'func'       => '_confirm_migration_crash_report_sent',
97
-                'capability' => 'manage_options',
98
-            ),
99
-            'data_reset'                          => array(
100
-                'func'       => '_data_reset_and_delete',
101
-                'capability' => 'manage_options',
102
-            ),
103
-            'reset_db'                            => array(
104
-                'func'       => '_reset_db',
105
-                'capability' => 'manage_options',
106
-                'noheader'   => true,
107
-                'args'       => array('nuke_old_ee4_data' => true),
108
-            ),
109
-            'start_with_fresh_ee4_db'             => array(
110
-                'func'       => '_reset_db',
111
-                'capability' => 'manage_options',
112
-                'noheader'   => true,
113
-                'args'       => array('nuke_old_ee4_data' => false),
114
-            ),
115
-            'delete_db'                           => array(
116
-                'func'       => '_delete_db',
117
-                'capability' => 'manage_options',
118
-                'noheader'   => true,
119
-            ),
120
-            'rerun_migration_from_ee3'            => array(
121
-                'func'       => '_rerun_migration_from_ee3',
122
-                'capability' => 'manage_options',
123
-                'noheader'   => true,
124
-            ),
125
-            'reset_reservations'                  => array(
126
-                'func'       => '_reset_reservations',
127
-                'capability' => 'manage_options',
128
-                'noheader'   => true,
129
-            ),
130
-            'reset_capabilities'                  => array(
131
-                'func'       => '_reset_capabilities',
132
-                'capability' => 'manage_options',
133
-                'noheader'   => true,
134
-            ),
135
-            'reattempt_migration'                 => array(
136
-                'func'       => '_reattempt_migration',
137
-                'capability' => 'manage_options',
138
-                'noheader'   => true,
139
-            ),
140
-            'datetime_tools' => array(
141
-                'func' => '_datetime_tools',
142
-                'capability' => 'manage_options'
143
-            ),
144
-            'run_datetime_offset_fix' => array(
145
-                'func' => '_apply_datetime_offset',
146
-                'noheader' => true,
147
-                'headers_sent_route' => 'datetime_tools',
148
-                'capability' => 'manage_options'
149
-            )
150
-        );
151
-    }
152
-
153
-
154
-
155
-    protected function _set_page_config()
156
-    {
157
-        $this->_page_config = array(
158
-            'default'       => array(
159
-                'nav'           => array(
160
-                    'label' => esc_html__('Maintenance', 'event_espresso'),
161
-                    'order' => 10,
162
-                ),
163
-                'require_nonce' => false,
164
-            ),
165
-            'data_reset'    => array(
166
-                'nav'           => array(
167
-                    'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
168
-                    'order' => 20,
169
-                ),
170
-                'require_nonce' => false,
171
-            ),
172
-            'datetime_tools' => array(
173
-                'nav' => array(
174
-                    'label' => esc_html__('Datetime Utilities', 'event_espresso'),
175
-                    'order' => 25
176
-                ),
177
-                'require_nonce' => false,
178
-            ),
179
-            'system_status' => array(
180
-                'nav'           => array(
181
-                    'label' => esc_html__("System Information", "event_espresso"),
182
-                    'order' => 30,
183
-                ),
184
-                'require_nonce' => false,
185
-            ),
186
-        );
187
-    }
188
-
189
-
190
-
191
-    /**
192
-     * default maintenance page. If we're in maintenance mode level 2, then we need to show
193
-     * the migration scripts and all that UI.
194
-     */
195
-    public function _maintenance()
196
-    {
197
-        //it all depends if we're in maintenance model level 1 (frontend-only) or
198
-        //level 2 (everything except maintenance page)
199
-        try {
200
-            //get the current maintenance level and check if
201
-            //we are removed
202
-            $mm = EE_Maintenance_Mode::instance()->level();
203
-            $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
204
-            if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
205
-                //we just took the site out of maintenance mode, so notify the user.
206
-                //unfortunately this message appears to be echoed on the NEXT page load...
207
-                //oh well, we should really be checking for this on addon deactivation anyways
208
-                EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
209
-                    'event_espresso'));
210
-                $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
211
-            }
212
-            //in case an exception is thrown while trying to handle migrations
213
-            switch (EE_Maintenance_Mode::instance()->level()) {
214
-                case EE_Maintenance_Mode::level_0_not_in_maintenance:
215
-                case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
216
-                    $show_maintenance_switch = true;
217
-                    $show_backup_db_text = false;
218
-                    $show_migration_progress = false;
219
-                    $script_names = array();
220
-                    $addons_should_be_upgraded_first = false;
221
-                    break;
222
-                case EE_Maintenance_Mode::level_2_complete_maintenance:
223
-                    $show_maintenance_switch = false;
224
-                    $show_migration_progress = true;
225
-                    if (isset($this->_req_data['continue_migration'])) {
226
-                        $show_backup_db_text = false;
227
-                    } else {
228
-                        $show_backup_db_text = true;
229
-                    }
230
-                    $scripts_needing_to_run = EE_Data_Migration_Manager::instance()
231
-                                                                       ->check_for_applicable_data_migration_scripts();
232
-                    $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
233
-                    $script_names = array();
234
-                    $current_script = null;
235
-                    foreach ($scripts_needing_to_run as $script) {
236
-                        if ($script instanceof EE_Data_Migration_Script_Base) {
237
-                            if ( ! $current_script) {
238
-                                $current_script = $script;
239
-                                $current_script->migration_page_hooks();
240
-                            }
241
-                            $script_names[] = $script->pretty_name();
242
-                        }
243
-                    }
244
-                    break;
245
-            }
246
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
247
-            $exception_thrown = false;
248
-        } catch (EE_Error $e) {
249
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
250
-            //now, just so we can display the page correctly, make a error migration script stage object
251
-            //and also put the error on it. It only persists for the duration of this request
252
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
253
-            $most_recent_migration->add_error($e->getMessage());
254
-            $exception_thrown = true;
255
-        }
256
-        $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
257
-        $current_db_state = str_replace('.decaf', '', $current_db_state);
258
-        if ($exception_thrown
259
-            || ($most_recent_migration
260
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
261
-                && $most_recent_migration->is_broken()
262
-            )
263
-        ) {
264
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
265
-            $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266
-            $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267
-                                                                                        'success' => '0',
268
-            ), EE_MAINTENANCE_ADMIN_URL);
269
-        } elseif ($addons_should_be_upgraded_first) {
270
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
271
-        } else {
272
-            if ($most_recent_migration
273
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
274
-                && $most_recent_migration->can_continue()
275
-            ) {
276
-                $show_backup_db_text = false;
277
-                $show_continue_current_migration_script = true;
278
-                $show_most_recent_migration = true;
279
-            } elseif (isset($this->_req_data['continue_migration'])) {
280
-                $show_most_recent_migration = true;
281
-                $show_continue_current_migration_script = false;
282
-            } else {
283
-                $show_most_recent_migration = false;
284
-                $show_continue_current_migration_script = false;
285
-            }
286
-            if (isset($current_script)) {
287
-                $migrates_to = $current_script->migrates_to_version();
288
-                $plugin_slug = $migrates_to['slug'];
289
-                $new_version = $migrates_to['version'];
290
-                $this->_template_args = array_merge($this->_template_args, array(
291
-                    'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
292
-                        isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
293
-                    'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
294
-                        $new_version, $plugin_slug) : null,
295
-                ));
296
-            } else {
297
-                $this->_template_args['current_db_state'] = null;
298
-                $this->_template_args['next_db_state'] = null;
299
-            }
300
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
301
-            $this->_template_args = array_merge(
302
-                $this->_template_args,
303
-                array(
304
-                    'show_most_recent_migration'             => $show_most_recent_migration,
305
-                    //flag for showing the most recent migration's status and/or errors
306
-                    'show_migration_progress'                => $show_migration_progress,
307
-                    //flag for showing the option to run migrations and see their progress
308
-                    'show_backup_db_text'                    => $show_backup_db_text,
309
-                    //flag for showing text telling the user to backup their DB
310
-                    'show_maintenance_switch'                => $show_maintenance_switch,
311
-                    //flag for showing the option to change maintenance mode between levels 0 and 1
312
-                    'script_names'                           => $script_names,
313
-                    //array of names of scripts that have run
314
-                    'show_continue_current_migration_script' => $show_continue_current_migration_script,
315
-                    //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
316
-                    'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
317
-                        EE_MAINTENANCE_ADMIN_URL),
318
-                    'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
319
-                        EE_MAINTENANCE_ADMIN_URL),
320
-                    'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
321
-                        EE_MAINTENANCE_ADMIN_URL),
322
-                    'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
323
-                        espresso_version()),
324
-                )
325
-            );
326
-            //make sure we have the form fields helper available. It usually is, but sometimes it isn't
327
-            //localize script stuff
328
-            wp_localize_script('ee-maintenance', 'ee_maintenance', array(
329
-                'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
330
-                'next'                             => esc_html__("Next", "event_espresso"),
331
-                'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
332
-                'click_next_when_ready'            => esc_html__("The current Database Update has ended. Click 'next' when ready to proceed",
333
-                    "event_espresso"),
334
-                'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
335
-                'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
336
-                'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337
-            ));
338
-        }
339
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
340
-        //now render the migration options part, and put it in a variable
341
-        $migration_options_template_file = apply_filters(
342
-            'FHEE__ee_migration_page__migration_options_template',
343
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
344
-        );
345
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
346
-        $this->_template_args['migration_options_html'] = $migration_options_html;
347
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348
-            $this->_template_args, true);
349
-        $this->display_admin_page_with_sidebar();
350
-    }
351
-
352
-
353
-
354
-    /**
355
-     * returns JSON and executes another step of the currently-executing data migration (called via ajax)
356
-     */
357
-    public function migration_step()
358
-    {
359
-        $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
360
-        $this->_return_json();
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * Can be used by js when it notices a response with HTML in it in order
367
-     * to log the malformed response
368
-     */
369
-    public function add_error_to_migrations_ran()
370
-    {
371
-        EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
372
-        $this->_template_args['data'] = array('ok' => true);
373
-        $this->_return_json();
374
-    }
375
-
376
-
377
-
378
-    /**
379
-     * changes the maintenance level, provided there are still no migration scripts that should run
380
-     */
381
-    public function _change_maintenance_level()
382
-    {
383
-        $new_level = absint($this->_req_data['maintenance_mode_level']);
384
-        if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
385
-            EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
386
-            $success = true;
387
-        } else {
388
-            EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
389
-            $success = false;
390
-        }
391
-        $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
392
-    }
393
-
394
-
395
-
396
-    /**
397
-     * a tab with options for resetting and/or deleting EE data
398
-     *
399
-     * @throws \EE_Error
400
-     * @throws \DomainException
401
-     */
402
-    public function _data_reset_and_delete()
403
-    {
404
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
405
-        $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406
-            'reset_reservations',
407
-            'reset_reservations',
408
-            array(),
409
-            'button button-primary',
410
-            '',
411
-            false
412
-        );
413
-        $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
414
-            'reset_capabilities',
415
-            'reset_capabilities',
416
-            array(),
417
-            'button button-primary',
418
-            '',
419
-            false
420
-        );
421
-        $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
422
-            array('action' => 'delete_db'),
423
-            EE_MAINTENANCE_ADMIN_URL
424
-        );
425
-        $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
426
-            array('action' => 'reset_db'),
427
-            EE_MAINTENANCE_ADMIN_URL
428
-        );
429
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
430
-            $this->_template_path,
431
-            $this->_template_args,
432
-            true
433
-        );
434
-        $this->display_admin_page_with_sidebar();
435
-    }
436
-
437
-
438
-
439
-    protected function _reset_reservations()
440
-    {
441
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442
-            EE_Error::add_success(
443
-                __(
444
-                    'Ticket and datetime reserved counts have been successfully reset.',
445
-                    'event_espresso'
446
-                )
447
-            );
448
-        } else {
449
-            EE_Error::add_success(
450
-                __(
451
-                    'Ticket and datetime reserved counts were correct and did not need resetting.',
452
-                    'event_espresso'
453
-                )
454
-            );
455
-        }
456
-        $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
457
-    }
458
-
459
-
460
-
461
-    protected function _reset_capabilities()
462
-    {
463
-        EE_Registry::instance()->CAP->init_caps(true);
464
-        EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
465
-            'event_espresso'));
466
-        $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
467
-    }
468
-
469
-
470
-
471
-    /**
472
-     * resets the DMSs so we can attempt to continue migrating after a fatal error
473
-     * (only a good idea when someone has somehow tried ot fix whatever caused
474
-     * the fatal error in teh first place)
475
-     */
476
-    protected function _reattempt_migration()
477
-    {
478
-        EE_Data_Migration_Manager::instance()->reattempt();
479
-        $this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * shows the big ol' System Information page
486
-     */
487
-    public function _system_status()
488
-    {
489
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
490
-        $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491
-        $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492
-            array(
493
-                'action' => 'download_system_status',
494
-            ),
495
-            EE_MAINTENANCE_ADMIN_URL
496
-        );
497
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
498
-            $this->_template_args, true);
499
-        $this->display_admin_page_with_sidebar();
500
-    }
501
-
502
-    /**
503
-     * Downloads an HTML file of the system status that can be easily stored or emailed
504
-     */
505
-    public function _download_system_status()
506
-    {
507
-        $status_info = EEM_System_Status::instance()->get_system_stati();
508
-        header( 'Content-Disposition: attachment' );
509
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
510
-        echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
-        echo "<h1>System Information for " . site_url() . "</h1>";
512
-        echo EEH_Template::layout_array_as_table( $status_info );
513
-        die;
514
-    }
515
-
516
-
517
-
518
-    public function _send_migration_crash_report()
519
-    {
520
-        $from = $this->_req_data['from'];
521
-        $from_name = $this->_req_data['from_name'];
522
-        $body = $this->_req_data['body'];
523
-        try {
524
-            $success = wp_mail(EE_SUPPORT_EMAIL,
525
-                'Migration Crash Report',
526
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
527
-                array(
528
-                    "from:$from_name<$from>",
529
-                    //					'content-type:text/html charset=UTF-8'
530
-                ));
531
-        } catch (Exception $e) {
532
-            $success = false;
533
-        }
534
-        $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
535
-            esc_html__("sent", "event_espresso"),
536
-            array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
537
-    }
538
-
539
-
540
-
541
-    public function _confirm_migration_crash_report_sent()
542
-    {
543
-        try {
544
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
545
-        } catch (EE_Error $e) {
546
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
547
-            //now, just so we can display the page correctly, make a error migration script stage object
548
-            //and also put the error on it. It only persists for the duration of this request
549
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
550
-            $most_recent_migration->add_error($e->getMessage());
551
-        }
552
-        $success = $this->_req_data['success'] == '1' ? true : false;
553
-        $this->_template_args['success'] = $success;
554
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;
555
-        $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
556
-            EE_MAINTENANCE_ADMIN_URL);
557
-        $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
558
-            EE_MAINTENANCE_ADMIN_URL);
559
-        $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560
-            EE_MAINTENANCE_ADMIN_URL);
561
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
562
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563
-            $this->_template_args, true);
564
-        $this->display_admin_page_with_sidebar();
565
-    }
566
-
567
-
568
-
569
-    /**
570
-     * Resets the entire EE4 database.
571
-     * Currently basically only sets up ee4 database for a fresh install- doesn't
572
-     * actually clean out the old wp options, or cpts (although does erase old ee table data)
573
-     *
574
-     * @param boolean $nuke_old_ee4_data controls whether or not we
575
-     *                                   destroy the old ee4 data, or just try initializing ee4 default data
576
-     */
577
-    public function _reset_db($nuke_old_ee4_data = true)
578
-    {
579
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
580
-        if ($nuke_old_ee4_data) {
581
-            EEH_Activation::delete_all_espresso_cpt_data();
582
-            EEH_Activation::delete_all_espresso_tables_and_data(false);
583
-            EEH_Activation::remove_cron_tasks();
584
-        }
585
-        //make sure when we reset the registry's config that it
586
-        //switches to using the new singleton
587
-        EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
588
-        EE_System::instance()->initialize_db_if_no_migrations_required(true);
589
-        EE_System::instance()->redirect_to_about_ee();
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     * Deletes ALL EE tables, Records, and Options from the database.
596
-     */
597
-    public function _delete_db()
598
-    {
599
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
600
-        EEH_Activation::delete_all_espresso_cpt_data();
601
-        EEH_Activation::delete_all_espresso_tables_and_data();
602
-        EEH_Activation::remove_cron_tasks();
603
-        EEH_Activation::deactivate_event_espresso();
604
-        wp_safe_redirect(admin_url('plugins.php'));
605
-        exit;
606
-    }
607
-
608
-
609
-
610
-    /**
611
-     * sets up EE4 to rerun the migrations from ee3 to ee4
612
-     */
613
-    public function _rerun_migration_from_ee3()
614
-    {
615
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
616
-        EEH_Activation::delete_all_espresso_cpt_data();
617
-        EEH_Activation::delete_all_espresso_tables_and_data(false);
618
-        //set the db state to something that will require migrations
619
-        update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
620
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
621
-        $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
622
-    }
623
-
624
-
625
-
626
-    //none of the below group are currently used for Gateway Settings
627
-    protected function _add_screen_options()
628
-    {
629
-    }
630
-
631
-
632
-
633
-    protected function _add_feature_pointers()
634
-    {
635
-    }
636
-
31
+	/**
32
+	 * @var EE_Datetime_Offset_Fix_Form
33
+	 */
34
+	protected $datetime_fix_offset_form;
35
+
36
+
37
+
38
+	protected function _init_page_props()
39
+	{
40
+		$this->page_slug = EE_MAINTENANCE_PG_SLUG;
41
+		$this->page_label = EE_MAINTENANCE_LABEL;
42
+		$this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
43
+		$this->_admin_base_path = EE_MAINTENANCE_ADMIN;
44
+	}
45
+
46
+
47
+
48
+	protected function _ajax_hooks()
49
+	{
50
+		add_action('wp_ajax_migration_step', array($this, 'migration_step'));
51
+		add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
52
+	}
53
+
54
+
55
+
56
+	protected function _define_page_props()
57
+	{
58
+		$this->_admin_page_title = EE_MAINTENANCE_LABEL;
59
+		$this->_labels = array(
60
+			'buttons' => array(
61
+				'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
62
+				'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
63
+			),
64
+		);
65
+	}
66
+
67
+
68
+
69
+	protected function _set_page_routes()
70
+	{
71
+		$this->_page_routes = array(
72
+			'default'                             => array(
73
+				'func'       => '_maintenance',
74
+				'capability' => 'manage_options',
75
+			),
76
+			'change_maintenance_level'            => array(
77
+				'func'       => '_change_maintenance_level',
78
+				'capability' => 'manage_options',
79
+				'noheader'   => true,
80
+			),
81
+			'system_status'                       => array(
82
+				'func'       => '_system_status',
83
+				'capability' => 'manage_options',
84
+			),
85
+			'download_system_status' => array(
86
+				'func'       => '_download_system_status',
87
+				'capability' => 'manage_options',
88
+				'noheader'   => true,
89
+			),
90
+			'send_migration_crash_report'         => array(
91
+				'func'       => '_send_migration_crash_report',
92
+				'capability' => 'manage_options',
93
+				'noheader'   => true,
94
+			),
95
+			'confirm_migration_crash_report_sent' => array(
96
+				'func'       => '_confirm_migration_crash_report_sent',
97
+				'capability' => 'manage_options',
98
+			),
99
+			'data_reset'                          => array(
100
+				'func'       => '_data_reset_and_delete',
101
+				'capability' => 'manage_options',
102
+			),
103
+			'reset_db'                            => array(
104
+				'func'       => '_reset_db',
105
+				'capability' => 'manage_options',
106
+				'noheader'   => true,
107
+				'args'       => array('nuke_old_ee4_data' => true),
108
+			),
109
+			'start_with_fresh_ee4_db'             => array(
110
+				'func'       => '_reset_db',
111
+				'capability' => 'manage_options',
112
+				'noheader'   => true,
113
+				'args'       => array('nuke_old_ee4_data' => false),
114
+			),
115
+			'delete_db'                           => array(
116
+				'func'       => '_delete_db',
117
+				'capability' => 'manage_options',
118
+				'noheader'   => true,
119
+			),
120
+			'rerun_migration_from_ee3'            => array(
121
+				'func'       => '_rerun_migration_from_ee3',
122
+				'capability' => 'manage_options',
123
+				'noheader'   => true,
124
+			),
125
+			'reset_reservations'                  => array(
126
+				'func'       => '_reset_reservations',
127
+				'capability' => 'manage_options',
128
+				'noheader'   => true,
129
+			),
130
+			'reset_capabilities'                  => array(
131
+				'func'       => '_reset_capabilities',
132
+				'capability' => 'manage_options',
133
+				'noheader'   => true,
134
+			),
135
+			'reattempt_migration'                 => array(
136
+				'func'       => '_reattempt_migration',
137
+				'capability' => 'manage_options',
138
+				'noheader'   => true,
139
+			),
140
+			'datetime_tools' => array(
141
+				'func' => '_datetime_tools',
142
+				'capability' => 'manage_options'
143
+			),
144
+			'run_datetime_offset_fix' => array(
145
+				'func' => '_apply_datetime_offset',
146
+				'noheader' => true,
147
+				'headers_sent_route' => 'datetime_tools',
148
+				'capability' => 'manage_options'
149
+			)
150
+		);
151
+	}
152
+
153
+
154
+
155
+	protected function _set_page_config()
156
+	{
157
+		$this->_page_config = array(
158
+			'default'       => array(
159
+				'nav'           => array(
160
+					'label' => esc_html__('Maintenance', 'event_espresso'),
161
+					'order' => 10,
162
+				),
163
+				'require_nonce' => false,
164
+			),
165
+			'data_reset'    => array(
166
+				'nav'           => array(
167
+					'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
168
+					'order' => 20,
169
+				),
170
+				'require_nonce' => false,
171
+			),
172
+			'datetime_tools' => array(
173
+				'nav' => array(
174
+					'label' => esc_html__('Datetime Utilities', 'event_espresso'),
175
+					'order' => 25
176
+				),
177
+				'require_nonce' => false,
178
+			),
179
+			'system_status' => array(
180
+				'nav'           => array(
181
+					'label' => esc_html__("System Information", "event_espresso"),
182
+					'order' => 30,
183
+				),
184
+				'require_nonce' => false,
185
+			),
186
+		);
187
+	}
188
+
189
+
190
+
191
+	/**
192
+	 * default maintenance page. If we're in maintenance mode level 2, then we need to show
193
+	 * the migration scripts and all that UI.
194
+	 */
195
+	public function _maintenance()
196
+	{
197
+		//it all depends if we're in maintenance model level 1 (frontend-only) or
198
+		//level 2 (everything except maintenance page)
199
+		try {
200
+			//get the current maintenance level and check if
201
+			//we are removed
202
+			$mm = EE_Maintenance_Mode::instance()->level();
203
+			$placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
204
+			if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
205
+				//we just took the site out of maintenance mode, so notify the user.
206
+				//unfortunately this message appears to be echoed on the NEXT page load...
207
+				//oh well, we should really be checking for this on addon deactivation anyways
208
+				EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
209
+					'event_espresso'));
210
+				$this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
211
+			}
212
+			//in case an exception is thrown while trying to handle migrations
213
+			switch (EE_Maintenance_Mode::instance()->level()) {
214
+				case EE_Maintenance_Mode::level_0_not_in_maintenance:
215
+				case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
216
+					$show_maintenance_switch = true;
217
+					$show_backup_db_text = false;
218
+					$show_migration_progress = false;
219
+					$script_names = array();
220
+					$addons_should_be_upgraded_first = false;
221
+					break;
222
+				case EE_Maintenance_Mode::level_2_complete_maintenance:
223
+					$show_maintenance_switch = false;
224
+					$show_migration_progress = true;
225
+					if (isset($this->_req_data['continue_migration'])) {
226
+						$show_backup_db_text = false;
227
+					} else {
228
+						$show_backup_db_text = true;
229
+					}
230
+					$scripts_needing_to_run = EE_Data_Migration_Manager::instance()
231
+																	   ->check_for_applicable_data_migration_scripts();
232
+					$addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
233
+					$script_names = array();
234
+					$current_script = null;
235
+					foreach ($scripts_needing_to_run as $script) {
236
+						if ($script instanceof EE_Data_Migration_Script_Base) {
237
+							if ( ! $current_script) {
238
+								$current_script = $script;
239
+								$current_script->migration_page_hooks();
240
+							}
241
+							$script_names[] = $script->pretty_name();
242
+						}
243
+					}
244
+					break;
245
+			}
246
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
247
+			$exception_thrown = false;
248
+		} catch (EE_Error $e) {
249
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
250
+			//now, just so we can display the page correctly, make a error migration script stage object
251
+			//and also put the error on it. It only persists for the duration of this request
252
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
253
+			$most_recent_migration->add_error($e->getMessage());
254
+			$exception_thrown = true;
255
+		}
256
+		$current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
257
+		$current_db_state = str_replace('.decaf', '', $current_db_state);
258
+		if ($exception_thrown
259
+			|| ($most_recent_migration
260
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
261
+				&& $most_recent_migration->is_broken()
262
+			)
263
+		) {
264
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
265
+			$this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
266
+			$this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
267
+																						'success' => '0',
268
+			), EE_MAINTENANCE_ADMIN_URL);
269
+		} elseif ($addons_should_be_upgraded_first) {
270
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
271
+		} else {
272
+			if ($most_recent_migration
273
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
274
+				&& $most_recent_migration->can_continue()
275
+			) {
276
+				$show_backup_db_text = false;
277
+				$show_continue_current_migration_script = true;
278
+				$show_most_recent_migration = true;
279
+			} elseif (isset($this->_req_data['continue_migration'])) {
280
+				$show_most_recent_migration = true;
281
+				$show_continue_current_migration_script = false;
282
+			} else {
283
+				$show_most_recent_migration = false;
284
+				$show_continue_current_migration_script = false;
285
+			}
286
+			if (isset($current_script)) {
287
+				$migrates_to = $current_script->migrates_to_version();
288
+				$plugin_slug = $migrates_to['slug'];
289
+				$new_version = $migrates_to['version'];
290
+				$this->_template_args = array_merge($this->_template_args, array(
291
+					'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
292
+						isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
293
+					'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
294
+						$new_version, $plugin_slug) : null,
295
+				));
296
+			} else {
297
+				$this->_template_args['current_db_state'] = null;
298
+				$this->_template_args['next_db_state'] = null;
299
+			}
300
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
301
+			$this->_template_args = array_merge(
302
+				$this->_template_args,
303
+				array(
304
+					'show_most_recent_migration'             => $show_most_recent_migration,
305
+					//flag for showing the most recent migration's status and/or errors
306
+					'show_migration_progress'                => $show_migration_progress,
307
+					//flag for showing the option to run migrations and see their progress
308
+					'show_backup_db_text'                    => $show_backup_db_text,
309
+					//flag for showing text telling the user to backup their DB
310
+					'show_maintenance_switch'                => $show_maintenance_switch,
311
+					//flag for showing the option to change maintenance mode between levels 0 and 1
312
+					'script_names'                           => $script_names,
313
+					//array of names of scripts that have run
314
+					'show_continue_current_migration_script' => $show_continue_current_migration_script,
315
+					//flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
316
+					'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
317
+						EE_MAINTENANCE_ADMIN_URL),
318
+					'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
319
+						EE_MAINTENANCE_ADMIN_URL),
320
+					'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
321
+						EE_MAINTENANCE_ADMIN_URL),
322
+					'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
323
+						espresso_version()),
324
+				)
325
+			);
326
+			//make sure we have the form fields helper available. It usually is, but sometimes it isn't
327
+			//localize script stuff
328
+			wp_localize_script('ee-maintenance', 'ee_maintenance', array(
329
+				'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
330
+				'next'                             => esc_html__("Next", "event_espresso"),
331
+				'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
332
+				'click_next_when_ready'            => esc_html__("The current Database Update has ended. Click 'next' when ready to proceed",
333
+					"event_espresso"),
334
+				'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
335
+				'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
336
+				'status_completed'                 => EE_Data_Migration_Manager::status_completed,
337
+			));
338
+		}
339
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
340
+		//now render the migration options part, and put it in a variable
341
+		$migration_options_template_file = apply_filters(
342
+			'FHEE__ee_migration_page__migration_options_template',
343
+			EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
344
+		);
345
+		$migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
346
+		$this->_template_args['migration_options_html'] = $migration_options_html;
347
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
348
+			$this->_template_args, true);
349
+		$this->display_admin_page_with_sidebar();
350
+	}
351
+
352
+
353
+
354
+	/**
355
+	 * returns JSON and executes another step of the currently-executing data migration (called via ajax)
356
+	 */
357
+	public function migration_step()
358
+	{
359
+		$this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
360
+		$this->_return_json();
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * Can be used by js when it notices a response with HTML in it in order
367
+	 * to log the malformed response
368
+	 */
369
+	public function add_error_to_migrations_ran()
370
+	{
371
+		EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
372
+		$this->_template_args['data'] = array('ok' => true);
373
+		$this->_return_json();
374
+	}
375
+
376
+
377
+
378
+	/**
379
+	 * changes the maintenance level, provided there are still no migration scripts that should run
380
+	 */
381
+	public function _change_maintenance_level()
382
+	{
383
+		$new_level = absint($this->_req_data['maintenance_mode_level']);
384
+		if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
385
+			EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
386
+			$success = true;
387
+		} else {
388
+			EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
389
+			$success = false;
390
+		}
391
+		$this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
392
+	}
393
+
394
+
395
+
396
+	/**
397
+	 * a tab with options for resetting and/or deleting EE data
398
+	 *
399
+	 * @throws \EE_Error
400
+	 * @throws \DomainException
401
+	 */
402
+	public function _data_reset_and_delete()
403
+	{
404
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
405
+		$this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
406
+			'reset_reservations',
407
+			'reset_reservations',
408
+			array(),
409
+			'button button-primary',
410
+			'',
411
+			false
412
+		);
413
+		$this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
414
+			'reset_capabilities',
415
+			'reset_capabilities',
416
+			array(),
417
+			'button button-primary',
418
+			'',
419
+			false
420
+		);
421
+		$this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
422
+			array('action' => 'delete_db'),
423
+			EE_MAINTENANCE_ADMIN_URL
424
+		);
425
+		$this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
426
+			array('action' => 'reset_db'),
427
+			EE_MAINTENANCE_ADMIN_URL
428
+		);
429
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
430
+			$this->_template_path,
431
+			$this->_template_args,
432
+			true
433
+		);
434
+		$this->display_admin_page_with_sidebar();
435
+	}
436
+
437
+
438
+
439
+	protected function _reset_reservations()
440
+	{
441
+		if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
442
+			EE_Error::add_success(
443
+				__(
444
+					'Ticket and datetime reserved counts have been successfully reset.',
445
+					'event_espresso'
446
+				)
447
+			);
448
+		} else {
449
+			EE_Error::add_success(
450
+				__(
451
+					'Ticket and datetime reserved counts were correct and did not need resetting.',
452
+					'event_espresso'
453
+				)
454
+			);
455
+		}
456
+		$this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
457
+	}
458
+
459
+
460
+
461
+	protected function _reset_capabilities()
462
+	{
463
+		EE_Registry::instance()->CAP->init_caps(true);
464
+		EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
465
+			'event_espresso'));
466
+		$this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
467
+	}
468
+
469
+
470
+
471
+	/**
472
+	 * resets the DMSs so we can attempt to continue migrating after a fatal error
473
+	 * (only a good idea when someone has somehow tried ot fix whatever caused
474
+	 * the fatal error in teh first place)
475
+	 */
476
+	protected function _reattempt_migration()
477
+	{
478
+		EE_Data_Migration_Manager::instance()->reattempt();
479
+		$this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * shows the big ol' System Information page
486
+	 */
487
+	public function _system_status()
488
+	{
489
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
490
+		$this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
491
+		$this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
492
+			array(
493
+				'action' => 'download_system_status',
494
+			),
495
+			EE_MAINTENANCE_ADMIN_URL
496
+		);
497
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
498
+			$this->_template_args, true);
499
+		$this->display_admin_page_with_sidebar();
500
+	}
501
+
502
+	/**
503
+	 * Downloads an HTML file of the system status that can be easily stored or emailed
504
+	 */
505
+	public function _download_system_status()
506
+	{
507
+		$status_info = EEM_System_Status::instance()->get_system_stati();
508
+		header( 'Content-Disposition: attachment' );
509
+		header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
510
+		echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
511
+		echo "<h1>System Information for " . site_url() . "</h1>";
512
+		echo EEH_Template::layout_array_as_table( $status_info );
513
+		die;
514
+	}
515
+
516
+
517
+
518
+	public function _send_migration_crash_report()
519
+	{
520
+		$from = $this->_req_data['from'];
521
+		$from_name = $this->_req_data['from_name'];
522
+		$body = $this->_req_data['body'];
523
+		try {
524
+			$success = wp_mail(EE_SUPPORT_EMAIL,
525
+				'Migration Crash Report',
526
+				$body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
527
+				array(
528
+					"from:$from_name<$from>",
529
+					//					'content-type:text/html charset=UTF-8'
530
+				));
531
+		} catch (Exception $e) {
532
+			$success = false;
533
+		}
534
+		$this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
535
+			esc_html__("sent", "event_espresso"),
536
+			array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
537
+	}
538
+
539
+
540
+
541
+	public function _confirm_migration_crash_report_sent()
542
+	{
543
+		try {
544
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
545
+		} catch (EE_Error $e) {
546
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
547
+			//now, just so we can display the page correctly, make a error migration script stage object
548
+			//and also put the error on it. It only persists for the duration of this request
549
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
550
+			$most_recent_migration->add_error($e->getMessage());
551
+		}
552
+		$success = $this->_req_data['success'] == '1' ? true : false;
553
+		$this->_template_args['success'] = $success;
554
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;
555
+		$this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
556
+			EE_MAINTENANCE_ADMIN_URL);
557
+		$this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
558
+			EE_MAINTENANCE_ADMIN_URL);
559
+		$this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
560
+			EE_MAINTENANCE_ADMIN_URL);
561
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
562
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
563
+			$this->_template_args, true);
564
+		$this->display_admin_page_with_sidebar();
565
+	}
566
+
567
+
568
+
569
+	/**
570
+	 * Resets the entire EE4 database.
571
+	 * Currently basically only sets up ee4 database for a fresh install- doesn't
572
+	 * actually clean out the old wp options, or cpts (although does erase old ee table data)
573
+	 *
574
+	 * @param boolean $nuke_old_ee4_data controls whether or not we
575
+	 *                                   destroy the old ee4 data, or just try initializing ee4 default data
576
+	 */
577
+	public function _reset_db($nuke_old_ee4_data = true)
578
+	{
579
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
580
+		if ($nuke_old_ee4_data) {
581
+			EEH_Activation::delete_all_espresso_cpt_data();
582
+			EEH_Activation::delete_all_espresso_tables_and_data(false);
583
+			EEH_Activation::remove_cron_tasks();
584
+		}
585
+		//make sure when we reset the registry's config that it
586
+		//switches to using the new singleton
587
+		EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
588
+		EE_System::instance()->initialize_db_if_no_migrations_required(true);
589
+		EE_System::instance()->redirect_to_about_ee();
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 * Deletes ALL EE tables, Records, and Options from the database.
596
+	 */
597
+	public function _delete_db()
598
+	{
599
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
600
+		EEH_Activation::delete_all_espresso_cpt_data();
601
+		EEH_Activation::delete_all_espresso_tables_and_data();
602
+		EEH_Activation::remove_cron_tasks();
603
+		EEH_Activation::deactivate_event_espresso();
604
+		wp_safe_redirect(admin_url('plugins.php'));
605
+		exit;
606
+	}
607
+
608
+
609
+
610
+	/**
611
+	 * sets up EE4 to rerun the migrations from ee3 to ee4
612
+	 */
613
+	public function _rerun_migration_from_ee3()
614
+	{
615
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
616
+		EEH_Activation::delete_all_espresso_cpt_data();
617
+		EEH_Activation::delete_all_espresso_tables_and_data(false);
618
+		//set the db state to something that will require migrations
619
+		update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
620
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
621
+		$this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
622
+	}
623
+
624
+
625
+
626
+	//none of the below group are currently used for Gateway Settings
627
+	protected function _add_screen_options()
628
+	{
629
+	}
630
+
631
+
632
+
633
+	protected function _add_feature_pointers()
634
+	{
635
+	}
636
+
637 637
 
638 638
 
639
-    public function admin_init()
640
-    {
641
-    }
642
-
643
-
644
-
645
-    public function admin_notices()
646
-    {
647
-    }
648
-
639
+	public function admin_init()
640
+	{
641
+	}
642
+
643
+
644
+
645
+	public function admin_notices()
646
+	{
647
+	}
648
+
649 649
 
650 650
 
651
-    public function admin_footer_scripts()
652
-    {
653
-    }
651
+	public function admin_footer_scripts()
652
+	{
653
+	}
654 654
 
655 655
 
656 656
 
657
-    public function load_scripts_styles()
658
-    {
659
-        wp_enqueue_script('ee_admin_js');
657
+	public function load_scripts_styles()
658
+	{
659
+		wp_enqueue_script('ee_admin_js');
660 660
 //		wp_enqueue_media();
661 661
 //		wp_enqueue_script('media-upload');
662
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
663
-            EVENT_ESPRESSO_VERSION, true);
664
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
665
-            EVENT_ESPRESSO_VERSION);
666
-        wp_enqueue_style('espresso_maintenance');
667
-    }
662
+		wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . '/ee-maintenance.js', array('jquery'),
663
+			EVENT_ESPRESSO_VERSION, true);
664
+		wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
665
+			EVENT_ESPRESSO_VERSION);
666
+		wp_enqueue_style('espresso_maintenance');
667
+	}
668 668
 
669 669
 
670 670
 
671
-    public function load_scripts_styles_default()
672
-    {
673
-        //styles
671
+	public function load_scripts_styles_default()
672
+	{
673
+		//styles
674 674
 //		wp_enqueue_style('ee-text-links');
675 675
 //		//scripts
676 676
 //		wp_enqueue_script('ee-text-links');
677
-    }
678
-
679
-
680
-    protected function _datetime_tools()
681
-    {
682
-        $form_action = EE_Admin_Page::add_query_args_and_nonce(
683
-            array(
684
-                'action' => 'run_datetime_offset_fix',
685
-                'return_action' => $this->_req_action
686
-            ),
687
-            EE_MAINTENANCE_ADMIN_URL
688
-        );
689
-        $form = $this->_get_datetime_offset_fix_form();
690
-        $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
691
-        $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
692
-                                                      . $form->get_html_and_js()
693
-                                                      . $form->form_close();
694
-        $this->display_admin_page_with_no_sidebar();
695
-    }
696
-
697
-
698
-
699
-    protected function _get_datetime_offset_fix_form()
700
-    {
701
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
703
-                array(
704
-                    'name' => 'datetime_offset_fix_option',
705
-                    'layout_strategy' => new EE_Admin_Two_Column_Layout(),
706
-                    'subsections' => array(
707
-                        'title' => new EE_Form_Section_HTML(
708
-                            EEH_HTML::h2(
709
-                                esc_html__('Datetime Offset Tool', 'event_espresso')
710
-                            )
711
-                        ),
712
-                        'explanation' => new EE_Form_Section_HTML(
713
-                            EEH_HTML::p(
714
-                                esc_html__(
715
-                                    'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
716
-                                    'event_espresso'
717
-                                )
718
-                            )
719
-                            . EEH_HTML::p(
720
-                                esc_html__(
721
-                                    'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
722
-                                    'event_espresso'
723
-                                )
724
-                            )
725
-                        ),
726
-                        'offset_input' => new EE_Float_Input(
727
-                            array(
728
-                                'html_name' => 'offset_for_datetimes',
729
-                                'html_label_text' => esc_html__(
730
-                                    'Offset to apply (in hours):',
731
-                                    'event_espresso'
732
-                                ),
733
-                                'min_value' => '-12',
734
-                                'max_value' => '14',
735
-                                'step_value' => '.25',
736
-                                'default' => DatetimeOffsetFix::getOffset()
737
-                            )
738
-                        ),
739
-                        'submit' => new EE_Submit_Input(
740
-                            array(
741
-                                'html_label_text' => '',
742
-                                'default' => esc_html__('Apply Offset', 'event_espresso')
743
-                            )
744
-                        )
745
-                    )
746
-                )
747
-            );
748
-        }
749
-        return $this->datetime_fix_offset_form;
750
-    }
751
-
752
-
753
-    /**
754
-     * Callback for the run_datetime_offset_fix route.
755
-     * @throws EE_Error
756
-     */
757
-    protected function _apply_datetime_offset()
758
-    {
759
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
760
-            $form = $this->_get_datetime_offset_fix_form();
761
-            $form->receive_form_submission($this->_req_data);
762
-            if ($form->is_valid()) {
763
-                //save offset so batch processor can get it.
764
-                DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
765
-                //redirect to batch tool
766
-                wp_redirect(
767
-                    EE_Admin_Page::add_query_args_and_nonce(
768
-                        array(
769
-                            'page' => 'espresso_batch',
770
-                            'batch' => 'job',
771
-                            'label' => esc_html__('Applying Offset', 'event_espresso'),
772
-                            'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
773
-                            'return_url' => urlencode(home_url(add_query_arg(null, null))),
774
-                        ),
775
-                        admin_url()
776
-                    )
777
-                );
778
-                exit;
779
-            }
780
-        }
781
-    }
677
+	}
678
+
679
+
680
+	protected function _datetime_tools()
681
+	{
682
+		$form_action = EE_Admin_Page::add_query_args_and_nonce(
683
+			array(
684
+				'action' => 'run_datetime_offset_fix',
685
+				'return_action' => $this->_req_action
686
+			),
687
+			EE_MAINTENANCE_ADMIN_URL
688
+		);
689
+		$form = $this->_get_datetime_offset_fix_form();
690
+		$this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
691
+		$this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
692
+													  . $form->get_html_and_js()
693
+													  . $form->form_close();
694
+		$this->display_admin_page_with_no_sidebar();
695
+	}
696
+
697
+
698
+
699
+	protected function _get_datetime_offset_fix_form()
700
+	{
701
+		if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
702
+			$this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
703
+				array(
704
+					'name' => 'datetime_offset_fix_option',
705
+					'layout_strategy' => new EE_Admin_Two_Column_Layout(),
706
+					'subsections' => array(
707
+						'title' => new EE_Form_Section_HTML(
708
+							EEH_HTML::h2(
709
+								esc_html__('Datetime Offset Tool', 'event_espresso')
710
+							)
711
+						),
712
+						'explanation' => new EE_Form_Section_HTML(
713
+							EEH_HTML::p(
714
+								esc_html__(
715
+									'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
716
+									'event_espresso'
717
+								)
718
+							)
719
+							. EEH_HTML::p(
720
+								esc_html__(
721
+									'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
722
+									'event_espresso'
723
+								)
724
+							)
725
+						),
726
+						'offset_input' => new EE_Float_Input(
727
+							array(
728
+								'html_name' => 'offset_for_datetimes',
729
+								'html_label_text' => esc_html__(
730
+									'Offset to apply (in hours):',
731
+									'event_espresso'
732
+								),
733
+								'min_value' => '-12',
734
+								'max_value' => '14',
735
+								'step_value' => '.25',
736
+								'default' => DatetimeOffsetFix::getOffset()
737
+							)
738
+						),
739
+						'submit' => new EE_Submit_Input(
740
+							array(
741
+								'html_label_text' => '',
742
+								'default' => esc_html__('Apply Offset', 'event_espresso')
743
+							)
744
+						)
745
+					)
746
+				)
747
+			);
748
+		}
749
+		return $this->datetime_fix_offset_form;
750
+	}
751
+
752
+
753
+	/**
754
+	 * Callback for the run_datetime_offset_fix route.
755
+	 * @throws EE_Error
756
+	 */
757
+	protected function _apply_datetime_offset()
758
+	{
759
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
760
+			$form = $this->_get_datetime_offset_fix_form();
761
+			$form->receive_form_submission($this->_req_data);
762
+			if ($form->is_valid()) {
763
+				//save offset so batch processor can get it.
764
+				DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
765
+				//redirect to batch tool
766
+				wp_redirect(
767
+					EE_Admin_Page::add_query_args_and_nonce(
768
+						array(
769
+							'page' => 'espresso_batch',
770
+							'batch' => 'job',
771
+							'label' => esc_html__('Applying Offset', 'event_espresso'),
772
+							'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
773
+							'return_url' => urlencode(home_url(add_query_arg(null, null))),
774
+						),
775
+						admin_url()
776
+					)
777
+				);
778
+				exit;
779
+			}
780
+		}
781
+	}
782 782
 } //end Maintenance_Admin_Page class
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 2 patches
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
     public static function instance()
33 33
     {
34 34
         // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Admin) {
35
+        if ( ! self::$_instance instanceof EE_Admin) {
36 36
             self::$_instance = new self();
37 37
         }
38 38
         return self::$_instance;
@@ -91,11 +91,11 @@  discard block
 block discarded – undo
91 91
      */
92 92
     private function _define_all_constants()
93 93
     {
94
-        if (! defined('EE_ADMIN_URL')) {
95
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
94
+        if ( ! defined('EE_ADMIN_URL')) {
95
+            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL.'core/admin/');
96
+            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL.'admin_pages/');
97
+            define('EE_ADMIN_TEMPLATE', EE_ADMIN.'templates'.DS);
98
+            define('WP_ADMIN_PATH', ABSPATH.'wp-admin/');
99 99
             define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100 100
         }
101 101
     }
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
         // set $main_file in stone
115 115
         static $main_file;
116 116
         // if $main_file is not set yet
117
-        if (! $main_file) {
117
+        if ( ! $main_file) {
118 118
             $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119 119
         }
120 120
         if ($plugin === $main_file) {
@@ -165,9 +165,9 @@  discard block
 block discarded – undo
165 165
     public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166 166
     {
167 167
         return array(
168
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
168
+            'maintenance' => EE_ADMIN_PAGES.'maintenance'.DS,
169
+            'about'       => EE_ADMIN_PAGES.'about'.DS,
170
+            'support'     => EE_ADMIN_PAGES.'support'.DS,
171 171
         );
172 172
     }
173 173
 
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
             add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196 196
         }
197 197
         // run the admin page factory but ONLY if we are doing an ee admin ajax request
198
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
198
+        if ( ! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199 199
             try {
200 200
                 //this loads the controller for the admin pages which will setup routing etc
201 201
                 EE_Registry::instance()->load_core('Admin_Page_Loader');
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
     public function enable_hidden_ee_nav_menu_metaboxes()
248 248
     {
249 249
         global $wp_meta_boxes, $pagenow;
250
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
250
+        if ( ! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251 251
             return;
252 252
         }
253 253
         $user = wp_get_current_user();
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
      */
319 319
     public function modify_edit_post_link($link, $id)
320 320
     {
321
-        if (! $post = get_post($id)) {
321
+        if ( ! $post = get_post($id)) {
322 322
             return $link;
323 323
         }
324 324
         if ($post->post_type === 'espresso_attendees') {
@@ -544,7 +544,7 @@  discard block
 block discarded – undo
544 544
 
545 545
         //loop through to remove any critical pages from the array.
546 546
         foreach ($critical_pages as $page_id) {
547
-            $needle = 'value="' . $page_id . '"';
547
+            $needle = 'value="'.$page_id.'"';
548 548
             foreach ($split_output as $key => $haystack) {
549 549
                 if (strpos($haystack, $needle) !== false) {
550 550
                     unset($split_output[$key]);
@@ -570,7 +570,7 @@  discard block
 block discarded – undo
570 570
         // calls.
571 571
         wp_enqueue_script(
572 572
             'ee-inject-wp',
573
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
573
+            EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js',
574 574
             array('jquery'),
575 575
             EVENT_ESPRESSO_VERSION,
576 576
             true
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
         // register cookie script for future dependencies
579 579
         wp_register_script(
580 580
             'jquery-cookie',
581
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
581
+            EE_THIRD_PARTY_URL.'joyride/jquery.cookie.js',
582 582
             array('jquery'),
583 583
             '2.1',
584 584
             true
@@ -587,16 +587,16 @@  discard block
 block discarded – undo
587 587
         // via: add_filter('FHEE_load_joyride', '__return_true' );
588 588
         if (apply_filters('FHEE_load_joyride', false)) {
589 589
             //joyride style
590
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
590
+            wp_register_style('joyride-css', EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css', array(), '2.1');
591 591
             wp_register_style(
592 592
                 'ee-joyride-css',
593
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
593
+                EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css',
594 594
                 array('joyride-css'),
595 595
                 EVENT_ESPRESSO_VERSION
596 596
             );
597 597
             wp_register_script(
598 598
                 'joyride-modernizr',
599
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
599
+                EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js',
600 600
                 array(),
601 601
                 '2.1',
602 602
                 true
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
             //joyride JS
605 605
             wp_register_script(
606 606
                 'jquery-joyride',
607
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
607
+                EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js',
608 608
                 array('jquery-cookie', 'joyride-modernizr'),
609 609
                 '2.1',
610 610
                 true
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
     public function get_persistent_admin_notices()
658 658
     {
659 659
         // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
-        $args       = array(
660
+        $args = array(
661 661
             'page'   => EE_Registry::instance()->REQ->is_set('page')
662 662
                 ? EE_Registry::instance()->REQ->get('page')
663 663
                 : '',
@@ -704,21 +704,21 @@  discard block
 block discarded – undo
704 704
                 ),
705 705
             )
706 706
         );
707
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
707
+        $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
708 708
             array('page' => 'espresso_registrations'),
709 709
             admin_url('admin.php')
710 710
         );
711
-        $items['registrations']['text']  = sprintf(
711
+        $items['registrations']['text'] = sprintf(
712 712
             _n('%s Registration', '%s Registrations', $registrations),
713 713
             number_format_i18n($registrations)
714 714
         );
715 715
         $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716 716
 
717
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
717
+        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718 718
 
719 719
         foreach ($items as $type => $item_properties) {
720 720
             $elements[] = sprintf(
721
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
721
+                '<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>',
722 722
                 $item_properties['url'],
723 723
                 $item_properties['title'],
724 724
                 $item_properties['text']
@@ -744,10 +744,10 @@  discard block
 block discarded – undo
744 744
         // check for date_format or time_format
745 745
         switch ($option) {
746 746
             case 'date_format':
747
-                $date_time_format = $value . ' ' . get_option('time_format');
747
+                $date_time_format = $value.' '.get_option('time_format');
748 748
                 break;
749 749
             case 'time_format':
750
-                $date_time_format = get_option('date_format') . ' ' . $value;
750
+                $date_time_format = get_option('date_format').' '.$value;
751 751
                 break;
752 752
             default:
753 753
                 $date_time_format = false;
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
 
771 771
 
772 772
                 foreach ($error_msg as $error) {
773
-                    $msg .= '<li>' . $error . '</li>';
773
+                    $msg .= '<li>'.$error.'</li>';
774 774
                 }
775 775
 
776 776
                 $msg .= '</ul></p><p>'
Please login to merge, or discard this patch.
Indentation   +848 added lines, -848 removed lines patch added patch discarded remove patch
@@ -15,395 +15,395 @@  discard block
 block discarded – undo
15 15
 final class EE_Admin implements InterminableInterface
16 16
 {
17 17
 
18
-    /**
19
-     * @access private
20
-     * @var EE_Admin $_instance
21
-     */
22
-    private static $_instance;
23
-
24
-
25
-    /**
26
-     *@ singleton method used to instantiate class object
27
-     *@ access public
28
-     *@ return class instance
29
-     *
30
-     * @throws \EE_Error
31
-     */
32
-    public static function instance()
33
-    {
34
-        // check if class object is instantiated
35
-        if (! self::$_instance instanceof EE_Admin) {
36
-            self::$_instance = new self();
37
-        }
38
-        return self::$_instance;
39
-    }
40
-
41
-
42
-    /**
43
-     * @return EE_Admin
44
-     * @throws EE_Error
45
-     */
46
-    public static function reset()
47
-    {
48
-        self::$_instance = null;
49
-        return self::instance();
50
-    }
51
-
52
-
53
-    /**
54
-     * class constructor
55
-     *
56
-     * @throws \EE_Error
57
-     */
58
-    protected function __construct()
59
-    {
60
-        // define global EE_Admin constants
61
-        $this->_define_all_constants();
62
-        // set autoloaders for our admin page classes based on included path information
63
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
64
-        // admin hooks
65
-        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
66
-        // load EE_Request_Handler early
67
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
68
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
69
-        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
70
-        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
71
-        add_action('admin_init', array($this, 'admin_init'), 100);
72
-        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
73
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
74
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
75
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
76
-        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
77
-
78
-        //reset Environment config (we only do this on admin page loads);
79
-        EE_Registry::instance()->CFG->environment->recheck_values();
80
-
81
-        do_action('AHEE__EE_Admin__loaded');
82
-    }
83
-
84
-
85
-    /**
86
-     * _define_all_constants
87
-     * define constants that are set globally for all admin pages
88
-     *
89
-     * @access private
90
-     * @return void
91
-     */
92
-    private function _define_all_constants()
93
-    {
94
-        if (! defined('EE_ADMIN_URL')) {
95
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
99
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100
-        }
101
-    }
102
-
103
-
104
-    /**
105
-     *    filter_plugin_actions - adds links to the Plugins page listing
106
-     *
107
-     * @access    public
108
-     * @param    array  $links
109
-     * @param    string $plugin
110
-     * @return    array
111
-     */
112
-    public function filter_plugin_actions($links, $plugin)
113
-    {
114
-        // set $main_file in stone
115
-        static $main_file;
116
-        // if $main_file is not set yet
117
-        if (! $main_file) {
118
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119
-        }
120
-        if ($plugin === $main_file) {
121
-            // compare current plugin to this one
122
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
123
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
124
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
125
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
126
-                                    . '</a>';
127
-                array_unshift($links, $maintenance_link);
128
-            } else {
129
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
130
-                                     . esc_html__('Settings', 'event_espresso')
131
-                                     . '</a>';
132
-                $events_link       = '<a href="admin.php?page=espresso_events">'
133
-                                     . esc_html__('Events', 'event_espresso')
134
-                                     . '</a>';
135
-                // add before other links
136
-                array_unshift($links, $org_settings_link, $events_link);
137
-            }
138
-        }
139
-        return $links;
140
-    }
141
-
142
-
143
-    /**
144
-     *    _get_request
145
-     *
146
-     * @access public
147
-     * @return void
148
-     * @throws EE_Error
149
-     * @throws ReflectionException
150
-     */
151
-    public function get_request()
152
-    {
153
-        EE_Registry::instance()->load_core('Request_Handler');
154
-        EE_Registry::instance()->load_core('CPT_Strategy');
155
-    }
156
-
157
-
158
-    /**
159
-     *    hide_admin_pages_except_maintenance_mode
160
-     *
161
-     * @access public
162
-     * @param array $admin_page_folder_names
163
-     * @return array
164
-     */
165
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166
-    {
167
-        return array(
168
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
171
-        );
172
-    }
173
-
174
-
175
-    /**
176
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
177
-     * EE_Front_Controller's init phases have run
178
-     *
179
-     * @access public
180
-     * @return void
181
-     * @throws EE_Error
182
-     * @throws ReflectionException
183
-     */
184
-    public function init()
185
-    {
186
-        //only enable most of the EE_Admin IF we're not in full maintenance mode
187
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
188
-            //ok so we want to enable the entire admin
189
-            add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
190
-            add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
191
-            add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
192
-            //at a glance dashboard widget
193
-            add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
194
-            //filter for get_edit_post_link used on comments for custom post types
195
-            add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196
-        }
197
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
198
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199
-            try {
200
-                //this loads the controller for the admin pages which will setup routing etc
201
-                EE_Registry::instance()->load_core('Admin_Page_Loader');
202
-            } catch (EE_Error $e) {
203
-                $e->get_error();
204
-            }
205
-        }
206
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
207
-        //make sure our CPTs and custom taxonomy metaboxes get shown for first time users
208
-        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
209
-        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
210
-        //exclude EE critical pages from all nav menus and wp_list_pages
211
-        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
212
-    }
213
-
214
-
215
-    /**
216
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
217
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
218
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
219
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
220
-     * normal property on the post_type object.  It's found ONLY in this particular context.
221
-     *
222
-     * @param  object $post_type WP post type object
223
-     * @return object            WP post type object
224
-     */
225
-    public function remove_pages_from_nav_menu($post_type)
226
-    {
227
-        //if this isn't the "pages" post type let's get out
228
-        if ($post_type->name !== 'page') {
229
-            return $post_type;
230
-        }
231
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
232
-
233
-        $post_type->_default_query = array(
234
-            'post__not_in' => $critical_pages,
235
-        );
236
-        return $post_type;
237
-    }
238
-
239
-
240
-    /**
241
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
242
-     * metaboxes get shown as well
243
-     *
244
-     * @access public
245
-     * @return void
246
-     */
247
-    public function enable_hidden_ee_nav_menu_metaboxes()
248
-    {
249
-        global $wp_meta_boxes, $pagenow;
250
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251
-            return;
252
-        }
253
-        $user = wp_get_current_user();
254
-        //has this been done yet?
255
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
256
-            return;
257
-        }
258
-
259
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
260
-        $initial_meta_boxes = apply_filters(
261
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
262
-            array(
263
-                'nav-menu-theme-locations',
264
-                'add-page',
265
-                'add-custom-links',
266
-                'add-category',
267
-                'add-espresso_events',
268
-                'add-espresso_venues',
269
-                'add-espresso_event_categories',
270
-                'add-espresso_venue_categories',
271
-                'add-post-type-post',
272
-                'add-post-type-page',
273
-            )
274
-        );
275
-
276
-        if (is_array($hidden_meta_boxes)) {
277
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
-                if (in_array($meta_box_id, $initial_meta_boxes)) {
279
-                    unset($hidden_meta_boxes[$key]);
280
-                }
281
-            }
282
-        }
283
-
284
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
-    }
287
-
288
-
289
-    /**
290
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
-     *
293
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
-     *         addons etc.
295
-     * @access public
296
-     * @return void
297
-     */
298
-    public function register_custom_nav_menu_boxes()
299
-    {
300
-        add_meta_box(
301
-            'add-extra-nav-menu-pages',
302
-            esc_html__('Event Espresso Pages', 'event_espresso'),
303
-            array($this, 'ee_cpt_archive_pages'),
304
-            'nav-menus',
305
-            'side',
306
-            'core'
307
-        );
308
-    }
309
-
310
-
311
-    /**
312
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
313
-     *
314
-     * @since   4.3.0
315
-     * @param string $link the original link generated by wp
316
-     * @param int    $id   post id
317
-     * @return string  the (maybe) modified link
318
-     */
319
-    public function modify_edit_post_link($link, $id)
320
-    {
321
-        if (! $post = get_post($id)) {
322
-            return $link;
323
-        }
324
-        if ($post->post_type === 'espresso_attendees') {
325
-            $query_args = array(
326
-                'action' => 'edit_attendee',
327
-                'post'   => $id,
328
-            );
329
-            return EEH_URL::add_query_args_and_nonce(
330
-                $query_args,
331
-                admin_url('admin.php?page=espresso_registrations')
332
-            );
333
-        }
334
-        return $link;
335
-    }
336
-
337
-
338
-    public function ee_cpt_archive_pages()
339
-    {
340
-        global $nav_menu_selected_id;
341
-
342
-        $db_fields   = false;
343
-        $walker      = new Walker_Nav_Menu_Checklist($db_fields);
344
-        $current_tab = 'event-archives';
345
-
346
-        /*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
18
+	/**
19
+	 * @access private
20
+	 * @var EE_Admin $_instance
21
+	 */
22
+	private static $_instance;
23
+
24
+
25
+	/**
26
+	 *@ singleton method used to instantiate class object
27
+	 *@ access public
28
+	 *@ return class instance
29
+	 *
30
+	 * @throws \EE_Error
31
+	 */
32
+	public static function instance()
33
+	{
34
+		// check if class object is instantiated
35
+		if (! self::$_instance instanceof EE_Admin) {
36
+			self::$_instance = new self();
37
+		}
38
+		return self::$_instance;
39
+	}
40
+
41
+
42
+	/**
43
+	 * @return EE_Admin
44
+	 * @throws EE_Error
45
+	 */
46
+	public static function reset()
47
+	{
48
+		self::$_instance = null;
49
+		return self::instance();
50
+	}
51
+
52
+
53
+	/**
54
+	 * class constructor
55
+	 *
56
+	 * @throws \EE_Error
57
+	 */
58
+	protected function __construct()
59
+	{
60
+		// define global EE_Admin constants
61
+		$this->_define_all_constants();
62
+		// set autoloaders for our admin page classes based on included path information
63
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
64
+		// admin hooks
65
+		add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
66
+		// load EE_Request_Handler early
67
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
68
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
69
+		add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
70
+		add_action('wp_loaded', array($this, 'wp_loaded'), 100);
71
+		add_action('admin_init', array($this, 'admin_init'), 100);
72
+		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
73
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
74
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
75
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
76
+		add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
77
+
78
+		//reset Environment config (we only do this on admin page loads);
79
+		EE_Registry::instance()->CFG->environment->recheck_values();
80
+
81
+		do_action('AHEE__EE_Admin__loaded');
82
+	}
83
+
84
+
85
+	/**
86
+	 * _define_all_constants
87
+	 * define constants that are set globally for all admin pages
88
+	 *
89
+	 * @access private
90
+	 * @return void
91
+	 */
92
+	private function _define_all_constants()
93
+	{
94
+		if (! defined('EE_ADMIN_URL')) {
95
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
96
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
97
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
98
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
99
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
100
+		}
101
+	}
102
+
103
+
104
+	/**
105
+	 *    filter_plugin_actions - adds links to the Plugins page listing
106
+	 *
107
+	 * @access    public
108
+	 * @param    array  $links
109
+	 * @param    string $plugin
110
+	 * @return    array
111
+	 */
112
+	public function filter_plugin_actions($links, $plugin)
113
+	{
114
+		// set $main_file in stone
115
+		static $main_file;
116
+		// if $main_file is not set yet
117
+		if (! $main_file) {
118
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
119
+		}
120
+		if ($plugin === $main_file) {
121
+			// compare current plugin to this one
122
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
123
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
124
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
125
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
126
+									. '</a>';
127
+				array_unshift($links, $maintenance_link);
128
+			} else {
129
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
130
+									 . esc_html__('Settings', 'event_espresso')
131
+									 . '</a>';
132
+				$events_link       = '<a href="admin.php?page=espresso_events">'
133
+									 . esc_html__('Events', 'event_espresso')
134
+									 . '</a>';
135
+				// add before other links
136
+				array_unshift($links, $org_settings_link, $events_link);
137
+			}
138
+		}
139
+		return $links;
140
+	}
141
+
142
+
143
+	/**
144
+	 *    _get_request
145
+	 *
146
+	 * @access public
147
+	 * @return void
148
+	 * @throws EE_Error
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function get_request()
152
+	{
153
+		EE_Registry::instance()->load_core('Request_Handler');
154
+		EE_Registry::instance()->load_core('CPT_Strategy');
155
+	}
156
+
157
+
158
+	/**
159
+	 *    hide_admin_pages_except_maintenance_mode
160
+	 *
161
+	 * @access public
162
+	 * @param array $admin_page_folder_names
163
+	 * @return array
164
+	 */
165
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
166
+	{
167
+		return array(
168
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
169
+			'about'       => EE_ADMIN_PAGES . 'about' . DS,
170
+			'support'     => EE_ADMIN_PAGES . 'support' . DS,
171
+		);
172
+	}
173
+
174
+
175
+	/**
176
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
177
+	 * EE_Front_Controller's init phases have run
178
+	 *
179
+	 * @access public
180
+	 * @return void
181
+	 * @throws EE_Error
182
+	 * @throws ReflectionException
183
+	 */
184
+	public function init()
185
+	{
186
+		//only enable most of the EE_Admin IF we're not in full maintenance mode
187
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
188
+			//ok so we want to enable the entire admin
189
+			add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismiss_ee_nag_notice_callback'));
190
+			add_action('admin_notices', array($this, 'get_persistent_admin_notices'), 9);
191
+			add_action('network_admin_notices', array($this, 'get_persistent_admin_notices'), 9);
192
+			//at a glance dashboard widget
193
+			add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
194
+			//filter for get_edit_post_link used on comments for custom post types
195
+			add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
196
+		}
197
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
198
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
199
+			try {
200
+				//this loads the controller for the admin pages which will setup routing etc
201
+				EE_Registry::instance()->load_core('Admin_Page_Loader');
202
+			} catch (EE_Error $e) {
203
+				$e->get_error();
204
+			}
205
+		}
206
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
207
+		//make sure our CPTs and custom taxonomy metaboxes get shown for first time users
208
+		add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
209
+		add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
210
+		//exclude EE critical pages from all nav menus and wp_list_pages
211
+		add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
212
+	}
213
+
214
+
215
+	/**
216
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
217
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
218
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
219
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
220
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
221
+	 *
222
+	 * @param  object $post_type WP post type object
223
+	 * @return object            WP post type object
224
+	 */
225
+	public function remove_pages_from_nav_menu($post_type)
226
+	{
227
+		//if this isn't the "pages" post type let's get out
228
+		if ($post_type->name !== 'page') {
229
+			return $post_type;
230
+		}
231
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
232
+
233
+		$post_type->_default_query = array(
234
+			'post__not_in' => $critical_pages,
235
+		);
236
+		return $post_type;
237
+	}
238
+
239
+
240
+	/**
241
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
242
+	 * metaboxes get shown as well
243
+	 *
244
+	 * @access public
245
+	 * @return void
246
+	 */
247
+	public function enable_hidden_ee_nav_menu_metaboxes()
248
+	{
249
+		global $wp_meta_boxes, $pagenow;
250
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
251
+			return;
252
+		}
253
+		$user = wp_get_current_user();
254
+		//has this been done yet?
255
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
256
+			return;
257
+		}
258
+
259
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
260
+		$initial_meta_boxes = apply_filters(
261
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
262
+			array(
263
+				'nav-menu-theme-locations',
264
+				'add-page',
265
+				'add-custom-links',
266
+				'add-category',
267
+				'add-espresso_events',
268
+				'add-espresso_venues',
269
+				'add-espresso_event_categories',
270
+				'add-espresso_venue_categories',
271
+				'add-post-type-post',
272
+				'add-post-type-page',
273
+			)
274
+		);
275
+
276
+		if (is_array($hidden_meta_boxes)) {
277
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
278
+				if (in_array($meta_box_id, $initial_meta_boxes)) {
279
+					unset($hidden_meta_boxes[$key]);
280
+				}
281
+			}
282
+		}
283
+
284
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
285
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
286
+	}
287
+
288
+
289
+	/**
290
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
291
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
292
+	 *
293
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
294
+	 *         addons etc.
295
+	 * @access public
296
+	 * @return void
297
+	 */
298
+	public function register_custom_nav_menu_boxes()
299
+	{
300
+		add_meta_box(
301
+			'add-extra-nav-menu-pages',
302
+			esc_html__('Event Espresso Pages', 'event_espresso'),
303
+			array($this, 'ee_cpt_archive_pages'),
304
+			'nav-menus',
305
+			'side',
306
+			'core'
307
+		);
308
+	}
309
+
310
+
311
+	/**
312
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
313
+	 *
314
+	 * @since   4.3.0
315
+	 * @param string $link the original link generated by wp
316
+	 * @param int    $id   post id
317
+	 * @return string  the (maybe) modified link
318
+	 */
319
+	public function modify_edit_post_link($link, $id)
320
+	{
321
+		if (! $post = get_post($id)) {
322
+			return $link;
323
+		}
324
+		if ($post->post_type === 'espresso_attendees') {
325
+			$query_args = array(
326
+				'action' => 'edit_attendee',
327
+				'post'   => $id,
328
+			);
329
+			return EEH_URL::add_query_args_and_nonce(
330
+				$query_args,
331
+				admin_url('admin.php?page=espresso_registrations')
332
+			);
333
+		}
334
+		return $link;
335
+	}
336
+
337
+
338
+	public function ee_cpt_archive_pages()
339
+	{
340
+		global $nav_menu_selected_id;
341
+
342
+		$db_fields   = false;
343
+		$walker      = new Walker_Nav_Menu_Checklist($db_fields);
344
+		$current_tab = 'event-archives';
345
+
346
+		/*if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
347 347
             $current_tab = 'search';
348 348
         }/**/
349 349
 
350
-        $removed_args = array(
351
-            'action',
352
-            'customlink-tab',
353
-            'edit-menu-item',
354
-            'menu-item',
355
-            'page-tab',
356
-            '_wpnonce',
357
-        );
350
+		$removed_args = array(
351
+			'action',
352
+			'customlink-tab',
353
+			'edit-menu-item',
354
+			'menu-item',
355
+			'page-tab',
356
+			'_wpnonce',
357
+		);
358 358
 
359
-        ?>
359
+		?>
360 360
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
361 361
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
362 362
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
363 363
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
364 364
                        href="<?php if ($nav_menu_selected_id) {
365
-                            echo esc_url(
366
-                                add_query_arg(
367
-                                    'extra-nav-menu-pages-tab',
368
-                                    'event-archives',
369
-                                    remove_query_arg($removed_args)
370
-                                )
371
-                            );
372
-                       } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
365
+							echo esc_url(
366
+								add_query_arg(
367
+									'extra-nav-menu-pages-tab',
368
+									'event-archives',
369
+									remove_query_arg($removed_args)
370
+								)
371
+							);
372
+					   } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
373 373
                         <?php _e('Event Archive Pages', 'event_espresso'); ?>
374 374
                     </a>
375 375
                 </li>
376 376
 
377 377
                 <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
378
-                echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
379
-                ?>">
378
+				echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
379
+				?>">
380 380
                     <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
381 381
                         <?php
382
-                        $pages          = $this->_get_extra_nav_menu_pages_items();
383
-                        $args['walker'] = $walker;
384
-                        echo walk_nav_menu_tree(
385
-                            array_map(
386
-                                array($this, '_setup_extra_nav_menu_pages_items'),
387
-                                $pages
388
-                            ),
389
-                            0,
390
-                            (object) $args
391
-                        );
392
-                        ?>
382
+						$pages          = $this->_get_extra_nav_menu_pages_items();
383
+						$args['walker'] = $walker;
384
+						echo walk_nav_menu_tree(
385
+							array_map(
386
+								array($this, '_setup_extra_nav_menu_pages_items'),
387
+								$pages
388
+							),
389
+							0,
390
+							(object) $args
391
+						);
392
+						?>
393 393
                     </ul>
394 394
                 </div><!-- /.tabs-panel -->
395 395
 
396 396
                 <p class="button-controls">
397 397
                 <span class="list-controls">
398 398
                     <a href="<?php
399
-                    echo esc_url(add_query_arg(
400
-                        array(
401
-                            'extra-nav-menu-pages-tab' => 'event-archives',
402
-                            'selectall'                => 1,
403
-                        ),
404
-                        remove_query_arg($removed_args)
405
-                    ));
406
-                    ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
399
+					echo esc_url(add_query_arg(
400
+						array(
401
+							'extra-nav-menu-pages-tab' => 'event-archives',
402
+							'selectall'                => 1,
403
+						),
404
+						remove_query_arg($removed_args)
405
+					));
406
+					?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
407 407
                 </span>
408 408
                 <span class="add-to-menu">
409 409
                     <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
@@ -416,485 +416,485 @@  discard block
 block discarded – undo
416 416
 
417 417
         </div><!-- /.posttypediv -->
418 418
         <?php
419
-    }
420
-
421
-
422
-    /**
423
-     * Returns an array of event archive nav items.
424
-     *
425
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
426
-     *        method we use for getting the extra nav menu items
427
-     * @return array
428
-     */
429
-    private function _get_extra_nav_menu_pages_items()
430
-    {
431
-        $menuitems[] = array(
432
-            'title'       => esc_html__('Event List', 'event_espresso'),
433
-            'url'         => get_post_type_archive_link('espresso_events'),
434
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
435
-        );
436
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
437
-    }
438
-
439
-
440
-    /**
441
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
442
-     * the properties and converts it to the menu item object.
443
-     *
444
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
445
-     * @param $menu_item_values
446
-     * @return stdClass
447
-     */
448
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
449
-    {
450
-        $menu_item = new stdClass();
451
-        $keys      = array(
452
-            'ID'               => 0,
453
-            'db_id'            => 0,
454
-            'menu_item_parent' => 0,
455
-            'object_id'        => -1,
456
-            'post_parent'      => 0,
457
-            'type'             => 'custom',
458
-            'object'           => '',
459
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
460
-            'title'            => '',
461
-            'url'              => '',
462
-            'target'           => '',
463
-            'attr_title'       => '',
464
-            'description'      => '',
465
-            'classes'          => array(),
466
-            'xfn'              => '',
467
-        );
468
-
469
-        foreach ($keys as $key => $value) {
470
-            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
471
-        }
472
-        return $menu_item;
473
-    }
474
-
475
-
476
-    /**
477
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
478
-     * EE_Admin_Page route is called.
479
-     *
480
-     * @return void
481
-     */
482
-    public function route_admin_request()
483
-    {
484
-    }
485
-
486
-
487
-    /**
488
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
489
-     *
490
-     * @return void
491
-     */
492
-    public function wp_loaded()
493
-    {
494
-    }
495
-
496
-
497
-    /**
498
-     * admin_init
499
-     *
500
-     * @access public
501
-     * @return void
502
-     * @throws EE_Error
503
-     * @throws ReflectionException
504
-     */
505
-    public function admin_init()
506
-    {
507
-
508
-        /**
509
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
510
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
511
-         * - check if doing post processing.
512
-         * - check if doing post processing of one of EE CPTs
513
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
514
-         */
515
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
516
-            EE_Registry::instance()->load_core('Register_CPTs');
517
-            EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
518
-        }
519
-
520
-
521
-        /**
522
-         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
523
-         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
524
-         * Pages" tab in the EE General Settings Admin page.
525
-         * This is for user-proofing.
526
-         */
527
-        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
528
-    }
529
-
530
-
531
-    /**
532
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
533
-     *
534
-     * @param string $output Current output.
535
-     * @return string
536
-     */
537
-    public function modify_dropdown_pages($output)
538
-    {
539
-        //get critical pages
540
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
541
-
542
-        //split current output by line break for easier parsing.
543
-        $split_output = explode("\n", $output);
544
-
545
-        //loop through to remove any critical pages from the array.
546
-        foreach ($critical_pages as $page_id) {
547
-            $needle = 'value="' . $page_id . '"';
548
-            foreach ($split_output as $key => $haystack) {
549
-                if (strpos($haystack, $needle) !== false) {
550
-                    unset($split_output[$key]);
551
-                }
552
-            }
553
-        }
554
-
555
-        //replace output with the new contents
556
-        return implode("\n", $split_output);
557
-    }
558
-
559
-
560
-    /**
561
-     * enqueue all admin scripts that need loaded for admin pages
562
-     *
563
-     * @access public
564
-     * @return void
565
-     */
566
-    public function enqueue_admin_scripts()
567
-    {
568
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
569
-        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
570
-        // calls.
571
-        wp_enqueue_script(
572
-            'ee-inject-wp',
573
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
574
-            array('jquery'),
575
-            EVENT_ESPRESSO_VERSION,
576
-            true
577
-        );
578
-        // register cookie script for future dependencies
579
-        wp_register_script(
580
-            'jquery-cookie',
581
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
582
-            array('jquery'),
583
-            '2.1',
584
-            true
585
-        );
586
-        //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
587
-        // via: add_filter('FHEE_load_joyride', '__return_true' );
588
-        if (apply_filters('FHEE_load_joyride', false)) {
589
-            //joyride style
590
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
591
-            wp_register_style(
592
-                'ee-joyride-css',
593
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
594
-                array('joyride-css'),
595
-                EVENT_ESPRESSO_VERSION
596
-            );
597
-            wp_register_script(
598
-                'joyride-modernizr',
599
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
600
-                array(),
601
-                '2.1',
602
-                true
603
-            );
604
-            //joyride JS
605
-            wp_register_script(
606
-                'jquery-joyride',
607
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
608
-                array('jquery-cookie', 'joyride-modernizr'),
609
-                '2.1',
610
-                true
611
-            );
612
-            // wanna go for a joyride?
613
-            wp_enqueue_style('ee-joyride-css');
614
-            wp_enqueue_script('jquery-joyride');
615
-        }
616
-    }
617
-
618
-
619
-    /**
620
-     *    display_admin_notices
621
-     *
622
-     * @access    public
623
-     * @return    string
624
-     */
625
-    public function display_admin_notices()
626
-    {
627
-        //add non-dismissable notice for datetime changes.  Only valid if EE version is greater than 4.9.46.p and the
628
-        // site does not have a timezone_string set.
629
-        if (EE_Register_Addon::_meets_min_core_version_requirement(
630
-                '4.9.46.p'
631
-            )
632
-            && ! get_option('timezone_string')
633
-        ) {
634
-            EE_Error::add_attention(
635
-                sprintf(
636
-                    esc_html__(
637
-                        '%1$sImportant%2$s: Please note some upcoming changes to dates and times in Event Espresso that may affect your website.  Read more about it %3$shere%4$s.',
638
-                        'event_espresso'
639
-                    ),
640
-                    '<strong>',
641
-                    '</strong>',
642
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
643
-                    '</a>'
644
-                )
645
-            );
646
-        }
647
-        echo EE_Error::get_notices();
648
-    }
649
-
650
-
651
-    /**
652
-     *    get_persistent_admin_notices
653
-     *
654
-     * @access    public
655
-     * @return        void
656
-     */
657
-    public function get_persistent_admin_notices()
658
-    {
659
-        // http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
-        $args       = array(
661
-            'page'   => EE_Registry::instance()->REQ->is_set('page')
662
-                ? EE_Registry::instance()->REQ->get('page')
663
-                : '',
664
-            'action' => EE_Registry::instance()->REQ->is_set('action')
665
-                ? EE_Registry::instance()->REQ->get('action')
666
-                : '',
667
-        );
668
-        $return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
669
-        echo EE_Error::get_persistent_admin_notices($return_url);
670
-    }
671
-
672
-
673
-    /**
674
-     *    dismiss_persistent_admin_notice
675
-     *
676
-     * @access    public
677
-     * @return        void
678
-     */
679
-    public function dismiss_ee_nag_notice_callback()
680
-    {
681
-        EE_Error::dismiss_persistent_admin_notice();
682
-    }
683
-
684
-
685
-    /**
686
-     * @param array $elements
687
-     * @return array
688
-     * @throws \EE_Error
689
-     */
690
-    public function dashboard_glance_items($elements)
691
-    {
692
-        $elements                        = is_array($elements) ? $elements : array($elements);
693
-        $events                          = EEM_Event::instance()->count();
694
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
695
-            array('page' => 'espresso_events'),
696
-            admin_url('admin.php')
697
-        );
698
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
699
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
700
-        $registrations                   = EEM_Registration::instance()->count(
701
-            array(
702
-                array(
703
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
704
-                ),
705
-            )
706
-        );
707
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
708
-            array('page' => 'espresso_registrations'),
709
-            admin_url('admin.php')
710
-        );
711
-        $items['registrations']['text']  = sprintf(
712
-            _n('%s Registration', '%s Registrations', $registrations),
713
-            number_format_i18n($registrations)
714
-        );
715
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716
-
717
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718
-
719
-        foreach ($items as $type => $item_properties) {
720
-            $elements[] = sprintf(
721
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
722
-                $item_properties['url'],
723
-                $item_properties['title'],
724
-                $item_properties['text']
725
-            );
726
-        }
727
-        return $elements;
728
-    }
729
-
730
-
731
-    /**
732
-     *    check_for_invalid_datetime_formats
733
-     *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
734
-     *    their selected format can be parsed by PHP
735
-     *
736
-     * @access    public
737
-     * @param    $value
738
-     * @param    $option
739
-     * @throws EE_Error
740
-     * @return    string
741
-     */
742
-    public function check_for_invalid_datetime_formats($value, $option)
743
-    {
744
-        // check for date_format or time_format
745
-        switch ($option) {
746
-            case 'date_format':
747
-                $date_time_format = $value . ' ' . get_option('time_format');
748
-                break;
749
-            case 'time_format':
750
-                $date_time_format = get_option('date_format') . ' ' . $value;
751
-                break;
752
-            default:
753
-                $date_time_format = false;
754
-        }
755
-        // do we have a date_time format to check ?
756
-        if ($date_time_format) {
757
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
758
-
759
-            if (is_array($error_msg)) {
760
-                $msg = '<p>'
761
-                       . sprintf(
762
-                           esc_html__(
763
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
764
-                               'event_espresso'
765
-                           ),
766
-                           date($date_time_format),
767
-                           $date_time_format
768
-                       )
769
-                       . '</p><p><ul>';
770
-
771
-
772
-                foreach ($error_msg as $error) {
773
-                    $msg .= '<li>' . $error . '</li>';
774
-                }
775
-
776
-                $msg .= '</ul></p><p>'
777
-                        . sprintf(
778
-                            esc_html__(
779
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
780
-                                'event_espresso'
781
-                            ),
782
-                            '<span style="color:#D54E21;">',
783
-                            '</span>'
784
-                        )
785
-                        . '</p>';
786
-
787
-                // trigger WP settings error
788
-                add_settings_error(
789
-                    'date_format',
790
-                    'date_format',
791
-                    $msg
792
-                );
793
-
794
-                // set format to something valid
795
-                switch ($option) {
796
-                    case 'date_format':
797
-                        $value = 'F j, Y';
798
-                        break;
799
-                    case 'time_format':
800
-                        $value = 'g:i a';
801
-                        break;
802
-                }
803
-            }
804
-        }
805
-        return $value;
806
-    }
807
-
808
-
809
-    /**
810
-     *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
811
-     *
812
-     * @access    public
813
-     * @param $content
814
-     * @return    string
815
-     */
816
-    public function its_eSpresso($content)
817
-    {
818
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
819
-    }
820
-
821
-
822
-    /**
823
-     *    espresso_admin_footer
824
-     *
825
-     * @access    public
826
-     * @return    string
827
-     */
828
-    public function espresso_admin_footer()
829
-    {
830
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
831
-    }
832
-
833
-
834
-    /**
835
-     * static method for registering ee admin page.
836
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
837
-     *
838
-     * @since      4.3.0
839
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
840
-     * @see        EE_Register_Admin_Page::register()
841
-     * @param       $page_basename
842
-     * @param       $page_path
843
-     * @param array $config
844
-     * @return void
845
-     * @throws EE_Error
846
-     */
847
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
848
-    {
849
-        EE_Error::doing_it_wrong(
850
-            __METHOD__,
851
-            sprintf(
852
-                esc_html__(
853
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
854
-                    'event_espresso'
855
-                ),
856
-                $page_basename
857
-            ),
858
-            '4.3'
859
-        );
860
-        if (class_exists('EE_Register_Admin_Page')) {
861
-            $config['page_path'] = $page_path;
862
-        }
863
-        EE_Register_Admin_Page::register($page_basename, $config);
864
-    }
865
-
866
-
867
-    /**
868
-     * @deprecated 4.8.41
869
-     * @access     public
870
-     * @param  int      $post_ID
871
-     * @param  \WP_Post $post
872
-     * @return void
873
-     */
874
-    public static function parse_post_content_on_save($post_ID, $post)
875
-    {
876
-        EE_Error::doing_it_wrong(
877
-            __METHOD__,
878
-            esc_html__('Usage is deprecated', 'event_espresso'),
879
-            '4.8.41'
880
-        );
881
-    }
882
-
883
-
884
-    /**
885
-     * @deprecated 4.8.41
886
-     * @access     public
887
-     * @param  $option
888
-     * @param  $old_value
889
-     * @param  $value
890
-     * @return void
891
-     */
892
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
893
-    {
894
-        EE_Error::doing_it_wrong(
895
-            __METHOD__,
896
-            esc_html__('Usage is deprecated', 'event_espresso'),
897
-            '4.8.41'
898
-        );
899
-    }
419
+	}
420
+
421
+
422
+	/**
423
+	 * Returns an array of event archive nav items.
424
+	 *
425
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
426
+	 *        method we use for getting the extra nav menu items
427
+	 * @return array
428
+	 */
429
+	private function _get_extra_nav_menu_pages_items()
430
+	{
431
+		$menuitems[] = array(
432
+			'title'       => esc_html__('Event List', 'event_espresso'),
433
+			'url'         => get_post_type_archive_link('espresso_events'),
434
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
435
+		);
436
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
437
+	}
438
+
439
+
440
+	/**
441
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
442
+	 * the properties and converts it to the menu item object.
443
+	 *
444
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
445
+	 * @param $menu_item_values
446
+	 * @return stdClass
447
+	 */
448
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
449
+	{
450
+		$menu_item = new stdClass();
451
+		$keys      = array(
452
+			'ID'               => 0,
453
+			'db_id'            => 0,
454
+			'menu_item_parent' => 0,
455
+			'object_id'        => -1,
456
+			'post_parent'      => 0,
457
+			'type'             => 'custom',
458
+			'object'           => '',
459
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
460
+			'title'            => '',
461
+			'url'              => '',
462
+			'target'           => '',
463
+			'attr_title'       => '',
464
+			'description'      => '',
465
+			'classes'          => array(),
466
+			'xfn'              => '',
467
+		);
468
+
469
+		foreach ($keys as $key => $value) {
470
+			$menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
471
+		}
472
+		return $menu_item;
473
+	}
474
+
475
+
476
+	/**
477
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
478
+	 * EE_Admin_Page route is called.
479
+	 *
480
+	 * @return void
481
+	 */
482
+	public function route_admin_request()
483
+	{
484
+	}
485
+
486
+
487
+	/**
488
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
489
+	 *
490
+	 * @return void
491
+	 */
492
+	public function wp_loaded()
493
+	{
494
+	}
495
+
496
+
497
+	/**
498
+	 * admin_init
499
+	 *
500
+	 * @access public
501
+	 * @return void
502
+	 * @throws EE_Error
503
+	 * @throws ReflectionException
504
+	 */
505
+	public function admin_init()
506
+	{
507
+
508
+		/**
509
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
510
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
511
+		 * - check if doing post processing.
512
+		 * - check if doing post processing of one of EE CPTs
513
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
514
+		 */
515
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
516
+			EE_Registry::instance()->load_core('Register_CPTs');
517
+			EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
518
+		}
519
+
520
+
521
+		/**
522
+		 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
523
+		 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
524
+		 * Pages" tab in the EE General Settings Admin page.
525
+		 * This is for user-proofing.
526
+		 */
527
+		add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
528
+	}
529
+
530
+
531
+	/**
532
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
533
+	 *
534
+	 * @param string $output Current output.
535
+	 * @return string
536
+	 */
537
+	public function modify_dropdown_pages($output)
538
+	{
539
+		//get critical pages
540
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
541
+
542
+		//split current output by line break for easier parsing.
543
+		$split_output = explode("\n", $output);
544
+
545
+		//loop through to remove any critical pages from the array.
546
+		foreach ($critical_pages as $page_id) {
547
+			$needle = 'value="' . $page_id . '"';
548
+			foreach ($split_output as $key => $haystack) {
549
+				if (strpos($haystack, $needle) !== false) {
550
+					unset($split_output[$key]);
551
+				}
552
+			}
553
+		}
554
+
555
+		//replace output with the new contents
556
+		return implode("\n", $split_output);
557
+	}
558
+
559
+
560
+	/**
561
+	 * enqueue all admin scripts that need loaded for admin pages
562
+	 *
563
+	 * @access public
564
+	 * @return void
565
+	 */
566
+	public function enqueue_admin_scripts()
567
+	{
568
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
569
+		// Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
570
+		// calls.
571
+		wp_enqueue_script(
572
+			'ee-inject-wp',
573
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
574
+			array('jquery'),
575
+			EVENT_ESPRESSO_VERSION,
576
+			true
577
+		);
578
+		// register cookie script for future dependencies
579
+		wp_register_script(
580
+			'jquery-cookie',
581
+			EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
582
+			array('jquery'),
583
+			'2.1',
584
+			true
585
+		);
586
+		//joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
587
+		// via: add_filter('FHEE_load_joyride', '__return_true' );
588
+		if (apply_filters('FHEE_load_joyride', false)) {
589
+			//joyride style
590
+			wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
591
+			wp_register_style(
592
+				'ee-joyride-css',
593
+				EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
594
+				array('joyride-css'),
595
+				EVENT_ESPRESSO_VERSION
596
+			);
597
+			wp_register_script(
598
+				'joyride-modernizr',
599
+				EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
600
+				array(),
601
+				'2.1',
602
+				true
603
+			);
604
+			//joyride JS
605
+			wp_register_script(
606
+				'jquery-joyride',
607
+				EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
608
+				array('jquery-cookie', 'joyride-modernizr'),
609
+				'2.1',
610
+				true
611
+			);
612
+			// wanna go for a joyride?
613
+			wp_enqueue_style('ee-joyride-css');
614
+			wp_enqueue_script('jquery-joyride');
615
+		}
616
+	}
617
+
618
+
619
+	/**
620
+	 *    display_admin_notices
621
+	 *
622
+	 * @access    public
623
+	 * @return    string
624
+	 */
625
+	public function display_admin_notices()
626
+	{
627
+		//add non-dismissable notice for datetime changes.  Only valid if EE version is greater than 4.9.46.p and the
628
+		// site does not have a timezone_string set.
629
+		if (EE_Register_Addon::_meets_min_core_version_requirement(
630
+				'4.9.46.p'
631
+			)
632
+			&& ! get_option('timezone_string')
633
+		) {
634
+			EE_Error::add_attention(
635
+				sprintf(
636
+					esc_html__(
637
+						'%1$sImportant%2$s: Please note some upcoming changes to dates and times in Event Espresso that may affect your website.  Read more about it %3$shere%4$s.',
638
+						'event_espresso'
639
+					),
640
+					'<strong>',
641
+					'</strong>',
642
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
643
+					'</a>'
644
+				)
645
+			);
646
+		}
647
+		echo EE_Error::get_notices();
648
+	}
649
+
650
+
651
+	/**
652
+	 *    get_persistent_admin_notices
653
+	 *
654
+	 * @access    public
655
+	 * @return        void
656
+	 */
657
+	public function get_persistent_admin_notices()
658
+	{
659
+		// http://www.example.com/wp-admin/admin.php?page=espresso_general_settings&action=critical_pages&critical_pages_nonce=2831ce0f30
660
+		$args       = array(
661
+			'page'   => EE_Registry::instance()->REQ->is_set('page')
662
+				? EE_Registry::instance()->REQ->get('page')
663
+				: '',
664
+			'action' => EE_Registry::instance()->REQ->is_set('action')
665
+				? EE_Registry::instance()->REQ->get('action')
666
+				: '',
667
+		);
668
+		$return_url = EE_Admin_Page::add_query_args_and_nonce($args, EE_ADMIN_URL);
669
+		echo EE_Error::get_persistent_admin_notices($return_url);
670
+	}
671
+
672
+
673
+	/**
674
+	 *    dismiss_persistent_admin_notice
675
+	 *
676
+	 * @access    public
677
+	 * @return        void
678
+	 */
679
+	public function dismiss_ee_nag_notice_callback()
680
+	{
681
+		EE_Error::dismiss_persistent_admin_notice();
682
+	}
683
+
684
+
685
+	/**
686
+	 * @param array $elements
687
+	 * @return array
688
+	 * @throws \EE_Error
689
+	 */
690
+	public function dashboard_glance_items($elements)
691
+	{
692
+		$elements                        = is_array($elements) ? $elements : array($elements);
693
+		$events                          = EEM_Event::instance()->count();
694
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
695
+			array('page' => 'espresso_events'),
696
+			admin_url('admin.php')
697
+		);
698
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
699
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
700
+		$registrations                   = EEM_Registration::instance()->count(
701
+			array(
702
+				array(
703
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
704
+				),
705
+			)
706
+		);
707
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
708
+			array('page' => 'espresso_registrations'),
709
+			admin_url('admin.php')
710
+		);
711
+		$items['registrations']['text']  = sprintf(
712
+			_n('%s Registration', '%s Registrations', $registrations),
713
+			number_format_i18n($registrations)
714
+		);
715
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
716
+
717
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
718
+
719
+		foreach ($items as $type => $item_properties) {
720
+			$elements[] = sprintf(
721
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
722
+				$item_properties['url'],
723
+				$item_properties['title'],
724
+				$item_properties['text']
725
+			);
726
+		}
727
+		return $elements;
728
+	}
729
+
730
+
731
+	/**
732
+	 *    check_for_invalid_datetime_formats
733
+	 *    if an admin changes their date or time format settings on the WP General Settings admin page, verify that
734
+	 *    their selected format can be parsed by PHP
735
+	 *
736
+	 * @access    public
737
+	 * @param    $value
738
+	 * @param    $option
739
+	 * @throws EE_Error
740
+	 * @return    string
741
+	 */
742
+	public function check_for_invalid_datetime_formats($value, $option)
743
+	{
744
+		// check for date_format or time_format
745
+		switch ($option) {
746
+			case 'date_format':
747
+				$date_time_format = $value . ' ' . get_option('time_format');
748
+				break;
749
+			case 'time_format':
750
+				$date_time_format = get_option('date_format') . ' ' . $value;
751
+				break;
752
+			default:
753
+				$date_time_format = false;
754
+		}
755
+		// do we have a date_time format to check ?
756
+		if ($date_time_format) {
757
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
758
+
759
+			if (is_array($error_msg)) {
760
+				$msg = '<p>'
761
+					   . sprintf(
762
+						   esc_html__(
763
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
764
+							   'event_espresso'
765
+						   ),
766
+						   date($date_time_format),
767
+						   $date_time_format
768
+					   )
769
+					   . '</p><p><ul>';
770
+
771
+
772
+				foreach ($error_msg as $error) {
773
+					$msg .= '<li>' . $error . '</li>';
774
+				}
775
+
776
+				$msg .= '</ul></p><p>'
777
+						. sprintf(
778
+							esc_html__(
779
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
780
+								'event_espresso'
781
+							),
782
+							'<span style="color:#D54E21;">',
783
+							'</span>'
784
+						)
785
+						. '</p>';
786
+
787
+				// trigger WP settings error
788
+				add_settings_error(
789
+					'date_format',
790
+					'date_format',
791
+					$msg
792
+				);
793
+
794
+				// set format to something valid
795
+				switch ($option) {
796
+					case 'date_format':
797
+						$value = 'F j, Y';
798
+						break;
799
+					case 'time_format':
800
+						$value = 'g:i a';
801
+						break;
802
+				}
803
+			}
804
+		}
805
+		return $value;
806
+	}
807
+
808
+
809
+	/**
810
+	 *    its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
811
+	 *
812
+	 * @access    public
813
+	 * @param $content
814
+	 * @return    string
815
+	 */
816
+	public function its_eSpresso($content)
817
+	{
818
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
819
+	}
820
+
821
+
822
+	/**
823
+	 *    espresso_admin_footer
824
+	 *
825
+	 * @access    public
826
+	 * @return    string
827
+	 */
828
+	public function espresso_admin_footer()
829
+	{
830
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
831
+	}
832
+
833
+
834
+	/**
835
+	 * static method for registering ee admin page.
836
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
837
+	 *
838
+	 * @since      4.3.0
839
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
840
+	 * @see        EE_Register_Admin_Page::register()
841
+	 * @param       $page_basename
842
+	 * @param       $page_path
843
+	 * @param array $config
844
+	 * @return void
845
+	 * @throws EE_Error
846
+	 */
847
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
848
+	{
849
+		EE_Error::doing_it_wrong(
850
+			__METHOD__,
851
+			sprintf(
852
+				esc_html__(
853
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
854
+					'event_espresso'
855
+				),
856
+				$page_basename
857
+			),
858
+			'4.3'
859
+		);
860
+		if (class_exists('EE_Register_Admin_Page')) {
861
+			$config['page_path'] = $page_path;
862
+		}
863
+		EE_Register_Admin_Page::register($page_basename, $config);
864
+	}
865
+
866
+
867
+	/**
868
+	 * @deprecated 4.8.41
869
+	 * @access     public
870
+	 * @param  int      $post_ID
871
+	 * @param  \WP_Post $post
872
+	 * @return void
873
+	 */
874
+	public static function parse_post_content_on_save($post_ID, $post)
875
+	{
876
+		EE_Error::doing_it_wrong(
877
+			__METHOD__,
878
+			esc_html__('Usage is deprecated', 'event_espresso'),
879
+			'4.8.41'
880
+		);
881
+	}
882
+
883
+
884
+	/**
885
+	 * @deprecated 4.8.41
886
+	 * @access     public
887
+	 * @param  $option
888
+	 * @param  $old_value
889
+	 * @param  $value
890
+	 * @return void
891
+	 */
892
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
893
+	{
894
+		EE_Error::doing_it_wrong(
895
+			__METHOD__,
896
+			esc_html__('Usage is deprecated', 'event_espresso'),
897
+			'4.8.41'
898
+		);
899
+	}
900 900
 }
Please login to merge, or discard this patch.
core/EE_Request_Handler.core.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 
276 276
 
277 277
     /**
278
-     * @param $string
278
+     * @param string $string
279 279
      * @return void
280 280
      */
281 281
     public function add_output($string)
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
327 327
 
328 328
 
329 329
     /**
330
-     * @return    mixed
330
+     * @return    boolean
331 331
      */
332 332
     public function is_espresso_page()
333 333
     {
@@ -389,7 +389,7 @@  discard block
 block discarded – undo
389 389
     /**
390 390
      * remove param
391 391
      *
392
-     * @param $key
392
+     * @param string $key
393 393
      * @return    void
394 394
      */
395 395
     public function un_set($key)
Please login to merge, or discard this patch.
Indentation   +383 added lines, -383 removed lines patch added patch discarded remove patch
@@ -13,389 +13,389 @@
 block discarded – undo
13 13
 final class EE_Request_Handler implements InterminableInterface
14 14
 {
15 15
 
16
-    /**
17
-     * @var EE_Request $request
18
-     */
19
-    private $request;
20
-
21
-    /**
22
-     * @var array $_notice
23
-     */
24
-    private $_notice = array();
25
-
26
-    /**
27
-     * rendered output to be returned to WP
28
-     *
29
-     * @var string $_output
30
-     */
31
-    private $_output = '';
32
-
33
-    /**
34
-     * whether current request is via AJAX
35
-     *
36
-     * @var boolean $ajax
37
-     */
38
-    public $ajax = false;
39
-
40
-    /**
41
-     * whether current request is via AJAX from the frontend of the site
42
-     *
43
-     * @var boolean $front_ajax
44
-     */
45
-    public $front_ajax = false;
46
-
47
-
48
-
49
-    /**
50
-     * @param  EE_Request $request
51
-     */
52
-    public function __construct(EE_Request $request)
53
-    {
54
-        $this->request = $request;
55
-        $this->ajax = $this->request->ajax;
56
-        $this->front_ajax = $this->request->front_ajax;
57
-        do_action('AHEE__EE_Request_Handler__construct__complete');
58
-    }
59
-
60
-
61
-
62
-    /**
63
-     * @param WP $wp
64
-     * @return void
65
-     * @throws EE_Error
66
-     * @throws ReflectionException
67
-     */
68
-    public function parse_request($wp = null)
69
-    {
70
-        //if somebody forgot to provide us with WP, that's ok because its global
71
-        if (! $wp instanceof WP) {
72
-            global $wp;
73
-        }
74
-        $this->set_request_vars($wp);
75
-    }
76
-
77
-
78
-
79
-    /**
80
-     * @param WP $wp
81
-     * @return void
82
-     * @throws EE_Error
83
-     * @throws ReflectionException
84
-     */
85
-    public function set_request_vars($wp = null)
86
-    {
87
-        if (! is_admin()) {
88
-            // set request post_id
89
-            $this->request->set('post_id', $this->get_post_id_from_request($wp));
90
-            // set request post name
91
-            $this->request->set('post_name', $this->get_post_name_from_request($wp));
92
-            // set request post_type
93
-            $this->request->set('post_type', $this->get_post_type_from_request($wp));
94
-            // true or false ? is this page being used by EE ?
95
-            $this->set_espresso_page();
96
-        }
97
-    }
98
-
99
-
100
-
101
-    /**
102
-     * @param WP $wp
103
-     * @return int
104
-     */
105
-    public function get_post_id_from_request($wp = null)
106
-    {
107
-        if (! $wp instanceof WP) {
108
-            global $wp;
109
-        }
110
-        $post_id = null;
111
-        if (isset($wp->query_vars['p'])) {
112
-            $post_id = $wp->query_vars['p'];
113
-        }
114
-        if (! $post_id && isset($wp->query_vars['page_id'])) {
115
-            $post_id = $wp->query_vars['page_id'];
116
-        }
117
-        if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
118
-            $post_id = basename($wp->request);
119
-        }
120
-        return $post_id;
121
-    }
122
-
123
-
124
-
125
-    /**
126
-     * @param WP $wp
127
-     * @return string
128
-     */
129
-    public function get_post_name_from_request($wp = null)
130
-    {
131
-        if (! $wp instanceof WP) {
132
-            global $wp;
133
-        }
134
-        $post_name = null;
135
-        if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
136
-            $post_name = $wp->query_vars['name'];
137
-        }
138
-        if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
139
-            $post_name = $wp->query_vars['pagename'];
140
-        }
141
-        if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
142
-            $possible_post_name = basename($wp->request);
143
-            if (! is_numeric($possible_post_name)) {
144
-                /** @type WPDB $wpdb */
145
-                global $wpdb;
146
-                $SQL =
147
-                    "SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
148
-                $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
149
-                if ($possible_post_name) {
150
-                    $post_name = $possible_post_name;
151
-                }
152
-            }
153
-        }
154
-        if (! $post_name && $this->get('post_id')) {
155
-            /** @type WPDB $wpdb */
156
-            global $wpdb;
157
-            $SQL =
158
-                "SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
159
-            $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
160
-            if ($possible_post_name) {
161
-                $post_name = $possible_post_name;
162
-            }
163
-        }
164
-        return $post_name;
165
-    }
166
-
167
-
168
-
169
-    /**
170
-     * @param WP $wp
171
-     * @return mixed
172
-     */
173
-    public function get_post_type_from_request($wp = null)
174
-    {
175
-        if (! $wp instanceof WP) {
176
-            global $wp;
177
-        }
178
-        return isset($wp->query_vars['post_type'])
179
-            ? $wp->query_vars['post_type']
180
-            : null;
181
-    }
182
-
183
-
184
-
185
-    /**
186
-     * Just a helper method for getting the url for the displayed page.
187
-     *
188
-     * @param  WP $wp
189
-     * @return string
190
-     */
191
-    public function get_current_page_permalink($wp = null)
192
-    {
193
-        $post_id = $this->get_post_id_from_request($wp);
194
-        if ($post_id) {
195
-            $current_page_permalink = get_permalink($post_id);
196
-        } else {
197
-            if (! $wp instanceof WP) {
198
-                global $wp;
199
-            }
200
-            if ($wp->request) {
201
-                $current_page_permalink = site_url($wp->request);
202
-            } else {
203
-                $current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
204
-            }
205
-        }
206
-        return $current_page_permalink;
207
-    }
208
-
209
-
210
-
211
-    /**
212
-     * @return bool
213
-     * @throws EE_Error
214
-     * @throws ReflectionException
215
-     */
216
-    public function test_for_espresso_page()
217
-    {
218
-        global $wp;
219
-        /** @type EE_CPT_Strategy $EE_CPT_Strategy */
220
-        $EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
221
-        $espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
222
-        if (is_array($espresso_CPT_taxonomies)) {
223
-            foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
224
-                if (isset($wp->query_vars, $wp->query_vars[$espresso_CPT_taxonomy])) {
225
-                    return true;
226
-                }
227
-            }
228
-        }
229
-        // load espresso CPT endpoints
230
-        $espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
231
-        $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
232
-        $post_types = (array)$this->get('post_type');
233
-        foreach ($post_types as $post_type) {
234
-            // was a post name passed ?
235
-            if (isset($post_type_CPT_endpoints[$post_type])) {
236
-                // kk we know this is an espresso page, but is it a specific post ?
237
-                if (! $this->get('post_name')) {
238
-                    // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
239
-                    $post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
240
-                        ? $post_type_CPT_endpoints[$this->get('post_type')]
241
-                        : '';
242
-                    // if the post type matches on of our then set the endpoint
243
-                    if ($post_name) {
244
-                        $this->set('post_name', $post_name);
245
-                    }
246
-                }
247
-                return true;
248
-            }
249
-        }
250
-        return false;
251
-    }
252
-    /**
253
-     * @param $key
254
-     * @param $value
255
-     * @return    void
256
-     */
257
-    public function set_notice($key, $value)
258
-    {
259
-        $this->_notice[$key] = $value;
260
-    }
261
-
262
-
263
-
264
-    /**
265
-     * @param $key
266
-     * @return    mixed
267
-     */
268
-    public function get_notice($key)
269
-    {
270
-        return isset($this->_notice[$key])
271
-            ? $this->_notice[$key]
272
-            : null;
273
-    }
274
-
275
-
276
-
277
-    /**
278
-     * @param $string
279
-     * @return void
280
-     */
281
-    public function add_output($string)
282
-    {
283
-        $this->_output .= $string;
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * @return string
290
-     */
291
-    public function get_output()
292
-    {
293
-        return $this->_output;
294
-    }
295
-
296
-
297
-
298
-    /**
299
-     * @param $item
300
-     * @param $key
301
-     */
302
-    public function sanitize_text_field_for_array_walk(&$item, &$key)
303
-    {
304
-        $item = strpos($item, 'email') !== false
305
-            ? sanitize_email($item)
306
-            : sanitize_text_field($item);
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * @param null|bool $value
313
-     * @return void
314
-     * @throws EE_Error
315
-     * @throws ReflectionException
316
-     */
317
-    public function set_espresso_page($value = null)
318
-    {
319
-        $this->request->set(
320
-            'is_espresso_page',
321
-            ! empty($value)
322
-                ? $value
323
-                : $this->test_for_espresso_page()
324
-        );
325
-    }
326
-
327
-
328
-
329
-    /**
330
-     * @return    mixed
331
-     */
332
-    public function is_espresso_page()
333
-    {
334
-        return $this->request->is_set('is_espresso_page');
335
-    }
336
-
337
-
338
-
339
-    /**
340
-     * returns contents of $_REQUEST
341
-     *
342
-     * @return array
343
-     */
344
-    public function params()
345
-    {
346
-        return $this->request->params();
347
-    }
348
-
349
-
350
-
351
-    /**
352
-     * @param      $key
353
-     * @param      $value
354
-     * @param bool $override_ee
355
-     * @return    void
356
-     */
357
-    public function set($key, $value, $override_ee = false)
358
-    {
359
-        $this->request->set($key, $value, $override_ee);
360
-    }
361
-
362
-
363
-
364
-    /**
365
-     * @param      $key
366
-     * @param null $default
367
-     * @return    mixed
368
-     */
369
-    public function get($key, $default = null)
370
-    {
371
-        return $this->request->get($key, $default);
372
-    }
373
-
374
-
375
-
376
-    /**
377
-     * check if param exists
378
-     *
379
-     * @param $key
380
-     * @return    boolean
381
-     */
382
-    public function is_set($key)
383
-    {
384
-        return $this->request->is_set($key);
385
-    }
386
-
387
-
388
-
389
-    /**
390
-     * remove param
391
-     *
392
-     * @param $key
393
-     * @return    void
394
-     */
395
-    public function un_set($key)
396
-    {
397
-        $this->request->un_set($key);
398
-    }
16
+	/**
17
+	 * @var EE_Request $request
18
+	 */
19
+	private $request;
20
+
21
+	/**
22
+	 * @var array $_notice
23
+	 */
24
+	private $_notice = array();
25
+
26
+	/**
27
+	 * rendered output to be returned to WP
28
+	 *
29
+	 * @var string $_output
30
+	 */
31
+	private $_output = '';
32
+
33
+	/**
34
+	 * whether current request is via AJAX
35
+	 *
36
+	 * @var boolean $ajax
37
+	 */
38
+	public $ajax = false;
39
+
40
+	/**
41
+	 * whether current request is via AJAX from the frontend of the site
42
+	 *
43
+	 * @var boolean $front_ajax
44
+	 */
45
+	public $front_ajax = false;
46
+
47
+
48
+
49
+	/**
50
+	 * @param  EE_Request $request
51
+	 */
52
+	public function __construct(EE_Request $request)
53
+	{
54
+		$this->request = $request;
55
+		$this->ajax = $this->request->ajax;
56
+		$this->front_ajax = $this->request->front_ajax;
57
+		do_action('AHEE__EE_Request_Handler__construct__complete');
58
+	}
59
+
60
+
61
+
62
+	/**
63
+	 * @param WP $wp
64
+	 * @return void
65
+	 * @throws EE_Error
66
+	 * @throws ReflectionException
67
+	 */
68
+	public function parse_request($wp = null)
69
+	{
70
+		//if somebody forgot to provide us with WP, that's ok because its global
71
+		if (! $wp instanceof WP) {
72
+			global $wp;
73
+		}
74
+		$this->set_request_vars($wp);
75
+	}
76
+
77
+
78
+
79
+	/**
80
+	 * @param WP $wp
81
+	 * @return void
82
+	 * @throws EE_Error
83
+	 * @throws ReflectionException
84
+	 */
85
+	public function set_request_vars($wp = null)
86
+	{
87
+		if (! is_admin()) {
88
+			// set request post_id
89
+			$this->request->set('post_id', $this->get_post_id_from_request($wp));
90
+			// set request post name
91
+			$this->request->set('post_name', $this->get_post_name_from_request($wp));
92
+			// set request post_type
93
+			$this->request->set('post_type', $this->get_post_type_from_request($wp));
94
+			// true or false ? is this page being used by EE ?
95
+			$this->set_espresso_page();
96
+		}
97
+	}
98
+
99
+
100
+
101
+	/**
102
+	 * @param WP $wp
103
+	 * @return int
104
+	 */
105
+	public function get_post_id_from_request($wp = null)
106
+	{
107
+		if (! $wp instanceof WP) {
108
+			global $wp;
109
+		}
110
+		$post_id = null;
111
+		if (isset($wp->query_vars['p'])) {
112
+			$post_id = $wp->query_vars['p'];
113
+		}
114
+		if (! $post_id && isset($wp->query_vars['page_id'])) {
115
+			$post_id = $wp->query_vars['page_id'];
116
+		}
117
+		if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
118
+			$post_id = basename($wp->request);
119
+		}
120
+		return $post_id;
121
+	}
122
+
123
+
124
+
125
+	/**
126
+	 * @param WP $wp
127
+	 * @return string
128
+	 */
129
+	public function get_post_name_from_request($wp = null)
130
+	{
131
+		if (! $wp instanceof WP) {
132
+			global $wp;
133
+		}
134
+		$post_name = null;
135
+		if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
136
+			$post_name = $wp->query_vars['name'];
137
+		}
138
+		if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
139
+			$post_name = $wp->query_vars['pagename'];
140
+		}
141
+		if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
142
+			$possible_post_name = basename($wp->request);
143
+			if (! is_numeric($possible_post_name)) {
144
+				/** @type WPDB $wpdb */
145
+				global $wpdb;
146
+				$SQL =
147
+					"SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
148
+				$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
149
+				if ($possible_post_name) {
150
+					$post_name = $possible_post_name;
151
+				}
152
+			}
153
+		}
154
+		if (! $post_name && $this->get('post_id')) {
155
+			/** @type WPDB $wpdb */
156
+			global $wpdb;
157
+			$SQL =
158
+				"SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
159
+			$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
160
+			if ($possible_post_name) {
161
+				$post_name = $possible_post_name;
162
+			}
163
+		}
164
+		return $post_name;
165
+	}
166
+
167
+
168
+
169
+	/**
170
+	 * @param WP $wp
171
+	 * @return mixed
172
+	 */
173
+	public function get_post_type_from_request($wp = null)
174
+	{
175
+		if (! $wp instanceof WP) {
176
+			global $wp;
177
+		}
178
+		return isset($wp->query_vars['post_type'])
179
+			? $wp->query_vars['post_type']
180
+			: null;
181
+	}
182
+
183
+
184
+
185
+	/**
186
+	 * Just a helper method for getting the url for the displayed page.
187
+	 *
188
+	 * @param  WP $wp
189
+	 * @return string
190
+	 */
191
+	public function get_current_page_permalink($wp = null)
192
+	{
193
+		$post_id = $this->get_post_id_from_request($wp);
194
+		if ($post_id) {
195
+			$current_page_permalink = get_permalink($post_id);
196
+		} else {
197
+			if (! $wp instanceof WP) {
198
+				global $wp;
199
+			}
200
+			if ($wp->request) {
201
+				$current_page_permalink = site_url($wp->request);
202
+			} else {
203
+				$current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
204
+			}
205
+		}
206
+		return $current_page_permalink;
207
+	}
208
+
209
+
210
+
211
+	/**
212
+	 * @return bool
213
+	 * @throws EE_Error
214
+	 * @throws ReflectionException
215
+	 */
216
+	public function test_for_espresso_page()
217
+	{
218
+		global $wp;
219
+		/** @type EE_CPT_Strategy $EE_CPT_Strategy */
220
+		$EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
221
+		$espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
222
+		if (is_array($espresso_CPT_taxonomies)) {
223
+			foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
224
+				if (isset($wp->query_vars, $wp->query_vars[$espresso_CPT_taxonomy])) {
225
+					return true;
226
+				}
227
+			}
228
+		}
229
+		// load espresso CPT endpoints
230
+		$espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
231
+		$post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
232
+		$post_types = (array)$this->get('post_type');
233
+		foreach ($post_types as $post_type) {
234
+			// was a post name passed ?
235
+			if (isset($post_type_CPT_endpoints[$post_type])) {
236
+				// kk we know this is an espresso page, but is it a specific post ?
237
+				if (! $this->get('post_name')) {
238
+					// there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
239
+					$post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
240
+						? $post_type_CPT_endpoints[$this->get('post_type')]
241
+						: '';
242
+					// if the post type matches on of our then set the endpoint
243
+					if ($post_name) {
244
+						$this->set('post_name', $post_name);
245
+					}
246
+				}
247
+				return true;
248
+			}
249
+		}
250
+		return false;
251
+	}
252
+	/**
253
+	 * @param $key
254
+	 * @param $value
255
+	 * @return    void
256
+	 */
257
+	public function set_notice($key, $value)
258
+	{
259
+		$this->_notice[$key] = $value;
260
+	}
261
+
262
+
263
+
264
+	/**
265
+	 * @param $key
266
+	 * @return    mixed
267
+	 */
268
+	public function get_notice($key)
269
+	{
270
+		return isset($this->_notice[$key])
271
+			? $this->_notice[$key]
272
+			: null;
273
+	}
274
+
275
+
276
+
277
+	/**
278
+	 * @param $string
279
+	 * @return void
280
+	 */
281
+	public function add_output($string)
282
+	{
283
+		$this->_output .= $string;
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * @return string
290
+	 */
291
+	public function get_output()
292
+	{
293
+		return $this->_output;
294
+	}
295
+
296
+
297
+
298
+	/**
299
+	 * @param $item
300
+	 * @param $key
301
+	 */
302
+	public function sanitize_text_field_for_array_walk(&$item, &$key)
303
+	{
304
+		$item = strpos($item, 'email') !== false
305
+			? sanitize_email($item)
306
+			: sanitize_text_field($item);
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * @param null|bool $value
313
+	 * @return void
314
+	 * @throws EE_Error
315
+	 * @throws ReflectionException
316
+	 */
317
+	public function set_espresso_page($value = null)
318
+	{
319
+		$this->request->set(
320
+			'is_espresso_page',
321
+			! empty($value)
322
+				? $value
323
+				: $this->test_for_espresso_page()
324
+		);
325
+	}
326
+
327
+
328
+
329
+	/**
330
+	 * @return    mixed
331
+	 */
332
+	public function is_espresso_page()
333
+	{
334
+		return $this->request->is_set('is_espresso_page');
335
+	}
336
+
337
+
338
+
339
+	/**
340
+	 * returns contents of $_REQUEST
341
+	 *
342
+	 * @return array
343
+	 */
344
+	public function params()
345
+	{
346
+		return $this->request->params();
347
+	}
348
+
349
+
350
+
351
+	/**
352
+	 * @param      $key
353
+	 * @param      $value
354
+	 * @param bool $override_ee
355
+	 * @return    void
356
+	 */
357
+	public function set($key, $value, $override_ee = false)
358
+	{
359
+		$this->request->set($key, $value, $override_ee);
360
+	}
361
+
362
+
363
+
364
+	/**
365
+	 * @param      $key
366
+	 * @param null $default
367
+	 * @return    mixed
368
+	 */
369
+	public function get($key, $default = null)
370
+	{
371
+		return $this->request->get($key, $default);
372
+	}
373
+
374
+
375
+
376
+	/**
377
+	 * check if param exists
378
+	 *
379
+	 * @param $key
380
+	 * @return    boolean
381
+	 */
382
+	public function is_set($key)
383
+	{
384
+		return $this->request->is_set($key);
385
+	}
386
+
387
+
388
+
389
+	/**
390
+	 * remove param
391
+	 *
392
+	 * @param $key
393
+	 * @return    void
394
+	 */
395
+	public function un_set($key)
396
+	{
397
+		$this->request->un_set($key);
398
+	}
399 399
 
400 400
 
401 401
 
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
     public function parse_request($wp = null)
69 69
     {
70 70
         //if somebody forgot to provide us with WP, that's ok because its global
71
-        if (! $wp instanceof WP) {
71
+        if ( ! $wp instanceof WP) {
72 72
             global $wp;
73 73
         }
74 74
         $this->set_request_vars($wp);
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
      */
85 85
     public function set_request_vars($wp = null)
86 86
     {
87
-        if (! is_admin()) {
87
+        if ( ! is_admin()) {
88 88
             // set request post_id
89 89
             $this->request->set('post_id', $this->get_post_id_from_request($wp));
90 90
             // set request post name
@@ -104,17 +104,17 @@  discard block
 block discarded – undo
104 104
      */
105 105
     public function get_post_id_from_request($wp = null)
106 106
     {
107
-        if (! $wp instanceof WP) {
107
+        if ( ! $wp instanceof WP) {
108 108
             global $wp;
109 109
         }
110 110
         $post_id = null;
111 111
         if (isset($wp->query_vars['p'])) {
112 112
             $post_id = $wp->query_vars['p'];
113 113
         }
114
-        if (! $post_id && isset($wp->query_vars['page_id'])) {
114
+        if ( ! $post_id && isset($wp->query_vars['page_id'])) {
115 115
             $post_id = $wp->query_vars['page_id'];
116 116
         }
117
-        if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
117
+        if ( ! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
118 118
             $post_id = basename($wp->request);
119 119
         }
120 120
         return $post_id;
@@ -128,19 +128,19 @@  discard block
 block discarded – undo
128 128
      */
129 129
     public function get_post_name_from_request($wp = null)
130 130
     {
131
-        if (! $wp instanceof WP) {
131
+        if ( ! $wp instanceof WP) {
132 132
             global $wp;
133 133
         }
134 134
         $post_name = null;
135 135
         if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
136 136
             $post_name = $wp->query_vars['name'];
137 137
         }
138
-        if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
138
+        if ( ! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
139 139
             $post_name = $wp->query_vars['pagename'];
140 140
         }
141
-        if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
141
+        if ( ! $post_name && $wp->request !== null && ! empty($wp->request)) {
142 142
             $possible_post_name = basename($wp->request);
143
-            if (! is_numeric($possible_post_name)) {
143
+            if ( ! is_numeric($possible_post_name)) {
144 144
                 /** @type WPDB $wpdb */
145 145
                 global $wpdb;
146 146
                 $SQL =
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
                 }
152 152
             }
153 153
         }
154
-        if (! $post_name && $this->get('post_id')) {
154
+        if ( ! $post_name && $this->get('post_id')) {
155 155
             /** @type WPDB $wpdb */
156 156
             global $wpdb;
157 157
             $SQL =
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
      */
173 173
     public function get_post_type_from_request($wp = null)
174 174
     {
175
-        if (! $wp instanceof WP) {
175
+        if ( ! $wp instanceof WP) {
176 176
             global $wp;
177 177
         }
178 178
         return isset($wp->query_vars['post_type'])
@@ -194,7 +194,7 @@  discard block
 block discarded – undo
194 194
         if ($post_id) {
195 195
             $current_page_permalink = get_permalink($post_id);
196 196
         } else {
197
-            if (! $wp instanceof WP) {
197
+            if ( ! $wp instanceof WP) {
198 198
                 global $wp;
199 199
             }
200 200
             if ($wp->request) {
@@ -229,12 +229,12 @@  discard block
 block discarded – undo
229 229
         // load espresso CPT endpoints
230 230
         $espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
231 231
         $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
232
-        $post_types = (array)$this->get('post_type');
232
+        $post_types = (array) $this->get('post_type');
233 233
         foreach ($post_types as $post_type) {
234 234
             // was a post name passed ?
235 235
             if (isset($post_type_CPT_endpoints[$post_type])) {
236 236
                 // kk we know this is an espresso page, but is it a specific post ?
237
-                if (! $this->get('post_name')) {
237
+                if ( ! $this->get('post_name')) {
238 238
                     // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
239 239
                     $post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
240 240
                         ? $post_type_CPT_endpoints[$this->get('post_type')]
Please login to merge, or discard this patch.
core/EE_Module_Request_Router.core.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -17,248 +17,248 @@
 block discarded – undo
17 17
 final class EE_Module_Request_Router implements InterminableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var EE_Request $request
22
-     */
23
-    private $request;
20
+	/**
21
+	 * @var EE_Request $request
22
+	 */
23
+	private $request;
24 24
 
25
-    /**
26
-     * @var array $_previous_routes
27
-     */
28
-    private static $_previous_routes = array();
25
+	/**
26
+	 * @var array $_previous_routes
27
+	 */
28
+	private static $_previous_routes = array();
29 29
 
30
-    /**
31
-     * @var WP_Query $WP_Query
32
-     */
33
-    public $WP_Query;
30
+	/**
31
+	 * @var WP_Query $WP_Query
32
+	 */
33
+	public $WP_Query;
34 34
 
35 35
 
36 36
 
37
-    /**
38
-     * EE_Module_Request_Router constructor.
39
-     *
40
-     * @param EE_Request $request
41
-     */
42
-    public function __construct(EE_Request $request)
43
-    {
44
-        $this->request = $request;
45
-    }
37
+	/**
38
+	 * EE_Module_Request_Router constructor.
39
+	 *
40
+	 * @param EE_Request $request
41
+	 */
42
+	public function __construct(EE_Request $request)
43
+	{
44
+		$this->request = $request;
45
+	}
46 46
 
47 47
 
48 48
 
49
-    /**
50
-     * on the first call  to this method, it checks the EE_Request_Handler for a "route"
51
-     * on subsequent calls to this method,
52
-     * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
53
-     * and checks if the last called route has any forwarding routes registered for it
54
-     *
55
-     * @param WP_Query $WP_Query
56
-     * @return NULL|string
57
-     * @throws EE_Error
58
-     * @throws ReflectionException
59
-     */
60
-    public function get_route(WP_Query $WP_Query)
61
-    {
62
-        $this->WP_Query = $WP_Query;
63
-        // assume this if first route being called
64
-        $previous_route = false;
65
-        // but is it really ???
66
-        if (! empty(self::$_previous_routes)) {
67
-            // get last run route
68
-            $previous_routes = array_values(self::$_previous_routes);
69
-            $previous_route = array_pop($previous_routes);
70
-        }
71
-        //  has another route already been run ?
72
-        if ($previous_route) {
73
-            // check if  forwarding has been set
74
-            $current_route = $this->get_forward($previous_route);
75
-            try {
76
-                //check for recursive forwarding
77
-                if (isset(self::$_previous_routes[$current_route])) {
78
-                    throw new EE_Error(
79
-                        sprintf(
80
-                            __(
81
-                                'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
82
-                                'event_espresso'
83
-                            ),
84
-                            $current_route
85
-                        )
86
-                    );
87
-                }
88
-            } catch (EE_Error $e) {
89
-                $e->get_error();
90
-                return null;
91
-            }
92
-        } else {
93
-            // first route called
94
-            $current_route = null;
95
-            // grab all routes
96
-            $routes = EE_Config::get_routes();
97
-            //d( $routes );
98
-            foreach ($routes as $key => $route) {
99
-                // check request for module route
100
-                if ($this->request->is_set($key)) {
101
-                    $current_route = sanitize_text_field($this->request->get($key));
102
-                    if ($current_route) {
103
-                        $current_route = array($key, $current_route);
104
-                        break;
105
-                    }
106
-                }
107
-            }
108
-        }
109
-        // sorry, but I can't read what you route !
110
-        if (empty($current_route)) {
111
-            return null;
112
-        }
113
-        //add route to previous routes array
114
-        self::$_previous_routes[] = $current_route;
115
-        return $current_route;
116
-    }
49
+	/**
50
+	 * on the first call  to this method, it checks the EE_Request_Handler for a "route"
51
+	 * on subsequent calls to this method,
52
+	 * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
53
+	 * and checks if the last called route has any forwarding routes registered for it
54
+	 *
55
+	 * @param WP_Query $WP_Query
56
+	 * @return NULL|string
57
+	 * @throws EE_Error
58
+	 * @throws ReflectionException
59
+	 */
60
+	public function get_route(WP_Query $WP_Query)
61
+	{
62
+		$this->WP_Query = $WP_Query;
63
+		// assume this if first route being called
64
+		$previous_route = false;
65
+		// but is it really ???
66
+		if (! empty(self::$_previous_routes)) {
67
+			// get last run route
68
+			$previous_routes = array_values(self::$_previous_routes);
69
+			$previous_route = array_pop($previous_routes);
70
+		}
71
+		//  has another route already been run ?
72
+		if ($previous_route) {
73
+			// check if  forwarding has been set
74
+			$current_route = $this->get_forward($previous_route);
75
+			try {
76
+				//check for recursive forwarding
77
+				if (isset(self::$_previous_routes[$current_route])) {
78
+					throw new EE_Error(
79
+						sprintf(
80
+							__(
81
+								'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
82
+								'event_espresso'
83
+							),
84
+							$current_route
85
+						)
86
+					);
87
+				}
88
+			} catch (EE_Error $e) {
89
+				$e->get_error();
90
+				return null;
91
+			}
92
+		} else {
93
+			// first route called
94
+			$current_route = null;
95
+			// grab all routes
96
+			$routes = EE_Config::get_routes();
97
+			//d( $routes );
98
+			foreach ($routes as $key => $route) {
99
+				// check request for module route
100
+				if ($this->request->is_set($key)) {
101
+					$current_route = sanitize_text_field($this->request->get($key));
102
+					if ($current_route) {
103
+						$current_route = array($key, $current_route);
104
+						break;
105
+					}
106
+				}
107
+			}
108
+		}
109
+		// sorry, but I can't read what you route !
110
+		if (empty($current_route)) {
111
+			return null;
112
+		}
113
+		//add route to previous routes array
114
+		self::$_previous_routes[] = $current_route;
115
+		return $current_route;
116
+	}
117 117
 
118 118
 
119 119
 
120
-    /**
121
-     * this method simply takes a valid route, and resolves what module class method the route points to
122
-     *
123
-     * @param string $key
124
-     * @param string $current_route
125
-     * @return mixed EED_Module | boolean
126
-     * @throws EE_Error
127
-     * @throws ReflectionException
128
-     */
129
-    public function resolve_route($key, $current_route)
130
-    {
131
-        // get module method that route has been mapped to
132
-        $module_method = EE_Config::get_route($current_route, $key);
133
-        // verify result was returned
134
-        if (empty($module_method)) {
135
-            $msg = sprintf(
136
-                __('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
137
-                $current_route
138
-            );
139
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
140
-            return false;
141
-        }
142
-        // verify that result is an array
143
-        if (! is_array($module_method)) {
144
-            $msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
145
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
146
-            return false;
147
-        }
148
-        // grab module name
149
-        $module_name = $module_method[0];
150
-        // verify that a class method was registered properly
151
-        if (! isset($module_method[1])) {
152
-            $msg = sprintf(
153
-                __('A class method for the %s  route has not been properly registered.', 'event_espresso'),
154
-                $current_route
155
-            );
156
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
157
-            return false;
158
-        }
159
-        // grab method
160
-        $method = $module_method[1];
161
-        // verify that class exists
162
-        if (! class_exists($module_name)) {
163
-            $msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
164
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
165
-            return false;
166
-        }
167
-        // verify that method exists
168
-        if (! method_exists($module_name, $method)) {
169
-            $msg = sprintf(
170
-                __('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
171
-            );
172
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
173
-            return false;
174
-        }
175
-        // instantiate module and call route method
176
-        return $this->_module_router($module_name, $method);
177
-    }
120
+	/**
121
+	 * this method simply takes a valid route, and resolves what module class method the route points to
122
+	 *
123
+	 * @param string $key
124
+	 * @param string $current_route
125
+	 * @return mixed EED_Module | boolean
126
+	 * @throws EE_Error
127
+	 * @throws ReflectionException
128
+	 */
129
+	public function resolve_route($key, $current_route)
130
+	{
131
+		// get module method that route has been mapped to
132
+		$module_method = EE_Config::get_route($current_route, $key);
133
+		// verify result was returned
134
+		if (empty($module_method)) {
135
+			$msg = sprintf(
136
+				__('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
137
+				$current_route
138
+			);
139
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
140
+			return false;
141
+		}
142
+		// verify that result is an array
143
+		if (! is_array($module_method)) {
144
+			$msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
145
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
146
+			return false;
147
+		}
148
+		// grab module name
149
+		$module_name = $module_method[0];
150
+		// verify that a class method was registered properly
151
+		if (! isset($module_method[1])) {
152
+			$msg = sprintf(
153
+				__('A class method for the %s  route has not been properly registered.', 'event_espresso'),
154
+				$current_route
155
+			);
156
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
157
+			return false;
158
+		}
159
+		// grab method
160
+		$method = $module_method[1];
161
+		// verify that class exists
162
+		if (! class_exists($module_name)) {
163
+			$msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
164
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
165
+			return false;
166
+		}
167
+		// verify that method exists
168
+		if (! method_exists($module_name, $method)) {
169
+			$msg = sprintf(
170
+				__('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
171
+			);
172
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
173
+			return false;
174
+		}
175
+		// instantiate module and call route method
176
+		return $this->_module_router($module_name, $method);
177
+	}
178 178
 
179 179
 
180 180
 
181
-    /**
182
-     * this method instantiates modules and calls the method that was defined when the route was registered
183
-     *
184
-     * @param string $module_name
185
-     * @return EED_Module|object|null
186
-     * @throws ReflectionException
187
-     */
188
-    public static function module_factory($module_name)
189
-    {
190
-        if ($module_name === 'EED_Module') {
191
-            EE_Error::add_error(
192
-                sprintf(
193
-                    __(
194
-                        'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
195
-                        'event_espresso'
196
-                    ), $module_name
197
-                ), __FILE__, __FUNCTION__, __LINE__
198
-            );
199
-            return null;
200
-        }
201
-        // instantiate module class
202
-        $module = new $module_name();
203
-        // ensure that class is actually a module
204
-        if (! $module instanceof EED_Module) {
205
-            EE_Error::add_error(
206
-                sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
207
-                __FILE__, __FUNCTION__, __LINE__
208
-            );
209
-            return null;
210
-        }
211
-        return $module;
212
-    }
181
+	/**
182
+	 * this method instantiates modules and calls the method that was defined when the route was registered
183
+	 *
184
+	 * @param string $module_name
185
+	 * @return EED_Module|object|null
186
+	 * @throws ReflectionException
187
+	 */
188
+	public static function module_factory($module_name)
189
+	{
190
+		if ($module_name === 'EED_Module') {
191
+			EE_Error::add_error(
192
+				sprintf(
193
+					__(
194
+						'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
195
+						'event_espresso'
196
+					), $module_name
197
+				), __FILE__, __FUNCTION__, __LINE__
198
+			);
199
+			return null;
200
+		}
201
+		// instantiate module class
202
+		$module = new $module_name();
203
+		// ensure that class is actually a module
204
+		if (! $module instanceof EED_Module) {
205
+			EE_Error::add_error(
206
+				sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
207
+				__FILE__, __FUNCTION__, __LINE__
208
+			);
209
+			return null;
210
+		}
211
+		return $module;
212
+	}
213 213
 
214 214
 
215 215
 
216
-    /**
217
-     * this method instantiates modules and calls the method that was defined when the route was registered
218
-     *
219
-     * @param string $module_name
220
-     * @param string $method
221
-     * @return EED_Module|null
222
-     * @throws EE_Error
223
-     * @throws ReflectionException
224
-     */
225
-    private function _module_router($module_name, $method)
226
-    {
227
-        // instantiate module class
228
-        $module = EE_Module_Request_Router::module_factory($module_name);
229
-        if ($module instanceof EED_Module) {
230
-            // and call whatever action the route was for
231
-            try {
232
-                call_user_func(array($module, $method), $this->WP_Query);
233
-            } catch (EE_Error $e) {
234
-                $e->get_error();
235
-                return null;
236
-            }
237
-        }
238
-        return $module;
239
-    }
216
+	/**
217
+	 * this method instantiates modules and calls the method that was defined when the route was registered
218
+	 *
219
+	 * @param string $module_name
220
+	 * @param string $method
221
+	 * @return EED_Module|null
222
+	 * @throws EE_Error
223
+	 * @throws ReflectionException
224
+	 */
225
+	private function _module_router($module_name, $method)
226
+	{
227
+		// instantiate module class
228
+		$module = EE_Module_Request_Router::module_factory($module_name);
229
+		if ($module instanceof EED_Module) {
230
+			// and call whatever action the route was for
231
+			try {
232
+				call_user_func(array($module, $method), $this->WP_Query);
233
+			} catch (EE_Error $e) {
234
+				$e->get_error();
235
+				return null;
236
+			}
237
+		}
238
+		return $module;
239
+	}
240 240
 
241 241
 
242 242
 
243
-    /**
244
-     * @param $current_route
245
-     * @return string
246
-     */
247
-    public function get_forward($current_route)
248
-    {
249
-        return EE_Config::get_forward($current_route);
250
-    }
243
+	/**
244
+	 * @param $current_route
245
+	 * @return string
246
+	 */
247
+	public function get_forward($current_route)
248
+	{
249
+		return EE_Config::get_forward($current_route);
250
+	}
251 251
 
252 252
 
253 253
 
254
-    /**
255
-     * @param $current_route
256
-     * @return string
257
-     */
258
-    public function get_view($current_route)
259
-    {
260
-        return EE_Config::get_view($current_route);
261
-    }
254
+	/**
255
+	 * @param $current_route
256
+	 * @return string
257
+	 */
258
+	public function get_view($current_route)
259
+	{
260
+		return EE_Config::get_view($current_route);
261
+	}
262 262
 
263 263
 
264 264
 }
Please login to merge, or discard this patch.