Completed
Branch BUG/reg-status-change-recursio... (fbd515)
by
unknown
09:28 queued 36s
created
admin_pages/registrations/Registrations_Admin_Page.core.php 1 patch
Indentation   +3831 added lines, -3831 removed lines patch added patch discarded remove patch
@@ -19,2406 +19,2406 @@  discard block
 block discarded – undo
19 19
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * @var EE_Registration
24
-     */
25
-    private $_registration;
26
-
27
-    /**
28
-     * @var EE_Event
29
-     */
30
-    private $_reg_event;
31
-
32
-    /**
33
-     * @var EE_Session
34
-     */
35
-    private $_session;
36
-
37
-    private static $_reg_status;
38
-
39
-    /**
40
-     * Form for displaying the custom questions for this registration.
41
-     * This gets used a few times throughout the request so its best to cache it
42
-     *
43
-     * @var EE_Registration_Custom_Questions_Form
44
-     */
45
-    protected $_reg_custom_questions_form = null;
46
-
47
-
48
-    /**
49
-     *        constructor
50
-     *
51
-     * @Constructor
52
-     * @access public
53
-     * @param bool $routing
54
-     * @return Registrations_Admin_Page
55
-     */
56
-    public function __construct($routing = true)
57
-    {
58
-        parent::__construct($routing);
59
-        add_action('wp_loaded', array($this, 'wp_loaded'));
60
-    }
61
-
62
-
63
-    public function wp_loaded()
64
-    {
65
-        // when adding a new registration...
66
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
-            EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
69
-                || absint($this->_req_data['processing_registration']) !== 1
70
-            ) {
71
-                // and it's NOT the attendee information reg step
72
-                // force cookie expiration by setting time to last week
73
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
-                // and update the global
75
-                $_COOKIE['ee_registration_added'] = 0;
76
-            }
77
-        }
78
-    }
79
-
80
-
81
-    protected function _init_page_props()
82
-    {
83
-        $this->page_slug = REG_PG_SLUG;
84
-        $this->_admin_base_url = REG_ADMIN_URL;
85
-        $this->_admin_base_path = REG_ADMIN;
86
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
87
-        $this->_cpt_routes = array(
88
-            'add_new_attendee' => 'espresso_attendees',
89
-            'edit_attendee'    => 'espresso_attendees',
90
-            'insert_attendee'  => 'espresso_attendees',
91
-            'update_attendee'  => 'espresso_attendees',
92
-        );
93
-        $this->_cpt_model_names = array(
94
-            'add_new_attendee' => 'EEM_Attendee',
95
-            'edit_attendee'    => 'EEM_Attendee',
96
-        );
97
-        $this->_cpt_edit_routes = array(
98
-            'espresso_attendees' => 'edit_attendee',
99
-        );
100
-        $this->_pagenow_map = array(
101
-            'add_new_attendee' => 'post-new.php',
102
-            'edit_attendee'    => 'post.php',
103
-            'trash'            => 'post.php',
104
-        );
105
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
-        // add filters so that the comment urls don't take users to a confusing 404 page
107
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
-    }
109
-
110
-
111
-    public function clear_comment_link($link, $comment, $args)
112
-    {
113
-        // gotta make sure this only happens on this route
114
-        $post_type = get_post_type($comment->comment_post_ID);
115
-        if ($post_type === 'espresso_attendees') {
116
-            return '#commentsdiv';
117
-        }
118
-        return $link;
119
-    }
120
-
121
-
122
-    protected function _ajax_hooks()
123
-    {
124
-        // todo: all hooks for registrations ajax goes in here
125
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
-    }
127
-
128
-
129
-    protected function _define_page_props()
130
-    {
131
-        $this->_admin_page_title = $this->page_label;
132
-        $this->_labels = array(
133
-            'buttons'                      => array(
134
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
-            ),
143
-            'publishbox'                   => array(
144
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
-            ),
147
-            'hide_add_button_on_cpt_route' => array(
148
-                'edit_attendee' => true,
149
-            ),
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     *        grab url requests and route them
156
-     *
157
-     * @access private
158
-     * @return void
159
-     */
160
-    public function _set_page_routes()
161
-    {
162
-        $this->_get_registration_status_array();
163
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
-            ? $this->_req_data['_REG_ID'] : 0;
165
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
167
-            : $reg_id;
168
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
-            ? $this->_req_data['ATT_ID'] : 0;
170
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
-            ? $this->_req_data['post']
172
-            : $att_id;
173
-        $this->_page_routes = array(
174
-            'default'                             => array(
175
-                'func'       => '_registrations_overview_list_table',
176
-                'capability' => 'ee_read_registrations',
177
-            ),
178
-            'view_registration'                   => array(
179
-                'func'       => '_registration_details',
180
-                'capability' => 'ee_read_registration',
181
-                'obj_id'     => $reg_id,
182
-            ),
183
-            'edit_registration'                   => array(
184
-                'func'               => '_update_attendee_registration_form',
185
-                'noheader'           => true,
186
-                'headers_sent_route' => 'view_registration',
187
-                'capability'         => 'ee_edit_registration',
188
-                'obj_id'             => $reg_id,
189
-                '_REG_ID'            => $reg_id,
190
-            ),
191
-            'trash_registrations'                 => array(
192
-                'func'       => '_trash_or_restore_registrations',
193
-                'args'       => array('trash' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_delete_registrations',
196
-            ),
197
-            'restore_registrations'               => array(
198
-                'func'       => '_trash_or_restore_registrations',
199
-                'args'       => array('trash' => false),
200
-                'noheader'   => true,
201
-                'capability' => 'ee_delete_registrations',
202
-            ),
203
-            'delete_registrations'                => array(
204
-                'func'       => '_delete_registrations',
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'new_registration'                    => array(
209
-                'func'       => 'new_registration',
210
-                'capability' => 'ee_edit_registrations',
211
-            ),
212
-            'process_reg_step'                    => array(
213
-                'func'       => 'process_reg_step',
214
-                'noheader'   => true,
215
-                'capability' => 'ee_edit_registrations',
216
-            ),
217
-            'redirect_to_txn'                     => array(
218
-                'func'       => 'redirect_to_txn',
219
-                'noheader'   => true,
220
-                'capability' => 'ee_edit_registrations',
221
-            ),
222
-            'change_reg_status'                   => array(
223
-                'func'       => '_change_reg_status',
224
-                'noheader'   => true,
225
-                'capability' => 'ee_edit_registration',
226
-                'obj_id'     => $reg_id,
227
-            ),
228
-            'approve_registration'                => array(
229
-                'func'       => 'approve_registration',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registration',
232
-                'obj_id'     => $reg_id,
233
-            ),
234
-            'approve_and_notify_registration'     => array(
235
-                'func'       => 'approve_registration',
236
-                'noheader'   => true,
237
-                'args'       => array(true),
238
-                'capability' => 'ee_edit_registration',
239
-                'obj_id'     => $reg_id,
240
-            ),
241
-            'approve_registrations'               => array(
242
-                'func'       => 'bulk_action_on_registrations',
243
-                'noheader'   => true,
244
-                'capability' => 'ee_edit_registrations',
245
-                'args'       => array('approve'),
246
-            ),
247
-            'approve_and_notify_registrations'    => array(
248
-                'func'       => 'bulk_action_on_registrations',
249
-                'noheader'   => true,
250
-                'capability' => 'ee_edit_registrations',
251
-                'args'       => array('approve', true),
252
-            ),
253
-            'decline_registration'                => array(
254
-                'func'       => 'decline_registration',
255
-                'noheader'   => true,
256
-                'capability' => 'ee_edit_registration',
257
-                'obj_id'     => $reg_id,
258
-            ),
259
-            'decline_and_notify_registration'     => array(
260
-                'func'       => 'decline_registration',
261
-                'noheader'   => true,
262
-                'args'       => array(true),
263
-                'capability' => 'ee_edit_registration',
264
-                'obj_id'     => $reg_id,
265
-            ),
266
-            'decline_registrations'               => array(
267
-                'func'       => 'bulk_action_on_registrations',
268
-                'noheader'   => true,
269
-                'capability' => 'ee_edit_registrations',
270
-                'args'       => array('decline'),
271
-            ),
272
-            'decline_and_notify_registrations'    => array(
273
-                'func'       => 'bulk_action_on_registrations',
274
-                'noheader'   => true,
275
-                'capability' => 'ee_edit_registrations',
276
-                'args'       => array('decline', true),
277
-            ),
278
-            'pending_registration'                => array(
279
-                'func'       => 'pending_registration',
280
-                'noheader'   => true,
281
-                'capability' => 'ee_edit_registration',
282
-                'obj_id'     => $reg_id,
283
-            ),
284
-            'pending_and_notify_registration'     => array(
285
-                'func'       => 'pending_registration',
286
-                'noheader'   => true,
287
-                'args'       => array(true),
288
-                'capability' => 'ee_edit_registration',
289
-                'obj_id'     => $reg_id,
290
-            ),
291
-            'pending_registrations'               => array(
292
-                'func'       => 'bulk_action_on_registrations',
293
-                'noheader'   => true,
294
-                'capability' => 'ee_edit_registrations',
295
-                'args'       => array('pending'),
296
-            ),
297
-            'pending_and_notify_registrations'    => array(
298
-                'func'       => 'bulk_action_on_registrations',
299
-                'noheader'   => true,
300
-                'capability' => 'ee_edit_registrations',
301
-                'args'       => array('pending', true),
302
-            ),
303
-            'no_approve_registration'             => array(
304
-                'func'       => 'not_approve_registration',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'no_approve_and_notify_registration'  => array(
310
-                'func'       => 'not_approve_registration',
311
-                'noheader'   => true,
312
-                'args'       => array(true),
313
-                'capability' => 'ee_edit_registration',
314
-                'obj_id'     => $reg_id,
315
-            ),
316
-            'no_approve_registrations'            => array(
317
-                'func'       => 'bulk_action_on_registrations',
318
-                'noheader'   => true,
319
-                'capability' => 'ee_edit_registrations',
320
-                'args'       => array('not_approve'),
321
-            ),
322
-            'no_approve_and_notify_registrations' => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('not_approve', true),
327
-            ),
328
-            'cancel_registration'                 => array(
329
-                'func'       => 'cancel_registration',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registration',
332
-                'obj_id'     => $reg_id,
333
-            ),
334
-            'cancel_and_notify_registration'      => array(
335
-                'func'       => 'cancel_registration',
336
-                'noheader'   => true,
337
-                'args'       => array(true),
338
-                'capability' => 'ee_edit_registration',
339
-                'obj_id'     => $reg_id,
340
-            ),
341
-            'cancel_registrations'                => array(
342
-                'func'       => 'bulk_action_on_registrations',
343
-                'noheader'   => true,
344
-                'capability' => 'ee_edit_registrations',
345
-                'args'       => array('cancel'),
346
-            ),
347
-            'cancel_and_notify_registrations'     => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('cancel', true),
352
-            ),
353
-            'wait_list_registration'              => array(
354
-                'func'       => 'wait_list_registration',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registration',
357
-                'obj_id'     => $reg_id,
358
-            ),
359
-            'wait_list_and_notify_registration'   => array(
360
-                'func'       => 'wait_list_registration',
361
-                'noheader'   => true,
362
-                'args'       => array(true),
363
-                'capability' => 'ee_edit_registration',
364
-                'obj_id'     => $reg_id,
365
-            ),
366
-            'contact_list'                        => array(
367
-                'func'       => '_attendee_contact_list_table',
368
-                'capability' => 'ee_read_contacts',
369
-            ),
370
-            'add_new_attendee'                    => array(
371
-                'func' => '_create_new_cpt_item',
372
-                'args' => array(
373
-                    'new_attendee' => true,
374
-                    'capability'   => 'ee_edit_contacts',
375
-                ),
376
-            ),
377
-            'edit_attendee'                       => array(
378
-                'func'       => '_edit_cpt_item',
379
-                'capability' => 'ee_edit_contacts',
380
-                'obj_id'     => $att_id,
381
-            ),
382
-            'duplicate_attendee'                  => array(
383
-                'func'       => '_duplicate_attendee',
384
-                'noheader'   => true,
385
-                'capability' => 'ee_edit_contacts',
386
-                'obj_id'     => $att_id,
387
-            ),
388
-            'insert_attendee'                     => array(
389
-                'func'       => '_insert_or_update_attendee',
390
-                'args'       => array(
391
-                    'new_attendee' => true,
392
-                ),
393
-                'noheader'   => true,
394
-                'capability' => 'ee_edit_contacts',
395
-            ),
396
-            'update_attendee'                     => array(
397
-                'func'       => '_insert_or_update_attendee',
398
-                'args'       => array(
399
-                    'new_attendee' => false,
400
-                ),
401
-                'noheader'   => true,
402
-                'capability' => 'ee_edit_contacts',
403
-                'obj_id'     => $att_id,
404
-            ),
405
-            'trash_attendees'                     => array(
406
-                'func'       => '_trash_or_restore_attendees',
407
-                'args'       => array(
408
-                    'trash' => 'true',
409
-                ),
410
-                'noheader'   => true,
411
-                'capability' => 'ee_delete_contacts',
412
-            ),
413
-            'trash_attendee'                      => array(
414
-                'func'       => '_trash_or_restore_attendees',
415
-                'args'       => array(
416
-                    'trash' => true,
417
-                ),
418
-                'noheader'   => true,
419
-                'capability' => 'ee_delete_contacts',
420
-                'obj_id'     => $att_id,
421
-            ),
422
-            'restore_attendees'                   => array(
423
-                'func'       => '_trash_or_restore_attendees',
424
-                'args'       => array(
425
-                    'trash' => false,
426
-                ),
427
-                'noheader'   => true,
428
-                'capability' => 'ee_delete_contacts',
429
-                'obj_id'     => $att_id,
430
-            ),
431
-            'resend_registration'                 => array(
432
-                'func'       => '_resend_registration',
433
-                'noheader'   => true,
434
-                'capability' => 'ee_send_message',
435
-            ),
436
-            'registrations_report'                => array(
437
-                'func'       => '_registrations_report',
438
-                'noheader'   => true,
439
-                'capability' => 'ee_read_registrations',
440
-            ),
441
-            'contact_list_export'                 => array(
442
-                'func'       => '_contact_list_export',
443
-                'noheader'   => true,
444
-                'capability' => 'export',
445
-            ),
446
-            'contact_list_report'                 => array(
447
-                'func'       => '_contact_list_report',
448
-                'noheader'   => true,
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-        );
452
-    }
453
-
454
-
455
-    protected function _set_page_config()
456
-    {
457
-        $this->_page_config = array(
458
-            'default'           => array(
459
-                'nav'           => array(
460
-                    'label' => esc_html__('Overview', 'event_espresso'),
461
-                    'order' => 5,
462
-                ),
463
-                'help_tabs'     => array(
464
-                    'registrations_overview_help_tab'                       => array(
465
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
-                        'filename' => 'registrations_overview',
467
-                    ),
468
-                    'registrations_overview_table_column_headings_help_tab' => array(
469
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
-                        'filename' => 'registrations_overview_table_column_headings',
471
-                    ),
472
-                    'registrations_overview_filters_help_tab'               => array(
473
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
-                        'filename' => 'registrations_overview_filters',
475
-                    ),
476
-                    'registrations_overview_views_help_tab'                 => array(
477
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
478
-                        'filename' => 'registrations_overview_views',
479
-                    ),
480
-                    'registrations_regoverview_other_help_tab'              => array(
481
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
-                        'filename' => 'registrations_overview_other',
483
-                    ),
484
-                ),
485
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
486
-                'qtips'         => array('Registration_List_Table_Tips'),
487
-                'list_table'    => 'EE_Registrations_List_Table',
488
-                'require_nonce' => false,
489
-            ),
490
-            'view_registration' => array(
491
-                'nav'           => array(
492
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
493
-                    'order'      => 15,
494
-                    'url'        => isset($this->_req_data['_REG_ID'])
495
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
-                        : $this->_admin_base_url,
497
-                    'persistent' => false,
498
-                ),
499
-                'help_tabs'     => array(
500
-                    'registrations_details_help_tab'                    => array(
501
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
502
-                        'filename' => 'registrations_details',
503
-                    ),
504
-                    'registrations_details_table_help_tab'              => array(
505
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
-                        'filename' => 'registrations_details_table',
507
-                    ),
508
-                    'registrations_details_form_answers_help_tab'       => array(
509
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
-                        'filename' => 'registrations_details_form_answers',
511
-                    ),
512
-                    'registrations_details_registrant_details_help_tab' => array(
513
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
514
-                        'filename' => 'registrations_details_registrant_details',
515
-                    ),
516
-                ),
517
-                'help_tour'     => array('Registration_Details_Help_Tour'),
518
-                'metaboxes'     => array_merge(
519
-                    $this->_default_espresso_metaboxes,
520
-                    array('_registration_details_metaboxes')
521
-                ),
522
-                'require_nonce' => false,
523
-            ),
524
-            'new_registration'  => array(
525
-                'nav'           => array(
526
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
-                    'url'        => '#',
528
-                    'order'      => 15,
529
-                    'persistent' => false,
530
-                ),
531
-                'metaboxes'     => $this->_default_espresso_metaboxes,
532
-                'labels'        => array(
533
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
-                ),
535
-                'require_nonce' => false,
536
-            ),
537
-            'add_new_attendee'  => array(
538
-                'nav'           => array(
539
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
540
-                    'order'      => 15,
541
-                    'persistent' => false,
542
-                ),
543
-                'metaboxes'     => array_merge(
544
-                    $this->_default_espresso_metaboxes,
545
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
546
-                ),
547
-                'require_nonce' => false,
548
-            ),
549
-            'edit_attendee'     => array(
550
-                'nav'           => array(
551
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
-                    'order'      => 15,
553
-                    'persistent' => false,
554
-                    'url'        => isset($this->_req_data['ATT_ID'])
555
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
-                        : $this->_admin_base_url,
557
-                ),
558
-                'metaboxes'     => array('attendee_editor_metaboxes'),
559
-                'require_nonce' => false,
560
-            ),
561
-            'contact_list'      => array(
562
-                'nav'           => array(
563
-                    'label' => esc_html__('Contact List', 'event_espresso'),
564
-                    'order' => 20,
565
-                ),
566
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
567
-                'help_tabs'     => array(
568
-                    'registrations_contact_list_help_tab'                       => array(
569
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
-                        'filename' => 'registrations_contact_list',
571
-                    ),
572
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
573
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
-                        'filename' => 'registrations_contact_list_table_column_headings',
575
-                    ),
576
-                    'registrations_contact_list_views_help_tab'                 => array(
577
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
-                        'filename' => 'registrations_contact_list_views',
579
-                    ),
580
-                    'registrations_contact_list_other_help_tab'                 => array(
581
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
-                        'filename' => 'registrations_contact_list_other',
583
-                    ),
584
-                ),
585
-                'help_tour'     => array('Contact_List_Help_Tour'),
586
-                'metaboxes'     => array(),
587
-                'require_nonce' => false,
588
-            ),
589
-            // override default cpt routes
590
-            'create_new'        => '',
591
-            'edit'              => '',
592
-        );
593
-    }
594
-
595
-
596
-    /**
597
-     * The below methods aren't used by this class currently
598
-     */
599
-    protected function _add_screen_options()
600
-    {
601
-    }
602
-
603
-
604
-    protected function _add_feature_pointers()
605
-    {
606
-    }
607
-
608
-
609
-    public function admin_init()
610
-    {
611
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
-            'click "Update Registration Questions" to save your changes',
613
-            'event_espresso'
614
-        );
615
-    }
616
-
617
-
618
-    public function admin_notices()
619
-    {
620
-    }
621
-
622
-
623
-    public function admin_footer_scripts()
624
-    {
625
-    }
626
-
627
-
628
-    /**
629
-     *        get list of registration statuses
630
-     *
631
-     * @access private
632
-     * @return void
633
-     * @throws EE_Error
634
-     */
635
-    private function _get_registration_status_array()
636
-    {
637
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
-    }
639
-
640
-
641
-    protected function _add_screen_options_default()
642
-    {
643
-        $this->_per_page_screen_option();
644
-    }
645
-
646
-
647
-    protected function _add_screen_options_contact_list()
648
-    {
649
-        $page_title = $this->_admin_page_title;
650
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
-        $this->_per_page_screen_option();
652
-        $this->_admin_page_title = $page_title;
653
-    }
654
-
655
-
656
-    public function load_scripts_styles()
657
-    {
658
-        // style
659
-        wp_register_style(
660
-            'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
-            array('ee-admin-css'),
663
-            EVENT_ESPRESSO_VERSION
664
-        );
665
-        wp_enqueue_style('espresso_reg');
666
-        // script
667
-        wp_register_script(
668
-            'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
-            EVENT_ESPRESSO_VERSION,
672
-            true
673
-        );
674
-        wp_enqueue_script('espresso_reg');
675
-    }
676
-
677
-
678
-    public function load_scripts_styles_edit_attendee()
679
-    {
680
-        // stuff to only show up on our attendee edit details page.
681
-        $attendee_details_translations = array(
682
-            'att_publish_text' => sprintf(
683
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
-                $this->_cpt_model_obj->get_datetime('ATT_created')
685
-            ),
686
-        );
687
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
-        wp_enqueue_script('jquery-validate');
689
-    }
690
-
691
-
692
-    public function load_scripts_styles_view_registration()
693
-    {
694
-        // styles
695
-        wp_enqueue_style('espresso-ui-theme');
696
-        // scripts
697
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
698
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
-    }
700
-
701
-
702
-    public function load_scripts_styles_contact_list()
703
-    {
704
-        wp_dequeue_style('espresso_reg');
705
-        wp_register_style(
706
-            'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
-            array('ee-admin-css'),
709
-            EVENT_ESPRESSO_VERSION
710
-        );
711
-        wp_enqueue_style('espresso_att');
712
-    }
713
-
714
-
715
-    public function load_scripts_styles_new_registration()
716
-    {
717
-        wp_register_script(
718
-            'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
720
-            array('underscore', 'jquery'),
721
-            EVENT_ESPRESSO_VERSION,
722
-            true
723
-        );
724
-        wp_enqueue_script('ee-spco-for-admin');
725
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
-        EE_Form_Section_Proper::wp_enqueue_scripts();
727
-        EED_Ticket_Selector::load_tckt_slctr_assets();
728
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
729
-    }
730
-
731
-
732
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
-    {
734
-        add_filter('FHEE_load_EE_messages', '__return_true');
735
-    }
736
-
737
-
738
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
-    {
740
-        add_filter('FHEE_load_EE_messages', '__return_true');
741
-    }
742
-
743
-
744
-    protected function _set_list_table_views_default()
745
-    {
746
-        // for notification related bulk actions we need to make sure only active messengers have an option.
747
-        EED_Messages::set_autoloaders();
748
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
749
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
-        $active_mts = $message_resource_manager->list_of_active_message_types();
751
-        // key= bulk_action_slug, value= message type.
752
-        $match_array = array(
753
-            'approve_registrations'    => 'registration',
754
-            'decline_registrations'    => 'declined_registration',
755
-            'pending_registrations'    => 'pending_approval',
756
-            'no_approve_registrations' => 'not_approved_registration',
757
-            'cancel_registrations'     => 'cancelled_registration',
758
-        );
759
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
760
-            'ee_send_message',
761
-            'batch_send_messages'
762
-        );
763
-        /** setup reg status bulk actions **/
764
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
-                'Approve and Notify Registrations',
768
-                'event_espresso'
769
-            );
770
-        }
771
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
-                'Decline and Notify Registrations',
775
-                'event_espresso'
776
-            );
777
-        }
778
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
779
-            'Set Registrations to Pending Payment',
780
-            'event_espresso'
781
-        );
782
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
-                'Set Registrations to Pending Payment and Notify',
785
-                'event_espresso'
786
-            );
787
-        }
788
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
-            'Set Registrations to Not Approved',
790
-            'event_espresso'
791
-        );
792
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
-                'Set Registrations to Not Approved and Notify',
795
-                'event_espresso'
796
-            );
797
-        }
798
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
-                'Cancel Registrations and Notify',
802
-                'event_espresso'
803
-            );
804
-        }
805
-        $def_reg_status_actions = apply_filters(
806
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
-            $def_reg_status_actions,
808
-            $active_mts,
809
-            $can_send
810
-        );
811
-
812
-        $this->_views = array(
813
-            'all'   => array(
814
-                'slug'        => 'all',
815
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
-                'count'       => 0,
817
-                'bulk_action' => array_merge(
818
-                    $def_reg_status_actions,
819
-                    array(
820
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
-                    )
822
-                ),
823
-            ),
824
-            'month' => array(
825
-                'slug'        => 'month',
826
-                'label'       => esc_html__('This Month', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge(
829
-                    $def_reg_status_actions,
830
-                    array(
831
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
-                    )
833
-                ),
834
-            ),
835
-            'today' => array(
836
-                'slug'        => 'today',
837
-                'label'       => sprintf(
838
-                    esc_html__('Today - %s', 'event_espresso'),
839
-                    date('M d, Y', current_time('timestamp'))
840
-                ),
841
-                'count'       => 0,
842
-                'bulk_action' => array_merge(
843
-                    $def_reg_status_actions,
844
-                    array(
845
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
-                    )
847
-                ),
848
-            ),
849
-        );
850
-        if (EE_Registry::instance()->CAP->current_user_can(
851
-            'ee_delete_registrations',
852
-            'espresso_registrations_delete_registration'
853
-        )) {
854
-            $this->_views['incomplete'] = array(
855
-                'slug'        => 'incomplete',
856
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => array(
859
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
-                ),
861
-            );
862
-            $this->_views['trash'] = array(
863
-                'slug'        => 'trash',
864
-                'label'       => esc_html__('Trash', 'event_espresso'),
865
-                'count'       => 0,
866
-                'bulk_action' => array(
867
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
-                ),
870
-            );
871
-        }
872
-    }
873
-
874
-
875
-    protected function _set_list_table_views_contact_list()
876
-    {
877
-        $this->_views = array(
878
-            'in_use' => array(
879
-                'slug'        => 'in_use',
880
-                'label'       => esc_html__('In Use', 'event_espresso'),
881
-                'count'       => 0,
882
-                'bulk_action' => array(
883
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
-                ),
885
-            ),
886
-        );
887
-        if (EE_Registry::instance()->CAP->current_user_can(
888
-            'ee_delete_contacts',
889
-            'espresso_registrations_trash_attendees'
890
-        )
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post'   => $ATT_ID,
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                    . EE_Admin_Page::add_query_args_and_nonce(
1070
-                        array(
1071
-                            'action' => 'edit',
1072
-                            'post'   => $event->ID(),
1073
-                        ),
1074
-                        EVENTS_ADMIN_URL
1075
-                    )
1076
-                    . '">&nbsp;'
1077
-                    . $event->get('EVT_name')
1078
-                    . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        // get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         *
1166
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
-         *                             or if you have the development copy of EE you can view this at the path:
1169
-         *                             /docs/G--Model-System/model-query-params.md
1170
-         */
1171
-        $query_params['group_by'] = '';
1172
-
1173
-        return $count
1174
-            ? EEM_Registration::instance()->count($query_params)
1175
-            /** @type EE_Registration[] */
1176
-            : EEM_Registration::instance()->get_all($query_params);
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
-     * Note: this listens to values on the request for some of the query parameters.
1183
-     *
1184
-     * @param array $request
1185
-     * @param int   $per_page
1186
-     * @param bool  $count
1187
-     * @return array
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _get_registration_query_parameters(
1191
-        $request = array(),
1192
-        $per_page = 10,
1193
-        $count = false
1194
-    ) {
1195
-
1196
-        $query_params = array(
1197
-            0                          => $this->_get_where_conditions_for_registrations_query(
1198
-                $request
1199
-            ),
1200
-            'caps'                     => EEM_Registration::caps_read_admin,
1201
-            'default_where_conditions' => 'this_model_only',
1202
-        );
1203
-        if (! $count) {
1204
-            $query_params = array_merge(
1205
-                $query_params,
1206
-                $this->_get_orderby_for_registrations_query(),
1207
-                $this->_get_limit($per_page)
1208
-            );
1209
-        }
1210
-
1211
-        return $query_params;
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
-     *
1218
-     * @param array $request usually the same as $this->_req_data but not necessarily
1219
-     * @return array
1220
-     */
1221
-    protected function addAttendeeIdToWhereConditions(array $request)
1222
-    {
1223
-        $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1225
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1226
-        }
1227
-        return $where;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
-     *
1234
-     * @param array $request usually the same as $this->_req_data but not necessarily
1235
-     * @return array
1236
-     */
1237
-    protected function _add_event_id_to_where_conditions(array $request)
1238
-    {
1239
-        $where = array();
1240
-        if (! empty($request['event_id'])) {
1241
-            $where['EVT_ID'] = absint($request['event_id']);
1242
-        }
1243
-        return $where;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
-     *
1250
-     * @param array $request usually the same as $this->_req_data but not necessarily
1251
-     * @return array
1252
-     */
1253
-    protected function _add_category_id_to_where_conditions(array $request)
1254
-    {
1255
-        $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
-        }
1259
-        return $where;
1260
-    }
1261
-
1262
-
1263
-    /**
1264
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
-     *
1266
-     * @param array $request usually the same as $this->_req_data but not necessarily
1267
-     * @return array
1268
-     */
1269
-    protected function _add_datetime_id_to_where_conditions(array $request)
1270
-    {
1271
-        $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
-        }
1275
-        if (! empty($request['DTT_ID'])) {
1276
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
-        }
1278
-        return $where;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * Adds the correct registration status to the where conditions for the registrations query.
1284
-     *
1285
-     * @param array $request usually the same as $this->_req_data but not necessarily
1286
-     * @return array
1287
-     */
1288
-    protected function _add_registration_status_to_where_conditions(array $request)
1289
-    {
1290
-        $where = array();
1291
-        $view = EEH_Array::is_set($request, 'status', '');
1292
-        $registration_status = ! empty($request['_reg_status'])
1293
-            ? sanitize_text_field($request['_reg_status'])
1294
-            : '';
1295
-
1296
-        /*
22
+	/**
23
+	 * @var EE_Registration
24
+	 */
25
+	private $_registration;
26
+
27
+	/**
28
+	 * @var EE_Event
29
+	 */
30
+	private $_reg_event;
31
+
32
+	/**
33
+	 * @var EE_Session
34
+	 */
35
+	private $_session;
36
+
37
+	private static $_reg_status;
38
+
39
+	/**
40
+	 * Form for displaying the custom questions for this registration.
41
+	 * This gets used a few times throughout the request so its best to cache it
42
+	 *
43
+	 * @var EE_Registration_Custom_Questions_Form
44
+	 */
45
+	protected $_reg_custom_questions_form = null;
46
+
47
+
48
+	/**
49
+	 *        constructor
50
+	 *
51
+	 * @Constructor
52
+	 * @access public
53
+	 * @param bool $routing
54
+	 * @return Registrations_Admin_Page
55
+	 */
56
+	public function __construct($routing = true)
57
+	{
58
+		parent::__construct($routing);
59
+		add_action('wp_loaded', array($this, 'wp_loaded'));
60
+	}
61
+
62
+
63
+	public function wp_loaded()
64
+	{
65
+		// when adding a new registration...
66
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
+			EE_System::do_not_cache();
68
+			if (! isset($this->_req_data['processing_registration'])
69
+				|| absint($this->_req_data['processing_registration']) !== 1
70
+			) {
71
+				// and it's NOT the attendee information reg step
72
+				// force cookie expiration by setting time to last week
73
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
+				// and update the global
75
+				$_COOKIE['ee_registration_added'] = 0;
76
+			}
77
+		}
78
+	}
79
+
80
+
81
+	protected function _init_page_props()
82
+	{
83
+		$this->page_slug = REG_PG_SLUG;
84
+		$this->_admin_base_url = REG_ADMIN_URL;
85
+		$this->_admin_base_path = REG_ADMIN;
86
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
87
+		$this->_cpt_routes = array(
88
+			'add_new_attendee' => 'espresso_attendees',
89
+			'edit_attendee'    => 'espresso_attendees',
90
+			'insert_attendee'  => 'espresso_attendees',
91
+			'update_attendee'  => 'espresso_attendees',
92
+		);
93
+		$this->_cpt_model_names = array(
94
+			'add_new_attendee' => 'EEM_Attendee',
95
+			'edit_attendee'    => 'EEM_Attendee',
96
+		);
97
+		$this->_cpt_edit_routes = array(
98
+			'espresso_attendees' => 'edit_attendee',
99
+		);
100
+		$this->_pagenow_map = array(
101
+			'add_new_attendee' => 'post-new.php',
102
+			'edit_attendee'    => 'post.php',
103
+			'trash'            => 'post.php',
104
+		);
105
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
+		// add filters so that the comment urls don't take users to a confusing 404 page
107
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
+	}
109
+
110
+
111
+	public function clear_comment_link($link, $comment, $args)
112
+	{
113
+		// gotta make sure this only happens on this route
114
+		$post_type = get_post_type($comment->comment_post_ID);
115
+		if ($post_type === 'espresso_attendees') {
116
+			return '#commentsdiv';
117
+		}
118
+		return $link;
119
+	}
120
+
121
+
122
+	protected function _ajax_hooks()
123
+	{
124
+		// todo: all hooks for registrations ajax goes in here
125
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
+	}
127
+
128
+
129
+	protected function _define_page_props()
130
+	{
131
+		$this->_admin_page_title = $this->page_label;
132
+		$this->_labels = array(
133
+			'buttons'                      => array(
134
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
+			),
143
+			'publishbox'                   => array(
144
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
+			),
147
+			'hide_add_button_on_cpt_route' => array(
148
+				'edit_attendee' => true,
149
+			),
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 *        grab url requests and route them
156
+	 *
157
+	 * @access private
158
+	 * @return void
159
+	 */
160
+	public function _set_page_routes()
161
+	{
162
+		$this->_get_registration_status_array();
163
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
+			? $this->_req_data['_REG_ID'] : 0;
165
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
+			? $this->_req_data['reg_status_change_form']['REG_ID']
167
+			: $reg_id;
168
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
+			? $this->_req_data['ATT_ID'] : 0;
170
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
+			? $this->_req_data['post']
172
+			: $att_id;
173
+		$this->_page_routes = array(
174
+			'default'                             => array(
175
+				'func'       => '_registrations_overview_list_table',
176
+				'capability' => 'ee_read_registrations',
177
+			),
178
+			'view_registration'                   => array(
179
+				'func'       => '_registration_details',
180
+				'capability' => 'ee_read_registration',
181
+				'obj_id'     => $reg_id,
182
+			),
183
+			'edit_registration'                   => array(
184
+				'func'               => '_update_attendee_registration_form',
185
+				'noheader'           => true,
186
+				'headers_sent_route' => 'view_registration',
187
+				'capability'         => 'ee_edit_registration',
188
+				'obj_id'             => $reg_id,
189
+				'_REG_ID'            => $reg_id,
190
+			),
191
+			'trash_registrations'                 => array(
192
+				'func'       => '_trash_or_restore_registrations',
193
+				'args'       => array('trash' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_delete_registrations',
196
+			),
197
+			'restore_registrations'               => array(
198
+				'func'       => '_trash_or_restore_registrations',
199
+				'args'       => array('trash' => false),
200
+				'noheader'   => true,
201
+				'capability' => 'ee_delete_registrations',
202
+			),
203
+			'delete_registrations'                => array(
204
+				'func'       => '_delete_registrations',
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'new_registration'                    => array(
209
+				'func'       => 'new_registration',
210
+				'capability' => 'ee_edit_registrations',
211
+			),
212
+			'process_reg_step'                    => array(
213
+				'func'       => 'process_reg_step',
214
+				'noheader'   => true,
215
+				'capability' => 'ee_edit_registrations',
216
+			),
217
+			'redirect_to_txn'                     => array(
218
+				'func'       => 'redirect_to_txn',
219
+				'noheader'   => true,
220
+				'capability' => 'ee_edit_registrations',
221
+			),
222
+			'change_reg_status'                   => array(
223
+				'func'       => '_change_reg_status',
224
+				'noheader'   => true,
225
+				'capability' => 'ee_edit_registration',
226
+				'obj_id'     => $reg_id,
227
+			),
228
+			'approve_registration'                => array(
229
+				'func'       => 'approve_registration',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registration',
232
+				'obj_id'     => $reg_id,
233
+			),
234
+			'approve_and_notify_registration'     => array(
235
+				'func'       => 'approve_registration',
236
+				'noheader'   => true,
237
+				'args'       => array(true),
238
+				'capability' => 'ee_edit_registration',
239
+				'obj_id'     => $reg_id,
240
+			),
241
+			'approve_registrations'               => array(
242
+				'func'       => 'bulk_action_on_registrations',
243
+				'noheader'   => true,
244
+				'capability' => 'ee_edit_registrations',
245
+				'args'       => array('approve'),
246
+			),
247
+			'approve_and_notify_registrations'    => array(
248
+				'func'       => 'bulk_action_on_registrations',
249
+				'noheader'   => true,
250
+				'capability' => 'ee_edit_registrations',
251
+				'args'       => array('approve', true),
252
+			),
253
+			'decline_registration'                => array(
254
+				'func'       => 'decline_registration',
255
+				'noheader'   => true,
256
+				'capability' => 'ee_edit_registration',
257
+				'obj_id'     => $reg_id,
258
+			),
259
+			'decline_and_notify_registration'     => array(
260
+				'func'       => 'decline_registration',
261
+				'noheader'   => true,
262
+				'args'       => array(true),
263
+				'capability' => 'ee_edit_registration',
264
+				'obj_id'     => $reg_id,
265
+			),
266
+			'decline_registrations'               => array(
267
+				'func'       => 'bulk_action_on_registrations',
268
+				'noheader'   => true,
269
+				'capability' => 'ee_edit_registrations',
270
+				'args'       => array('decline'),
271
+			),
272
+			'decline_and_notify_registrations'    => array(
273
+				'func'       => 'bulk_action_on_registrations',
274
+				'noheader'   => true,
275
+				'capability' => 'ee_edit_registrations',
276
+				'args'       => array('decline', true),
277
+			),
278
+			'pending_registration'                => array(
279
+				'func'       => 'pending_registration',
280
+				'noheader'   => true,
281
+				'capability' => 'ee_edit_registration',
282
+				'obj_id'     => $reg_id,
283
+			),
284
+			'pending_and_notify_registration'     => array(
285
+				'func'       => 'pending_registration',
286
+				'noheader'   => true,
287
+				'args'       => array(true),
288
+				'capability' => 'ee_edit_registration',
289
+				'obj_id'     => $reg_id,
290
+			),
291
+			'pending_registrations'               => array(
292
+				'func'       => 'bulk_action_on_registrations',
293
+				'noheader'   => true,
294
+				'capability' => 'ee_edit_registrations',
295
+				'args'       => array('pending'),
296
+			),
297
+			'pending_and_notify_registrations'    => array(
298
+				'func'       => 'bulk_action_on_registrations',
299
+				'noheader'   => true,
300
+				'capability' => 'ee_edit_registrations',
301
+				'args'       => array('pending', true),
302
+			),
303
+			'no_approve_registration'             => array(
304
+				'func'       => 'not_approve_registration',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'no_approve_and_notify_registration'  => array(
310
+				'func'       => 'not_approve_registration',
311
+				'noheader'   => true,
312
+				'args'       => array(true),
313
+				'capability' => 'ee_edit_registration',
314
+				'obj_id'     => $reg_id,
315
+			),
316
+			'no_approve_registrations'            => array(
317
+				'func'       => 'bulk_action_on_registrations',
318
+				'noheader'   => true,
319
+				'capability' => 'ee_edit_registrations',
320
+				'args'       => array('not_approve'),
321
+			),
322
+			'no_approve_and_notify_registrations' => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('not_approve', true),
327
+			),
328
+			'cancel_registration'                 => array(
329
+				'func'       => 'cancel_registration',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registration',
332
+				'obj_id'     => $reg_id,
333
+			),
334
+			'cancel_and_notify_registration'      => array(
335
+				'func'       => 'cancel_registration',
336
+				'noheader'   => true,
337
+				'args'       => array(true),
338
+				'capability' => 'ee_edit_registration',
339
+				'obj_id'     => $reg_id,
340
+			),
341
+			'cancel_registrations'                => array(
342
+				'func'       => 'bulk_action_on_registrations',
343
+				'noheader'   => true,
344
+				'capability' => 'ee_edit_registrations',
345
+				'args'       => array('cancel'),
346
+			),
347
+			'cancel_and_notify_registrations'     => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('cancel', true),
352
+			),
353
+			'wait_list_registration'              => array(
354
+				'func'       => 'wait_list_registration',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registration',
357
+				'obj_id'     => $reg_id,
358
+			),
359
+			'wait_list_and_notify_registration'   => array(
360
+				'func'       => 'wait_list_registration',
361
+				'noheader'   => true,
362
+				'args'       => array(true),
363
+				'capability' => 'ee_edit_registration',
364
+				'obj_id'     => $reg_id,
365
+			),
366
+			'contact_list'                        => array(
367
+				'func'       => '_attendee_contact_list_table',
368
+				'capability' => 'ee_read_contacts',
369
+			),
370
+			'add_new_attendee'                    => array(
371
+				'func' => '_create_new_cpt_item',
372
+				'args' => array(
373
+					'new_attendee' => true,
374
+					'capability'   => 'ee_edit_contacts',
375
+				),
376
+			),
377
+			'edit_attendee'                       => array(
378
+				'func'       => '_edit_cpt_item',
379
+				'capability' => 'ee_edit_contacts',
380
+				'obj_id'     => $att_id,
381
+			),
382
+			'duplicate_attendee'                  => array(
383
+				'func'       => '_duplicate_attendee',
384
+				'noheader'   => true,
385
+				'capability' => 'ee_edit_contacts',
386
+				'obj_id'     => $att_id,
387
+			),
388
+			'insert_attendee'                     => array(
389
+				'func'       => '_insert_or_update_attendee',
390
+				'args'       => array(
391
+					'new_attendee' => true,
392
+				),
393
+				'noheader'   => true,
394
+				'capability' => 'ee_edit_contacts',
395
+			),
396
+			'update_attendee'                     => array(
397
+				'func'       => '_insert_or_update_attendee',
398
+				'args'       => array(
399
+					'new_attendee' => false,
400
+				),
401
+				'noheader'   => true,
402
+				'capability' => 'ee_edit_contacts',
403
+				'obj_id'     => $att_id,
404
+			),
405
+			'trash_attendees'                     => array(
406
+				'func'       => '_trash_or_restore_attendees',
407
+				'args'       => array(
408
+					'trash' => 'true',
409
+				),
410
+				'noheader'   => true,
411
+				'capability' => 'ee_delete_contacts',
412
+			),
413
+			'trash_attendee'                      => array(
414
+				'func'       => '_trash_or_restore_attendees',
415
+				'args'       => array(
416
+					'trash' => true,
417
+				),
418
+				'noheader'   => true,
419
+				'capability' => 'ee_delete_contacts',
420
+				'obj_id'     => $att_id,
421
+			),
422
+			'restore_attendees'                   => array(
423
+				'func'       => '_trash_or_restore_attendees',
424
+				'args'       => array(
425
+					'trash' => false,
426
+				),
427
+				'noheader'   => true,
428
+				'capability' => 'ee_delete_contacts',
429
+				'obj_id'     => $att_id,
430
+			),
431
+			'resend_registration'                 => array(
432
+				'func'       => '_resend_registration',
433
+				'noheader'   => true,
434
+				'capability' => 'ee_send_message',
435
+			),
436
+			'registrations_report'                => array(
437
+				'func'       => '_registrations_report',
438
+				'noheader'   => true,
439
+				'capability' => 'ee_read_registrations',
440
+			),
441
+			'contact_list_export'                 => array(
442
+				'func'       => '_contact_list_export',
443
+				'noheader'   => true,
444
+				'capability' => 'export',
445
+			),
446
+			'contact_list_report'                 => array(
447
+				'func'       => '_contact_list_report',
448
+				'noheader'   => true,
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+		);
452
+	}
453
+
454
+
455
+	protected function _set_page_config()
456
+	{
457
+		$this->_page_config = array(
458
+			'default'           => array(
459
+				'nav'           => array(
460
+					'label' => esc_html__('Overview', 'event_espresso'),
461
+					'order' => 5,
462
+				),
463
+				'help_tabs'     => array(
464
+					'registrations_overview_help_tab'                       => array(
465
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
+						'filename' => 'registrations_overview',
467
+					),
468
+					'registrations_overview_table_column_headings_help_tab' => array(
469
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
+						'filename' => 'registrations_overview_table_column_headings',
471
+					),
472
+					'registrations_overview_filters_help_tab'               => array(
473
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
+						'filename' => 'registrations_overview_filters',
475
+					),
476
+					'registrations_overview_views_help_tab'                 => array(
477
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
478
+						'filename' => 'registrations_overview_views',
479
+					),
480
+					'registrations_regoverview_other_help_tab'              => array(
481
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
+						'filename' => 'registrations_overview_other',
483
+					),
484
+				),
485
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
486
+				'qtips'         => array('Registration_List_Table_Tips'),
487
+				'list_table'    => 'EE_Registrations_List_Table',
488
+				'require_nonce' => false,
489
+			),
490
+			'view_registration' => array(
491
+				'nav'           => array(
492
+					'label'      => esc_html__('REG Details', 'event_espresso'),
493
+					'order'      => 15,
494
+					'url'        => isset($this->_req_data['_REG_ID'])
495
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
+						: $this->_admin_base_url,
497
+					'persistent' => false,
498
+				),
499
+				'help_tabs'     => array(
500
+					'registrations_details_help_tab'                    => array(
501
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
502
+						'filename' => 'registrations_details',
503
+					),
504
+					'registrations_details_table_help_tab'              => array(
505
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
+						'filename' => 'registrations_details_table',
507
+					),
508
+					'registrations_details_form_answers_help_tab'       => array(
509
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
+						'filename' => 'registrations_details_form_answers',
511
+					),
512
+					'registrations_details_registrant_details_help_tab' => array(
513
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
514
+						'filename' => 'registrations_details_registrant_details',
515
+					),
516
+				),
517
+				'help_tour'     => array('Registration_Details_Help_Tour'),
518
+				'metaboxes'     => array_merge(
519
+					$this->_default_espresso_metaboxes,
520
+					array('_registration_details_metaboxes')
521
+				),
522
+				'require_nonce' => false,
523
+			),
524
+			'new_registration'  => array(
525
+				'nav'           => array(
526
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
+					'url'        => '#',
528
+					'order'      => 15,
529
+					'persistent' => false,
530
+				),
531
+				'metaboxes'     => $this->_default_espresso_metaboxes,
532
+				'labels'        => array(
533
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
+				),
535
+				'require_nonce' => false,
536
+			),
537
+			'add_new_attendee'  => array(
538
+				'nav'           => array(
539
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
540
+					'order'      => 15,
541
+					'persistent' => false,
542
+				),
543
+				'metaboxes'     => array_merge(
544
+					$this->_default_espresso_metaboxes,
545
+					array('_publish_post_box', 'attendee_editor_metaboxes')
546
+				),
547
+				'require_nonce' => false,
548
+			),
549
+			'edit_attendee'     => array(
550
+				'nav'           => array(
551
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
+					'order'      => 15,
553
+					'persistent' => false,
554
+					'url'        => isset($this->_req_data['ATT_ID'])
555
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
+						: $this->_admin_base_url,
557
+				),
558
+				'metaboxes'     => array('attendee_editor_metaboxes'),
559
+				'require_nonce' => false,
560
+			),
561
+			'contact_list'      => array(
562
+				'nav'           => array(
563
+					'label' => esc_html__('Contact List', 'event_espresso'),
564
+					'order' => 20,
565
+				),
566
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
567
+				'help_tabs'     => array(
568
+					'registrations_contact_list_help_tab'                       => array(
569
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
+						'filename' => 'registrations_contact_list',
571
+					),
572
+					'registrations_contact-list_table_column_headings_help_tab' => array(
573
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
+						'filename' => 'registrations_contact_list_table_column_headings',
575
+					),
576
+					'registrations_contact_list_views_help_tab'                 => array(
577
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
+						'filename' => 'registrations_contact_list_views',
579
+					),
580
+					'registrations_contact_list_other_help_tab'                 => array(
581
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
+						'filename' => 'registrations_contact_list_other',
583
+					),
584
+				),
585
+				'help_tour'     => array('Contact_List_Help_Tour'),
586
+				'metaboxes'     => array(),
587
+				'require_nonce' => false,
588
+			),
589
+			// override default cpt routes
590
+			'create_new'        => '',
591
+			'edit'              => '',
592
+		);
593
+	}
594
+
595
+
596
+	/**
597
+	 * The below methods aren't used by this class currently
598
+	 */
599
+	protected function _add_screen_options()
600
+	{
601
+	}
602
+
603
+
604
+	protected function _add_feature_pointers()
605
+	{
606
+	}
607
+
608
+
609
+	public function admin_init()
610
+	{
611
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
+			'click "Update Registration Questions" to save your changes',
613
+			'event_espresso'
614
+		);
615
+	}
616
+
617
+
618
+	public function admin_notices()
619
+	{
620
+	}
621
+
622
+
623
+	public function admin_footer_scripts()
624
+	{
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get list of registration statuses
630
+	 *
631
+	 * @access private
632
+	 * @return void
633
+	 * @throws EE_Error
634
+	 */
635
+	private function _get_registration_status_array()
636
+	{
637
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
+	}
639
+
640
+
641
+	protected function _add_screen_options_default()
642
+	{
643
+		$this->_per_page_screen_option();
644
+	}
645
+
646
+
647
+	protected function _add_screen_options_contact_list()
648
+	{
649
+		$page_title = $this->_admin_page_title;
650
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
+		$this->_per_page_screen_option();
652
+		$this->_admin_page_title = $page_title;
653
+	}
654
+
655
+
656
+	public function load_scripts_styles()
657
+	{
658
+		// style
659
+		wp_register_style(
660
+			'espresso_reg',
661
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
+			array('ee-admin-css'),
663
+			EVENT_ESPRESSO_VERSION
664
+		);
665
+		wp_enqueue_style('espresso_reg');
666
+		// script
667
+		wp_register_script(
668
+			'espresso_reg',
669
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
+			EVENT_ESPRESSO_VERSION,
672
+			true
673
+		);
674
+		wp_enqueue_script('espresso_reg');
675
+	}
676
+
677
+
678
+	public function load_scripts_styles_edit_attendee()
679
+	{
680
+		// stuff to only show up on our attendee edit details page.
681
+		$attendee_details_translations = array(
682
+			'att_publish_text' => sprintf(
683
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
+				$this->_cpt_model_obj->get_datetime('ATT_created')
685
+			),
686
+		);
687
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
+		wp_enqueue_script('jquery-validate');
689
+	}
690
+
691
+
692
+	public function load_scripts_styles_view_registration()
693
+	{
694
+		// styles
695
+		wp_enqueue_style('espresso-ui-theme');
696
+		// scripts
697
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
698
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
+	}
700
+
701
+
702
+	public function load_scripts_styles_contact_list()
703
+	{
704
+		wp_dequeue_style('espresso_reg');
705
+		wp_register_style(
706
+			'espresso_att',
707
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
+			array('ee-admin-css'),
709
+			EVENT_ESPRESSO_VERSION
710
+		);
711
+		wp_enqueue_style('espresso_att');
712
+	}
713
+
714
+
715
+	public function load_scripts_styles_new_registration()
716
+	{
717
+		wp_register_script(
718
+			'ee-spco-for-admin',
719
+			REG_ASSETS_URL . 'spco_for_admin.js',
720
+			array('underscore', 'jquery'),
721
+			EVENT_ESPRESSO_VERSION,
722
+			true
723
+		);
724
+		wp_enqueue_script('ee-spco-for-admin');
725
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
+		EE_Form_Section_Proper::wp_enqueue_scripts();
727
+		EED_Ticket_Selector::load_tckt_slctr_assets();
728
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
729
+	}
730
+
731
+
732
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
+	{
734
+		add_filter('FHEE_load_EE_messages', '__return_true');
735
+	}
736
+
737
+
738
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
+	{
740
+		add_filter('FHEE_load_EE_messages', '__return_true');
741
+	}
742
+
743
+
744
+	protected function _set_list_table_views_default()
745
+	{
746
+		// for notification related bulk actions we need to make sure only active messengers have an option.
747
+		EED_Messages::set_autoloaders();
748
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
749
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
+		$active_mts = $message_resource_manager->list_of_active_message_types();
751
+		// key= bulk_action_slug, value= message type.
752
+		$match_array = array(
753
+			'approve_registrations'    => 'registration',
754
+			'decline_registrations'    => 'declined_registration',
755
+			'pending_registrations'    => 'pending_approval',
756
+			'no_approve_registrations' => 'not_approved_registration',
757
+			'cancel_registrations'     => 'cancelled_registration',
758
+		);
759
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
760
+			'ee_send_message',
761
+			'batch_send_messages'
762
+		);
763
+		/** setup reg status bulk actions **/
764
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
+				'Approve and Notify Registrations',
768
+				'event_espresso'
769
+			);
770
+		}
771
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
+				'Decline and Notify Registrations',
775
+				'event_espresso'
776
+			);
777
+		}
778
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
779
+			'Set Registrations to Pending Payment',
780
+			'event_espresso'
781
+		);
782
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
+				'Set Registrations to Pending Payment and Notify',
785
+				'event_espresso'
786
+			);
787
+		}
788
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
+			'Set Registrations to Not Approved',
790
+			'event_espresso'
791
+		);
792
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
+				'Set Registrations to Not Approved and Notify',
795
+				'event_espresso'
796
+			);
797
+		}
798
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
+				'Cancel Registrations and Notify',
802
+				'event_espresso'
803
+			);
804
+		}
805
+		$def_reg_status_actions = apply_filters(
806
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
+			$def_reg_status_actions,
808
+			$active_mts,
809
+			$can_send
810
+		);
811
+
812
+		$this->_views = array(
813
+			'all'   => array(
814
+				'slug'        => 'all',
815
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
+				'count'       => 0,
817
+				'bulk_action' => array_merge(
818
+					$def_reg_status_actions,
819
+					array(
820
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
+					)
822
+				),
823
+			),
824
+			'month' => array(
825
+				'slug'        => 'month',
826
+				'label'       => esc_html__('This Month', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge(
829
+					$def_reg_status_actions,
830
+					array(
831
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
+					)
833
+				),
834
+			),
835
+			'today' => array(
836
+				'slug'        => 'today',
837
+				'label'       => sprintf(
838
+					esc_html__('Today - %s', 'event_espresso'),
839
+					date('M d, Y', current_time('timestamp'))
840
+				),
841
+				'count'       => 0,
842
+				'bulk_action' => array_merge(
843
+					$def_reg_status_actions,
844
+					array(
845
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
+					)
847
+				),
848
+			),
849
+		);
850
+		if (EE_Registry::instance()->CAP->current_user_can(
851
+			'ee_delete_registrations',
852
+			'espresso_registrations_delete_registration'
853
+		)) {
854
+			$this->_views['incomplete'] = array(
855
+				'slug'        => 'incomplete',
856
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => array(
859
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
+				),
861
+			);
862
+			$this->_views['trash'] = array(
863
+				'slug'        => 'trash',
864
+				'label'       => esc_html__('Trash', 'event_espresso'),
865
+				'count'       => 0,
866
+				'bulk_action' => array(
867
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
+				),
870
+			);
871
+		}
872
+	}
873
+
874
+
875
+	protected function _set_list_table_views_contact_list()
876
+	{
877
+		$this->_views = array(
878
+			'in_use' => array(
879
+				'slug'        => 'in_use',
880
+				'label'       => esc_html__('In Use', 'event_espresso'),
881
+				'count'       => 0,
882
+				'bulk_action' => array(
883
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
+				),
885
+			),
886
+		);
887
+		if (EE_Registry::instance()->CAP->current_user_can(
888
+			'ee_delete_contacts',
889
+			'espresso_registrations_trash_attendees'
890
+		)
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post'   => $ATT_ID,
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+					. EE_Admin_Page::add_query_args_and_nonce(
1070
+						array(
1071
+							'action' => 'edit',
1072
+							'post'   => $event->ID(),
1073
+						),
1074
+						EVENTS_ADMIN_URL
1075
+					)
1076
+					. '">&nbsp;'
1077
+					. $event->get('EVT_name')
1078
+					. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		// get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG = EEM_Registration::instance();
1119
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 *
1166
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
+		 *                             or if you have the development copy of EE you can view this at the path:
1169
+		 *                             /docs/G--Model-System/model-query-params.md
1170
+		 */
1171
+		$query_params['group_by'] = '';
1172
+
1173
+		return $count
1174
+			? EEM_Registration::instance()->count($query_params)
1175
+			/** @type EE_Registration[] */
1176
+			: EEM_Registration::instance()->get_all($query_params);
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
+	 * Note: this listens to values on the request for some of the query parameters.
1183
+	 *
1184
+	 * @param array $request
1185
+	 * @param int   $per_page
1186
+	 * @param bool  $count
1187
+	 * @return array
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _get_registration_query_parameters(
1191
+		$request = array(),
1192
+		$per_page = 10,
1193
+		$count = false
1194
+	) {
1195
+
1196
+		$query_params = array(
1197
+			0                          => $this->_get_where_conditions_for_registrations_query(
1198
+				$request
1199
+			),
1200
+			'caps'                     => EEM_Registration::caps_read_admin,
1201
+			'default_where_conditions' => 'this_model_only',
1202
+		);
1203
+		if (! $count) {
1204
+			$query_params = array_merge(
1205
+				$query_params,
1206
+				$this->_get_orderby_for_registrations_query(),
1207
+				$this->_get_limit($per_page)
1208
+			);
1209
+		}
1210
+
1211
+		return $query_params;
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
+	 *
1218
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1219
+	 * @return array
1220
+	 */
1221
+	protected function addAttendeeIdToWhereConditions(array $request)
1222
+	{
1223
+		$where = array();
1224
+		if (! empty($request['ATT_ID'])) {
1225
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1226
+		}
1227
+		return $where;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
+	 *
1234
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1235
+	 * @return array
1236
+	 */
1237
+	protected function _add_event_id_to_where_conditions(array $request)
1238
+	{
1239
+		$where = array();
1240
+		if (! empty($request['event_id'])) {
1241
+			$where['EVT_ID'] = absint($request['event_id']);
1242
+		}
1243
+		return $where;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
+	 *
1250
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1251
+	 * @return array
1252
+	 */
1253
+	protected function _add_category_id_to_where_conditions(array $request)
1254
+	{
1255
+		$where = array();
1256
+		if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
+		}
1259
+		return $where;
1260
+	}
1261
+
1262
+
1263
+	/**
1264
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
+	 *
1266
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1267
+	 * @return array
1268
+	 */
1269
+	protected function _add_datetime_id_to_where_conditions(array $request)
1270
+	{
1271
+		$where = array();
1272
+		if (! empty($request['datetime_id'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
+		}
1275
+		if (! empty($request['DTT_ID'])) {
1276
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
+		}
1278
+		return $where;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * Adds the correct registration status to the where conditions for the registrations query.
1284
+	 *
1285
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1286
+	 * @return array
1287
+	 */
1288
+	protected function _add_registration_status_to_where_conditions(array $request)
1289
+	{
1290
+		$where = array();
1291
+		$view = EEH_Array::is_set($request, 'status', '');
1292
+		$registration_status = ! empty($request['_reg_status'])
1293
+			? sanitize_text_field($request['_reg_status'])
1294
+			: '';
1295
+
1296
+		/*
1297 1297
          * If filtering by registration status, then we show registrations matching that status.
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1302
-            $where['STS_ID'] = $registration_status;
1303
-        } else {
1304
-            // make sure we exclude incomplete registrations, but only if not trashed.
1305
-            if ($view === 'trash') {
1306
-                $where['REG_deleted'] = true;
1307
-            } elseif ($view === 'incomplete') {
1308
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
-            } else {
1310
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
-            }
1312
-        }
1313
-        return $where;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Adds any provided date restraints to the where conditions for the registrations query.
1319
-     *
1320
-     * @param array $request usually the same as $this->_req_data but not necessarily
1321
-     * @return array
1322
-     * @throws EE_Error
1323
-     * @throws InvalidArgumentException
1324
-     * @throws InvalidDataTypeException
1325
-     * @throws InvalidInterfaceException
1326
-     */
1327
-    protected function _add_date_to_where_conditions(array $request)
1328
-    {
1329
-        $where = array();
1330
-        $view = EEH_Array::is_set($request, 'status', '');
1331
-        $month_range = ! empty($request['month_range'])
1332
-            ? sanitize_text_field($request['month_range'])
1333
-            : '';
1334
-        $retrieve_for_today = $view === 'today';
1335
-        $retrieve_for_this_month = $view === 'month';
1336
-
1337
-        if ($retrieve_for_today) {
1338
-            $now = date('Y-m-d', current_time('timestamp'));
1339
-            $where['REG_date'] = array(
1340
-                'BETWEEN',
1341
-                array(
1342
-                    EEM_Registration::instance()->convert_datetime_for_query(
1343
-                        'REG_date',
1344
-                        $now . ' 00:00:00',
1345
-                        'Y-m-d H:i:s'
1346
-                    ),
1347
-                    EEM_Registration::instance()->convert_datetime_for_query(
1348
-                        'REG_date',
1349
-                        $now . ' 23:59:59',
1350
-                        'Y-m-d H:i:s'
1351
-                    ),
1352
-                ),
1353
-            );
1354
-        } elseif ($retrieve_for_this_month) {
1355
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1356
-            $days_this_month = date('t', current_time('timestamp'));
1357
-            $where['REG_date'] = array(
1358
-                'BETWEEN',
1359
-                array(
1360
-                    EEM_Registration::instance()->convert_datetime_for_query(
1361
-                        'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1363
-                        'Y-m-d H:i:s'
1364
-                    ),
1365
-                    EEM_Registration::instance()->convert_datetime_for_query(
1366
-                        'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
-                        'Y-m-d H:i:s'
1369
-                    ),
1370
-                ),
1371
-            );
1372
-        } elseif ($month_range) {
1373
-            $pieces = explode(' ', $month_range, 3);
1374
-            $month_requested = ! empty($pieces[0])
1375
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
-                : '';
1377
-            $year_requested = ! empty($pieces[1])
1378
-                ? $pieces[1]
1379
-                : '';
1380
-            // if there is not a month or year then we can't go further
1381
-            if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
-                $where['REG_date'] = array(
1384
-                    'BETWEEN',
1385
-                    array(
1386
-                        EEM_Registration::instance()->convert_datetime_for_query(
1387
-                            'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1389
-                            'Y-m-d H:i:s'
1390
-                        ),
1391
-                        EEM_Registration::instance()->convert_datetime_for_query(
1392
-                            'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
-                            'Y-m-d H:i:s'
1395
-                        ),
1396
-                    ),
1397
-                );
1398
-            }
1399
-        }
1400
-        return $where;
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * Adds any provided search restraints to the where conditions for the registrations query
1406
-     *
1407
-     * @param array $request usually the same as $this->_req_data but not necessarily
1408
-     * @return array
1409
-     */
1410
-    protected function _add_search_to_where_conditions(array $request)
1411
-    {
1412
-        $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
-            $where['OR*search_conditions'] = array(
1416
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1417
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
-                'REG_final_price'                         => array('LIKE', $search_string),
1428
-                'REG_code'                                => array('LIKE', $search_string),
1429
-                'REG_count'                               => array('LIKE', $search_string),
1430
-                'REG_group_size'                          => array('LIKE', $search_string),
1431
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
-            );
1435
-        }
1436
-        return $where;
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Sets up the where conditions for the registrations query.
1442
-     *
1443
-     * @param array $request
1444
-     * @return array
1445
-     * @throws EE_Error
1446
-     */
1447
-    protected function _get_where_conditions_for_registrations_query($request)
1448
-    {
1449
-        return apply_filters(
1450
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
-            array_merge(
1452
-                $this->addAttendeeIdToWhereConditions($request),
1453
-                $this->_add_event_id_to_where_conditions($request),
1454
-                $this->_add_category_id_to_where_conditions($request),
1455
-                $this->_add_datetime_id_to_where_conditions($request),
1456
-                $this->_add_registration_status_to_where_conditions($request),
1457
-                $this->_add_date_to_where_conditions($request),
1458
-                $this->_add_search_to_where_conditions($request)
1459
-            ),
1460
-            $request
1461
-        );
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * Sets up the orderby for the registrations query.
1467
-     *
1468
-     * @return array
1469
-     */
1470
-    protected function _get_orderby_for_registrations_query()
1471
-    {
1472
-        $orderby_field = ! empty($this->_req_data['orderby'])
1473
-            ? sanitize_text_field($this->_req_data['orderby'])
1474
-            : '_REG_date';
1475
-        switch ($orderby_field) {
1476
-            case '_REG_ID':
1477
-                $orderby = array('REG_ID');
1478
-                break;
1479
-            case '_Reg_status':
1480
-                $orderby = array('STS_ID');
1481
-                break;
1482
-            case 'ATT_fname':
1483
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
-                break;
1485
-            case 'ATT_lname':
1486
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
-                break;
1488
-            case 'event_name':
1489
-                $orderby = array('Event.EVT_name');
1490
-                break;
1491
-            case 'DTT_EVT_start':
1492
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1493
-                break;
1494
-            case '_REG_date':
1495
-                $orderby = array('REG_date');
1496
-                break;
1497
-            default:
1498
-                $orderby = array($orderby_field);
1499
-                break;
1500
-        }
1501
-
1502
-        // order
1503
-        $order = ! empty($this->_req_data['order'])
1504
-            ? sanitize_text_field($this->_req_data['order'])
1505
-            : 'DESC';
1506
-        $orderby = array_combine(
1507
-            $orderby,
1508
-            array_fill(0, count($orderby), $order)
1509
-        );
1510
-        // because there are many registrations with the same date, define
1511
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
1512
-        if (empty($orderby['REG_ID'])) {
1513
-            $orderby['REG_ID'] = $order;
1514
-        }
1515
-
1516
-        $orderby = apply_filters(
1517
-            'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
-            $orderby,
1519
-            $this->_req_data
1520
-        );
1521
-
1522
-        return array('order_by' => $orderby);
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * Sets up the limit for the registrations query.
1528
-     *
1529
-     * @param $per_page
1530
-     * @return array
1531
-     */
1532
-    protected function _get_limit($per_page)
1533
-    {
1534
-        $current_page = ! empty($this->_req_data['paged'])
1535
-            ? absint($this->_req_data['paged'])
1536
-            : 1;
1537
-        $per_page = ! empty($this->_req_data['perpage'])
1538
-            ? $this->_req_data['perpage']
1539
-            : $per_page;
1540
-
1541
-        // -1 means return all results so get out if that's set.
1542
-        if ((int) $per_page === -1) {
1543
-            return array();
1544
-        }
1545
-        $per_page = absint($per_page);
1546
-        $offset = ($current_page - 1) * $per_page;
1547
-        return array('limit' => array($offset, $per_page));
1548
-    }
1549
-
1550
-
1551
-    public function get_registration_status_array()
1552
-    {
1553
-        return self::$_reg_status;
1554
-    }
1555
-
1556
-
1557
-
1558
-
1559
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1560
-    /**
1561
-     *        generates HTML for the View Registration Details Admin page
1562
-     *
1563
-     * @access protected
1564
-     * @return void
1565
-     * @throws DomainException
1566
-     * @throws EE_Error
1567
-     * @throws InvalidArgumentException
1568
-     * @throws InvalidDataTypeException
1569
-     * @throws InvalidInterfaceException
1570
-     * @throws EntityNotFoundException
1571
-     */
1572
-    protected function _registration_details()
1573
-    {
1574
-        $this->_template_args = array();
1575
-        $this->_set_registration_object();
1576
-        if (is_object($this->_registration)) {
1577
-            $transaction = $this->_registration->transaction()
1578
-                ? $this->_registration->transaction()
1579
-                : EE_Transaction::new_instance();
1580
-            $this->_session = $transaction->session_data();
1581
-            $event_id = $this->_registration->event_ID();
1582
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
-            $this->_template_args['grand_total'] = $transaction->total();
1587
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
-            // link back to overview
1589
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
-            $this->_template_args['registration'] = $this->_registration;
1591
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
-                array(
1593
-                    'action'   => 'default',
1594
-                    'event_id' => $event_id,
1595
-                ),
1596
-                REG_ADMIN_URL
1597
-            );
1598
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
-                array(
1600
-                    'action' => 'default',
1601
-                    'EVT_ID' => $event_id,
1602
-                    'page'   => 'espresso_transactions',
1603
-                ),
1604
-                admin_url('admin.php')
1605
-            );
1606
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
-                array(
1608
-                    'page'   => 'espresso_events',
1609
-                    'action' => 'edit',
1610
-                    'post'   => $event_id,
1611
-                ),
1612
-                admin_url('admin.php')
1613
-            );
1614
-            // next and previous links
1615
-            $next_reg = $this->_registration->next(
1616
-                null,
1617
-                array(),
1618
-                'REG_ID'
1619
-            );
1620
-            $this->_template_args['next_registration'] = $next_reg
1621
-                ? $this->_next_link(
1622
-                    EE_Admin_Page::add_query_args_and_nonce(
1623
-                        array(
1624
-                            'action'  => 'view_registration',
1625
-                            '_REG_ID' => $next_reg['REG_ID'],
1626
-                        ),
1627
-                        REG_ADMIN_URL
1628
-                    ),
1629
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1630
-                )
1631
-                : '';
1632
-            $previous_reg = $this->_registration->previous(
1633
-                null,
1634
-                array(),
1635
-                'REG_ID'
1636
-            );
1637
-            $this->_template_args['previous_registration'] = $previous_reg
1638
-                ? $this->_previous_link(
1639
-                    EE_Admin_Page::add_query_args_and_nonce(
1640
-                        array(
1641
-                            'action'  => 'view_registration',
1642
-                            '_REG_ID' => $previous_reg['REG_ID'],
1643
-                        ),
1644
-                        REG_ADMIN_URL
1645
-                    ),
1646
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1647
-                )
1648
-                : '';
1649
-            // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1652
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
-                $template_path,
1654
-                $this->_template_args,
1655
-                true
1656
-            );
1657
-        } else {
1658
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
-        }
1660
-        // the details template wrapper
1661
-        $this->display_admin_page_with_sidebar();
1662
-    }
1663
-
1664
-
1665
-    protected function _registration_details_metaboxes()
1666
-    {
1667
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
-        $this->_set_registration_object();
1669
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
-        add_meta_box(
1671
-            'edit-reg-status-mbox',
1672
-            esc_html__('Registration Status', 'event_espresso'),
1673
-            array($this, 'set_reg_status_buttons_metabox'),
1674
-            $this->wp_page_slug,
1675
-            'normal',
1676
-            'high'
1677
-        );
1678
-        add_meta_box(
1679
-            'edit-reg-details-mbox',
1680
-            esc_html__('Registration Details', 'event_espresso'),
1681
-            array($this, '_reg_details_meta_box'),
1682
-            $this->wp_page_slug,
1683
-            'normal',
1684
-            'high'
1685
-        );
1686
-        if ($attendee instanceof EE_Attendee
1687
-            && EE_Registry::instance()->CAP->current_user_can(
1688
-                'ee_read_registration',
1689
-                'edit-reg-questions-mbox',
1690
-                $this->_registration->ID()
1691
-            )
1692
-        ) {
1693
-            add_meta_box(
1694
-                'edit-reg-questions-mbox',
1695
-                esc_html__('Registration Form Answers', 'event_espresso'),
1696
-                array($this, '_reg_questions_meta_box'),
1697
-                $this->wp_page_slug,
1698
-                'normal',
1699
-                'high'
1700
-            );
1701
-        }
1702
-        add_meta_box(
1703
-            'edit-reg-registrant-mbox',
1704
-            esc_html__('Contact Details', 'event_espresso'),
1705
-            array($this, '_reg_registrant_side_meta_box'),
1706
-            $this->wp_page_slug,
1707
-            'side',
1708
-            'high'
1709
-        );
1710
-        if ($this->_registration->group_size() > 1) {
1711
-            add_meta_box(
1712
-                'edit-reg-attendees-mbox',
1713
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
-                array($this, '_reg_attendees_meta_box'),
1715
-                $this->wp_page_slug,
1716
-                'normal',
1717
-                'high'
1718
-            );
1719
-        }
1720
-    }
1721
-
1722
-
1723
-    /**
1724
-     * set_reg_status_buttons_metabox
1725
-     *
1726
-     * @access protected
1727
-     * @return string
1728
-     * @throws \EE_Error
1729
-     */
1730
-    public function set_reg_status_buttons_metabox()
1731
-    {
1732
-        $this->_set_registration_object();
1733
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1734
-        echo $change_reg_status_form->form_open(
1735
-            self::add_query_args_and_nonce(
1736
-                array(
1737
-                    'action' => 'change_reg_status',
1738
-                ),
1739
-                REG_ADMIN_URL
1740
-            )
1741
-        );
1742
-        echo $change_reg_status_form->get_html();
1743
-        echo $change_reg_status_form->form_close();
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     * @return EE_Form_Section_Proper
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
-     */
1755
-    protected function _generate_reg_status_change_form()
1756
-    {
1757
-        $reg_status_change_form_array = array(
1758
-            'name'            => 'reg_status_change_form',
1759
-            'html_id'         => 'reg-status-change-form',
1760
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
-            'subsections'     => array(
1762
-                'return'             => new EE_Hidden_Input(
1763
-                    array(
1764
-                        'name'    => 'return',
1765
-                        'default' => 'view_registration',
1766
-                    )
1767
-                ),
1768
-                'REG_ID'             => new EE_Hidden_Input(
1769
-                    array(
1770
-                        'name'    => 'REG_ID',
1771
-                        'default' => $this->_registration->ID(),
1772
-                    )
1773
-                ),
1774
-                'current_status'     => new EE_Form_Section_HTML(
1775
-                    EEH_HTML::tr(
1776
-                        EEH_HTML::th(
1777
-                            EEH_HTML::label(
1778
-                                EEH_HTML::strong(
1779
-                                    esc_html__('Current Registration Status', 'event_espresso')
1780
-                                )
1781
-                            )
1782
-                        )
1783
-                        . EEH_HTML::td(
1784
-                            EEH_HTML::strong(
1785
-                                $this->_registration->pretty_status(),
1786
-                                '',
1787
-                                'status-' . $this->_registration->status_ID(),
1788
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
-                            )
1790
-                        )
1791
-                    )
1792
-                )
1793
-            )
1794
-        );
1795
-        if (EE_Registry::instance()->CAP->current_user_can(
1796
-            'ee_edit_registration',
1797
-            'toggle_registration_status',
1798
-            $this->_registration->ID()
1799
-        )) {
1800
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
-                $this->_get_reg_statuses(),
1802
-                array(
1803
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
-                    'default'         => $this->_registration->status_ID(),
1805
-                )
1806
-            );
1807
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
-                array(
1809
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
-                    'default'         => false,
1811
-                    'html_help_text'  => esc_html__(
1812
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1813
-                        'event_espresso'
1814
-                    )
1815
-                )
1816
-            );
1817
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
-                array(
1819
-                    'html_class'      => 'button-primary',
1820
-                    'html_label_text' => '&nbsp;',
1821
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
-                )
1823
-            );
1824
-        }
1825
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * Returns an array of all the buttons for the various statuses and switch status actions
1831
-     *
1832
-     * @return array
1833
-     * @throws EE_Error
1834
-     * @throws InvalidArgumentException
1835
-     * @throws InvalidDataTypeException
1836
-     * @throws InvalidInterfaceException
1837
-     * @throws EntityNotFoundException
1838
-     */
1839
-    protected function _get_reg_statuses()
1840
-    {
1841
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
-        // get current reg status
1844
-        $current_status = $this->_registration->status_ID();
1845
-        // is registration for free event? This will determine whether to display the pending payment option
1846
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1847
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
-        ) {
1849
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
-        }
1851
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
-     *
1858
-     * @param bool $status REG status given for changing registrations to.
1859
-     * @param bool $notify Whether to send messages notifications or not.
1860
-     * @return array (array with reg_id(s) updated and whether update was successful.
1861
-     * @throws EE_Error
1862
-     * @throws InvalidArgumentException
1863
-     * @throws InvalidDataTypeException
1864
-     * @throws InvalidInterfaceException
1865
-     * @throws ReflectionException
1866
-     * @throws RuntimeException
1867
-     * @throws EntityNotFoundException
1868
-     */
1869
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1870
-    {
1871
-        if (isset($this->_req_data['reg_status_change_form'])) {
1872
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
-                : array();
1875
-        } else {
1876
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1877
-                ? (array) $this->_req_data['_REG_ID']
1878
-                : array();
1879
-        }
1880
-        // sanitize $REG_IDs
1881
-        $REG_IDs = array_map('absint', $REG_IDs);
1882
-        // and remove empty entries
1883
-        $REG_IDs = array_filter($REG_IDs);
1884
-
1885
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
-
1887
-        /**
1888
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
-         * Currently this value is used downstream by the _process_resend_registration method.
1890
-         *
1891
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
-         * @param bool                     $status           The status registrations were changed to.
1893
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1894
-         * @param Registrations_Admin_Page $admin_page_object
1895
-         */
1896
-        $this->_req_data['_REG_ID'] = apply_filters(
1897
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
-            $result['REG_ID'],
1899
-            $status,
1900
-            $result['success'],
1901
-            $this
1902
-        );
1903
-
1904
-        // notify?
1905
-        if ($notify
1906
-            && $result['success']
1907
-            && ! empty($this->_req_data['_REG_ID'])
1908
-            && EE_Registry::instance()->CAP->current_user_can(
1909
-                'ee_send_message',
1910
-                'espresso_registrations_resend_registration'
1911
-            )
1912
-        ) {
1913
-            $this->_process_resend_registration();
1914
-        }
1915
-        return $result;
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
-     *
1923
-     * @param array  $REG_IDs
1924
-     * @param string $status
1925
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
-     *                        slug sent with setting the registration status.
1927
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
-     * @throws EE_Error
1929
-     * @throws InvalidArgumentException
1930
-     * @throws InvalidDataTypeException
1931
-     * @throws InvalidInterfaceException
1932
-     * @throws ReflectionException
1933
-     * @throws RuntimeException
1934
-     * @throws EntityNotFoundException
1935
-     */
1936
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
-    {
1938
-        $success = false;
1939
-        // typecast $REG_IDs
1940
-        $REG_IDs = (array) $REG_IDs;
1941
-        if (! empty($REG_IDs)) {
1942
-            $success = true;
1943
-            // set default status if none is passed
1944
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
-            $status_context = $notify
1946
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
-            // loop through REG_ID's and change status
1949
-            foreach ($REG_IDs as $REG_ID) {
1950
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
-                if ($registration instanceof EE_Registration) {
1952
-                    $registration->set_status(
1953
-                        $status,
1954
-                        false,
1955
-                        new Context(
1956
-                            $status_context,
1957
-                            esc_html__(
1958
-                                'Manually triggered status change on a Registration Admin Page route.',
1959
-                                'event_espresso'
1960
-                            )
1961
-                        )
1962
-                    );
1963
-                    $result = $registration->save();
1964
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
-                    $success = $result !== false ? $success : false;
1966
-                }
1967
-            }
1968
-        }
1969
-
1970
-        // return $success and processed registrations
1971
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
-    }
1973
-
1974
-
1975
-    /**
1976
-     * Common logic for setting up success message and redirecting to appropriate route
1977
-     *
1978
-     * @param  string $STS_ID status id for the registration changed to
1979
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
-     * @return void
1981
-     * @throws EE_Error
1982
-     */
1983
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1984
-    {
1985
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
-            : array('success' => false);
1987
-        $success = isset($result['success']) && $result['success'];
1988
-        // setup success message
1989
-        if ($success) {
1990
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
-                $msg = sprintf(
1992
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
-                );
1995
-            } else {
1996
-                $msg = sprintf(
1997
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
-                );
2000
-            }
2001
-            EE_Error::add_success($msg);
2002
-        } else {
2003
-            EE_Error::add_error(
2004
-                esc_html__(
2005
-                    'Something went wrong, and the status was not changed',
2006
-                    'event_espresso'
2007
-                ),
2008
-                __FILE__,
2009
-                __LINE__,
2010
-                __FUNCTION__
2011
-            );
2012
-        }
2013
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
-        } else {
2016
-            $route = array('action' => 'default');
2017
-        }
2018
-        // unset nonces
2019
-        foreach ($this->_req_data as $ref => $value) {
2020
-            if (strpos($ref, 'nonce') !== false) {
2021
-                unset($this->_req_data[ $ref ]);
2022
-                continue;
2023
-            }
2024
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
2025
-            $this->_req_data[ $ref ] = $value;
2026
-        }
2027
-        // merge request vars so that the reloaded list table contains any existing filter query params
2028
-        $route = array_merge($this->_req_data, $route);
2029
-        $this->_redirect_after_action($success, '', '', $route, true);
2030
-    }
2031
-
2032
-
2033
-    /**
2034
-     * incoming reg status change from reg details page.
2035
-     *
2036
-     * @return void
2037
-     */
2038
-    protected function _change_reg_status()
2039
-    {
2040
-        $this->_req_data['return'] = 'view_registration';
2041
-        // set notify based on whether the send notifications toggle is set or not
2042
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2043
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2044
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2045
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2046
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2047
-            case EEM_Registration::status_id_approved:
2048
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2049
-                $this->approve_registration($notify);
2050
-                break;
2051
-            case EEM_Registration::status_id_pending_payment:
2052
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2053
-                $this->pending_registration($notify);
2054
-                break;
2055
-            case EEM_Registration::status_id_not_approved:
2056
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2057
-                $this->not_approve_registration($notify);
2058
-                break;
2059
-            case EEM_Registration::status_id_declined:
2060
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2061
-                $this->decline_registration($notify);
2062
-                break;
2063
-            case EEM_Registration::status_id_cancelled:
2064
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2065
-                $this->cancel_registration($notify);
2066
-                break;
2067
-            case EEM_Registration::status_id_wait_list:
2068
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2069
-                $this->wait_list_registration($notify);
2070
-                break;
2071
-            case EEM_Registration::status_id_incomplete:
2072
-            default:
2073
-                $result['success'] = false;
2074
-                unset($this->_req_data['return']);
2075
-                $this->_reg_status_change_return('', false);
2076
-                break;
2077
-        }
2078
-    }
2079
-
2080
-
2081
-    /**
2082
-     * Callback for bulk action routes.
2083
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2084
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2085
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2086
-     * when an action is happening on just a single registration).
2087
-     *
2088
-     * @param      $action
2089
-     * @param bool $notify
2090
-     */
2091
-    protected function bulk_action_on_registrations($action, $notify = false)
2092
-    {
2093
-        do_action(
2094
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2095
-            $this,
2096
-            $action,
2097
-            $notify
2098
-        );
2099
-        $method = $action . '_registration';
2100
-        if (method_exists($this, $method)) {
2101
-            $this->$method($notify);
2102
-        }
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * approve_registration
2108
-     *
2109
-     * @access protected
2110
-     * @param bool $notify whether or not to notify the registrant about their approval.
2111
-     * @return void
2112
-     */
2113
-    protected function approve_registration($notify = false)
2114
-    {
2115
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2116
-    }
2117
-
2118
-
2119
-    /**
2120
-     *        decline_registration
2121
-     *
2122
-     * @access protected
2123
-     * @param bool $notify whether or not to notify the registrant about their status change.
2124
-     * @return void
2125
-     */
2126
-    protected function decline_registration($notify = false)
2127
-    {
2128
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2129
-    }
2130
-
2131
-
2132
-    /**
2133
-     *        cancel_registration
2134
-     *
2135
-     * @access protected
2136
-     * @param bool $notify whether or not to notify the registrant about their status change.
2137
-     * @return void
2138
-     */
2139
-    protected function cancel_registration($notify = false)
2140
-    {
2141
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2142
-    }
2143
-
2144
-
2145
-    /**
2146
-     *        not_approve_registration
2147
-     *
2148
-     * @access protected
2149
-     * @param bool $notify whether or not to notify the registrant about their status change.
2150
-     * @return void
2151
-     */
2152
-    protected function not_approve_registration($notify = false)
2153
-    {
2154
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2155
-    }
2156
-
2157
-
2158
-    /**
2159
-     *        decline_registration
2160
-     *
2161
-     * @access protected
2162
-     * @param bool $notify whether or not to notify the registrant about their status change.
2163
-     * @return void
2164
-     */
2165
-    protected function pending_registration($notify = false)
2166
-    {
2167
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2168
-    }
2169
-
2170
-
2171
-    /**
2172
-     * waitlist_registration
2173
-     *
2174
-     * @access protected
2175
-     * @param bool $notify whether or not to notify the registrant about their status change.
2176
-     * @return void
2177
-     */
2178
-    protected function wait_list_registration($notify = false)
2179
-    {
2180
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2181
-    }
2182
-
2183
-
2184
-    /**
2185
-     *        generates HTML for the Registration main meta box
2186
-     *
2187
-     * @access public
2188
-     * @return void
2189
-     * @throws DomainException
2190
-     * @throws EE_Error
2191
-     * @throws InvalidArgumentException
2192
-     * @throws InvalidDataTypeException
2193
-     * @throws InvalidInterfaceException
2194
-     * @throws ReflectionException
2195
-     * @throws EntityNotFoundException
2196
-     */
2197
-    public function _reg_details_meta_box()
2198
-    {
2199
-        EEH_Autoloader::register_line_item_display_autoloaders();
2200
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2201
-        EE_Registry::instance()->load_helper('Line_Item');
2202
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2203
-            : EE_Transaction::new_instance();
2204
-        $this->_session = $transaction->session_data();
2205
-        $filters = new EE_Line_Item_Filter_Collection();
2206
-        // $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2207
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2208
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2209
-            $filters,
2210
-            $transaction->total_line_item()
2211
-        );
2212
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2213
-        $line_item_display = new EE_Line_Item_Display(
2214
-            'reg_admin_table',
2215
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2216
-        );
2217
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2218
-            $filtered_line_item_tree,
2219
-            array('EE_Registration' => $this->_registration)
2220
-        );
2221
-        $attendee = $this->_registration->attendee();
2222
-        if (EE_Registry::instance()->CAP->current_user_can(
2223
-            'ee_read_transaction',
2224
-            'espresso_transactions_view_transaction'
2225
-        )) {
2226
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2227
-                EE_Admin_Page::add_query_args_and_nonce(
2228
-                    array(
2229
-                        'action' => 'view_transaction',
2230
-                        'TXN_ID' => $transaction->ID(),
2231
-                    ),
2232
-                    TXN_ADMIN_URL
2233
-                ),
2234
-                esc_html__(' View Transaction', 'event_espresso'),
2235
-                'button secondary-button right',
2236
-                'dashicons dashicons-cart'
2237
-            );
2238
-        } else {
2239
-            $this->_template_args['view_transaction_button'] = '';
2240
-        }
2241
-        if ($attendee instanceof EE_Attendee
2242
-            && EE_Registry::instance()->CAP->current_user_can(
2243
-                'ee_send_message',
2244
-                'espresso_registrations_resend_registration'
2245
-            )
2246
-        ) {
2247
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2248
-                EE_Admin_Page::add_query_args_and_nonce(
2249
-                    array(
2250
-                        'action'      => 'resend_registration',
2251
-                        '_REG_ID'     => $this->_registration->ID(),
2252
-                        'redirect_to' => 'view_registration',
2253
-                    ),
2254
-                    REG_ADMIN_URL
2255
-                ),
2256
-                esc_html__(' Resend Registration', 'event_espresso'),
2257
-                'button secondary-button right',
2258
-                'dashicons dashicons-email-alt'
2259
-            );
2260
-        } else {
2261
-            $this->_template_args['resend_registration_button'] = '';
2262
-        }
2263
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2264
-        $payment = $transaction->get_first_related('Payment');
2265
-        $payment = ! $payment instanceof EE_Payment
2266
-            ? EE_Payment::new_instance()
2267
-            : $payment;
2268
-        $payment_method = $payment->get_first_related('Payment_Method');
2269
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2270
-            ? EE_Payment_Method::new_instance()
2271
-            : $payment_method;
2272
-        $reg_details = array(
2273
-            'payment_method'       => $payment_method->name(),
2274
-            'response_msg'         => $payment->gateway_response(),
2275
-            'registration_id'      => $this->_registration->get('REG_code'),
2276
-            'registration_session' => $this->_registration->session_ID(),
2277
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2278
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2279
-        );
2280
-        if (isset($reg_details['registration_id'])) {
2281
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2282
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2283
-                'Registration ID',
2284
-                'event_espresso'
2285
-            );
2286
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2287
-        }
2288
-        if (isset($reg_details['payment_method'])) {
2289
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2290
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2291
-                'Most Recent Payment Method',
2292
-                'event_espresso'
2293
-            );
2294
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2295
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2296
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2297
-                'Payment method response',
2298
-                'event_espresso'
2299
-            );
2300
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2301
-        }
2302
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2303
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2304
-            'Registration Session',
2305
-            'event_espresso'
2306
-        );
2307
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2308
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2309
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2310
-            'Registration placed from IP',
2311
-            'event_espresso'
2312
-        );
2313
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2314
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2315
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2316
-            'Registrant User Agent',
2317
-            'event_espresso'
2318
-        );
2319
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2320
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2321
-            array(
2322
-                'action'   => 'default',
2323
-                'event_id' => $this->_registration->event_ID(),
2324
-            ),
2325
-            REG_ADMIN_URL
2326
-        );
2327
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2328
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2329
-        $template_path =
2330
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2331
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2332
-    }
2333
-
2334
-
2335
-    /**
2336
-     * generates HTML for the Registration Questions meta box.
2337
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2338
-     * otherwise uses new forms system
2339
-     *
2340
-     * @access public
2341
-     * @return void
2342
-     * @throws DomainException
2343
-     * @throws EE_Error
2344
-     */
2345
-    public function _reg_questions_meta_box()
2346
-    {
2347
-        // allow someone to override this method entirely
2348
-        if (apply_filters(
2349
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2350
-            true,
2351
-            $this,
2352
-            $this->_registration
2353
-        )) {
2354
-            $form = $this->_get_reg_custom_questions_form(
2355
-                $this->_registration->ID()
2356
-            );
2357
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2358
-                ? $form->get_html_and_js()
2359
-                : '';
2360
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2361
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2362
-            $template_path =
2363
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2364
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2365
-        }
2366
-    }
2367
-
2368
-
2369
-    /**
2370
-     * form_before_question_group
2371
-     *
2372
-     * @deprecated    as of 4.8.32.rc.000
2373
-     * @access        public
2374
-     * @param        string $output
2375
-     * @return        string
2376
-     */
2377
-    public function form_before_question_group($output)
2378
-    {
2379
-        EE_Error::doing_it_wrong(
2380
-            __CLASS__ . '::' . __FUNCTION__,
2381
-            esc_html__(
2382
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2383
-                'event_espresso'
2384
-            ),
2385
-            '4.8.32.rc.000'
2386
-        );
2387
-        return '
1301
+		if (! empty($registration_status)) {
1302
+			$where['STS_ID'] = $registration_status;
1303
+		} else {
1304
+			// make sure we exclude incomplete registrations, but only if not trashed.
1305
+			if ($view === 'trash') {
1306
+				$where['REG_deleted'] = true;
1307
+			} elseif ($view === 'incomplete') {
1308
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
+			} else {
1310
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
+			}
1312
+		}
1313
+		return $where;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1319
+	 *
1320
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1321
+	 * @return array
1322
+	 * @throws EE_Error
1323
+	 * @throws InvalidArgumentException
1324
+	 * @throws InvalidDataTypeException
1325
+	 * @throws InvalidInterfaceException
1326
+	 */
1327
+	protected function _add_date_to_where_conditions(array $request)
1328
+	{
1329
+		$where = array();
1330
+		$view = EEH_Array::is_set($request, 'status', '');
1331
+		$month_range = ! empty($request['month_range'])
1332
+			? sanitize_text_field($request['month_range'])
1333
+			: '';
1334
+		$retrieve_for_today = $view === 'today';
1335
+		$retrieve_for_this_month = $view === 'month';
1336
+
1337
+		if ($retrieve_for_today) {
1338
+			$now = date('Y-m-d', current_time('timestamp'));
1339
+			$where['REG_date'] = array(
1340
+				'BETWEEN',
1341
+				array(
1342
+					EEM_Registration::instance()->convert_datetime_for_query(
1343
+						'REG_date',
1344
+						$now . ' 00:00:00',
1345
+						'Y-m-d H:i:s'
1346
+					),
1347
+					EEM_Registration::instance()->convert_datetime_for_query(
1348
+						'REG_date',
1349
+						$now . ' 23:59:59',
1350
+						'Y-m-d H:i:s'
1351
+					),
1352
+				),
1353
+			);
1354
+		} elseif ($retrieve_for_this_month) {
1355
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1356
+			$days_this_month = date('t', current_time('timestamp'));
1357
+			$where['REG_date'] = array(
1358
+				'BETWEEN',
1359
+				array(
1360
+					EEM_Registration::instance()->convert_datetime_for_query(
1361
+						'REG_date',
1362
+						$current_year_and_month . '-01 00:00:00',
1363
+						'Y-m-d H:i:s'
1364
+					),
1365
+					EEM_Registration::instance()->convert_datetime_for_query(
1366
+						'REG_date',
1367
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
+						'Y-m-d H:i:s'
1369
+					),
1370
+				),
1371
+			);
1372
+		} elseif ($month_range) {
1373
+			$pieces = explode(' ', $month_range, 3);
1374
+			$month_requested = ! empty($pieces[0])
1375
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
+				: '';
1377
+			$year_requested = ! empty($pieces[1])
1378
+				? $pieces[1]
1379
+				: '';
1380
+			// if there is not a month or year then we can't go further
1381
+			if ($month_requested && $year_requested) {
1382
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
+				$where['REG_date'] = array(
1384
+					'BETWEEN',
1385
+					array(
1386
+						EEM_Registration::instance()->convert_datetime_for_query(
1387
+							'REG_date',
1388
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1389
+							'Y-m-d H:i:s'
1390
+						),
1391
+						EEM_Registration::instance()->convert_datetime_for_query(
1392
+							'REG_date',
1393
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
+							'Y-m-d H:i:s'
1395
+						),
1396
+					),
1397
+				);
1398
+			}
1399
+		}
1400
+		return $where;
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * Adds any provided search restraints to the where conditions for the registrations query
1406
+	 *
1407
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1408
+	 * @return array
1409
+	 */
1410
+	protected function _add_search_to_where_conditions(array $request)
1411
+	{
1412
+		$where = array();
1413
+		if (! empty($request['s'])) {
1414
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
+			$where['OR*search_conditions'] = array(
1416
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1417
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
+				'REG_final_price'                         => array('LIKE', $search_string),
1428
+				'REG_code'                                => array('LIKE', $search_string),
1429
+				'REG_count'                               => array('LIKE', $search_string),
1430
+				'REG_group_size'                          => array('LIKE', $search_string),
1431
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
+			);
1435
+		}
1436
+		return $where;
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Sets up the where conditions for the registrations query.
1442
+	 *
1443
+	 * @param array $request
1444
+	 * @return array
1445
+	 * @throws EE_Error
1446
+	 */
1447
+	protected function _get_where_conditions_for_registrations_query($request)
1448
+	{
1449
+		return apply_filters(
1450
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
+			array_merge(
1452
+				$this->addAttendeeIdToWhereConditions($request),
1453
+				$this->_add_event_id_to_where_conditions($request),
1454
+				$this->_add_category_id_to_where_conditions($request),
1455
+				$this->_add_datetime_id_to_where_conditions($request),
1456
+				$this->_add_registration_status_to_where_conditions($request),
1457
+				$this->_add_date_to_where_conditions($request),
1458
+				$this->_add_search_to_where_conditions($request)
1459
+			),
1460
+			$request
1461
+		);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * Sets up the orderby for the registrations query.
1467
+	 *
1468
+	 * @return array
1469
+	 */
1470
+	protected function _get_orderby_for_registrations_query()
1471
+	{
1472
+		$orderby_field = ! empty($this->_req_data['orderby'])
1473
+			? sanitize_text_field($this->_req_data['orderby'])
1474
+			: '_REG_date';
1475
+		switch ($orderby_field) {
1476
+			case '_REG_ID':
1477
+				$orderby = array('REG_ID');
1478
+				break;
1479
+			case '_Reg_status':
1480
+				$orderby = array('STS_ID');
1481
+				break;
1482
+			case 'ATT_fname':
1483
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
+				break;
1485
+			case 'ATT_lname':
1486
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
+				break;
1488
+			case 'event_name':
1489
+				$orderby = array('Event.EVT_name');
1490
+				break;
1491
+			case 'DTT_EVT_start':
1492
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1493
+				break;
1494
+			case '_REG_date':
1495
+				$orderby = array('REG_date');
1496
+				break;
1497
+			default:
1498
+				$orderby = array($orderby_field);
1499
+				break;
1500
+		}
1501
+
1502
+		// order
1503
+		$order = ! empty($this->_req_data['order'])
1504
+			? sanitize_text_field($this->_req_data['order'])
1505
+			: 'DESC';
1506
+		$orderby = array_combine(
1507
+			$orderby,
1508
+			array_fill(0, count($orderby), $order)
1509
+		);
1510
+		// because there are many registrations with the same date, define
1511
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
1512
+		if (empty($orderby['REG_ID'])) {
1513
+			$orderby['REG_ID'] = $order;
1514
+		}
1515
+
1516
+		$orderby = apply_filters(
1517
+			'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
+			$orderby,
1519
+			$this->_req_data
1520
+		);
1521
+
1522
+		return array('order_by' => $orderby);
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * Sets up the limit for the registrations query.
1528
+	 *
1529
+	 * @param $per_page
1530
+	 * @return array
1531
+	 */
1532
+	protected function _get_limit($per_page)
1533
+	{
1534
+		$current_page = ! empty($this->_req_data['paged'])
1535
+			? absint($this->_req_data['paged'])
1536
+			: 1;
1537
+		$per_page = ! empty($this->_req_data['perpage'])
1538
+			? $this->_req_data['perpage']
1539
+			: $per_page;
1540
+
1541
+		// -1 means return all results so get out if that's set.
1542
+		if ((int) $per_page === -1) {
1543
+			return array();
1544
+		}
1545
+		$per_page = absint($per_page);
1546
+		$offset = ($current_page - 1) * $per_page;
1547
+		return array('limit' => array($offset, $per_page));
1548
+	}
1549
+
1550
+
1551
+	public function get_registration_status_array()
1552
+	{
1553
+		return self::$_reg_status;
1554
+	}
1555
+
1556
+
1557
+
1558
+
1559
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1560
+	/**
1561
+	 *        generates HTML for the View Registration Details Admin page
1562
+	 *
1563
+	 * @access protected
1564
+	 * @return void
1565
+	 * @throws DomainException
1566
+	 * @throws EE_Error
1567
+	 * @throws InvalidArgumentException
1568
+	 * @throws InvalidDataTypeException
1569
+	 * @throws InvalidInterfaceException
1570
+	 * @throws EntityNotFoundException
1571
+	 */
1572
+	protected function _registration_details()
1573
+	{
1574
+		$this->_template_args = array();
1575
+		$this->_set_registration_object();
1576
+		if (is_object($this->_registration)) {
1577
+			$transaction = $this->_registration->transaction()
1578
+				? $this->_registration->transaction()
1579
+				: EE_Transaction::new_instance();
1580
+			$this->_session = $transaction->session_data();
1581
+			$event_id = $this->_registration->event_ID();
1582
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
+			$this->_template_args['grand_total'] = $transaction->total();
1587
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
+			// link back to overview
1589
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
+			$this->_template_args['registration'] = $this->_registration;
1591
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
+				array(
1593
+					'action'   => 'default',
1594
+					'event_id' => $event_id,
1595
+				),
1596
+				REG_ADMIN_URL
1597
+			);
1598
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
+				array(
1600
+					'action' => 'default',
1601
+					'EVT_ID' => $event_id,
1602
+					'page'   => 'espresso_transactions',
1603
+				),
1604
+				admin_url('admin.php')
1605
+			);
1606
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
+				array(
1608
+					'page'   => 'espresso_events',
1609
+					'action' => 'edit',
1610
+					'post'   => $event_id,
1611
+				),
1612
+				admin_url('admin.php')
1613
+			);
1614
+			// next and previous links
1615
+			$next_reg = $this->_registration->next(
1616
+				null,
1617
+				array(),
1618
+				'REG_ID'
1619
+			);
1620
+			$this->_template_args['next_registration'] = $next_reg
1621
+				? $this->_next_link(
1622
+					EE_Admin_Page::add_query_args_and_nonce(
1623
+						array(
1624
+							'action'  => 'view_registration',
1625
+							'_REG_ID' => $next_reg['REG_ID'],
1626
+						),
1627
+						REG_ADMIN_URL
1628
+					),
1629
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1630
+				)
1631
+				: '';
1632
+			$previous_reg = $this->_registration->previous(
1633
+				null,
1634
+				array(),
1635
+				'REG_ID'
1636
+			);
1637
+			$this->_template_args['previous_registration'] = $previous_reg
1638
+				? $this->_previous_link(
1639
+					EE_Admin_Page::add_query_args_and_nonce(
1640
+						array(
1641
+							'action'  => 'view_registration',
1642
+							'_REG_ID' => $previous_reg['REG_ID'],
1643
+						),
1644
+						REG_ADMIN_URL
1645
+					),
1646
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1647
+				)
1648
+				: '';
1649
+			// grab header
1650
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1652
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
+				$template_path,
1654
+				$this->_template_args,
1655
+				true
1656
+			);
1657
+		} else {
1658
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
+		}
1660
+		// the details template wrapper
1661
+		$this->display_admin_page_with_sidebar();
1662
+	}
1663
+
1664
+
1665
+	protected function _registration_details_metaboxes()
1666
+	{
1667
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
+		$this->_set_registration_object();
1669
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
+		add_meta_box(
1671
+			'edit-reg-status-mbox',
1672
+			esc_html__('Registration Status', 'event_espresso'),
1673
+			array($this, 'set_reg_status_buttons_metabox'),
1674
+			$this->wp_page_slug,
1675
+			'normal',
1676
+			'high'
1677
+		);
1678
+		add_meta_box(
1679
+			'edit-reg-details-mbox',
1680
+			esc_html__('Registration Details', 'event_espresso'),
1681
+			array($this, '_reg_details_meta_box'),
1682
+			$this->wp_page_slug,
1683
+			'normal',
1684
+			'high'
1685
+		);
1686
+		if ($attendee instanceof EE_Attendee
1687
+			&& EE_Registry::instance()->CAP->current_user_can(
1688
+				'ee_read_registration',
1689
+				'edit-reg-questions-mbox',
1690
+				$this->_registration->ID()
1691
+			)
1692
+		) {
1693
+			add_meta_box(
1694
+				'edit-reg-questions-mbox',
1695
+				esc_html__('Registration Form Answers', 'event_espresso'),
1696
+				array($this, '_reg_questions_meta_box'),
1697
+				$this->wp_page_slug,
1698
+				'normal',
1699
+				'high'
1700
+			);
1701
+		}
1702
+		add_meta_box(
1703
+			'edit-reg-registrant-mbox',
1704
+			esc_html__('Contact Details', 'event_espresso'),
1705
+			array($this, '_reg_registrant_side_meta_box'),
1706
+			$this->wp_page_slug,
1707
+			'side',
1708
+			'high'
1709
+		);
1710
+		if ($this->_registration->group_size() > 1) {
1711
+			add_meta_box(
1712
+				'edit-reg-attendees-mbox',
1713
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
+				array($this, '_reg_attendees_meta_box'),
1715
+				$this->wp_page_slug,
1716
+				'normal',
1717
+				'high'
1718
+			);
1719
+		}
1720
+	}
1721
+
1722
+
1723
+	/**
1724
+	 * set_reg_status_buttons_metabox
1725
+	 *
1726
+	 * @access protected
1727
+	 * @return string
1728
+	 * @throws \EE_Error
1729
+	 */
1730
+	public function set_reg_status_buttons_metabox()
1731
+	{
1732
+		$this->_set_registration_object();
1733
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1734
+		echo $change_reg_status_form->form_open(
1735
+			self::add_query_args_and_nonce(
1736
+				array(
1737
+					'action' => 'change_reg_status',
1738
+				),
1739
+				REG_ADMIN_URL
1740
+			)
1741
+		);
1742
+		echo $change_reg_status_form->get_html();
1743
+		echo $change_reg_status_form->form_close();
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 * @return EE_Form_Section_Proper
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
+	 */
1755
+	protected function _generate_reg_status_change_form()
1756
+	{
1757
+		$reg_status_change_form_array = array(
1758
+			'name'            => 'reg_status_change_form',
1759
+			'html_id'         => 'reg-status-change-form',
1760
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
+			'subsections'     => array(
1762
+				'return'             => new EE_Hidden_Input(
1763
+					array(
1764
+						'name'    => 'return',
1765
+						'default' => 'view_registration',
1766
+					)
1767
+				),
1768
+				'REG_ID'             => new EE_Hidden_Input(
1769
+					array(
1770
+						'name'    => 'REG_ID',
1771
+						'default' => $this->_registration->ID(),
1772
+					)
1773
+				),
1774
+				'current_status'     => new EE_Form_Section_HTML(
1775
+					EEH_HTML::tr(
1776
+						EEH_HTML::th(
1777
+							EEH_HTML::label(
1778
+								EEH_HTML::strong(
1779
+									esc_html__('Current Registration Status', 'event_espresso')
1780
+								)
1781
+							)
1782
+						)
1783
+						. EEH_HTML::td(
1784
+							EEH_HTML::strong(
1785
+								$this->_registration->pretty_status(),
1786
+								'',
1787
+								'status-' . $this->_registration->status_ID(),
1788
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
+							)
1790
+						)
1791
+					)
1792
+				)
1793
+			)
1794
+		);
1795
+		if (EE_Registry::instance()->CAP->current_user_can(
1796
+			'ee_edit_registration',
1797
+			'toggle_registration_status',
1798
+			$this->_registration->ID()
1799
+		)) {
1800
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
+				$this->_get_reg_statuses(),
1802
+				array(
1803
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
+					'default'         => $this->_registration->status_ID(),
1805
+				)
1806
+			);
1807
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
+				array(
1809
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
+					'default'         => false,
1811
+					'html_help_text'  => esc_html__(
1812
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1813
+						'event_espresso'
1814
+					)
1815
+				)
1816
+			);
1817
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
+				array(
1819
+					'html_class'      => 'button-primary',
1820
+					'html_label_text' => '&nbsp;',
1821
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
+				)
1823
+			);
1824
+		}
1825
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1831
+	 *
1832
+	 * @return array
1833
+	 * @throws EE_Error
1834
+	 * @throws InvalidArgumentException
1835
+	 * @throws InvalidDataTypeException
1836
+	 * @throws InvalidInterfaceException
1837
+	 * @throws EntityNotFoundException
1838
+	 */
1839
+	protected function _get_reg_statuses()
1840
+	{
1841
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
+		// get current reg status
1844
+		$current_status = $this->_registration->status_ID();
1845
+		// is registration for free event? This will determine whether to display the pending payment option
1846
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1847
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
+		) {
1849
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
+		}
1851
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
+	 *
1858
+	 * @param bool $status REG status given for changing registrations to.
1859
+	 * @param bool $notify Whether to send messages notifications or not.
1860
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1861
+	 * @throws EE_Error
1862
+	 * @throws InvalidArgumentException
1863
+	 * @throws InvalidDataTypeException
1864
+	 * @throws InvalidInterfaceException
1865
+	 * @throws ReflectionException
1866
+	 * @throws RuntimeException
1867
+	 * @throws EntityNotFoundException
1868
+	 */
1869
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1870
+	{
1871
+		if (isset($this->_req_data['reg_status_change_form'])) {
1872
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
+				: array();
1875
+		} else {
1876
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1877
+				? (array) $this->_req_data['_REG_ID']
1878
+				: array();
1879
+		}
1880
+		// sanitize $REG_IDs
1881
+		$REG_IDs = array_map('absint', $REG_IDs);
1882
+		// and remove empty entries
1883
+		$REG_IDs = array_filter($REG_IDs);
1884
+
1885
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
+
1887
+		/**
1888
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
+		 * Currently this value is used downstream by the _process_resend_registration method.
1890
+		 *
1891
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
+		 * @param bool                     $status           The status registrations were changed to.
1893
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1894
+		 * @param Registrations_Admin_Page $admin_page_object
1895
+		 */
1896
+		$this->_req_data['_REG_ID'] = apply_filters(
1897
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
+			$result['REG_ID'],
1899
+			$status,
1900
+			$result['success'],
1901
+			$this
1902
+		);
1903
+
1904
+		// notify?
1905
+		if ($notify
1906
+			&& $result['success']
1907
+			&& ! empty($this->_req_data['_REG_ID'])
1908
+			&& EE_Registry::instance()->CAP->current_user_can(
1909
+				'ee_send_message',
1910
+				'espresso_registrations_resend_registration'
1911
+			)
1912
+		) {
1913
+			$this->_process_resend_registration();
1914
+		}
1915
+		return $result;
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
+	 *
1923
+	 * @param array  $REG_IDs
1924
+	 * @param string $status
1925
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
+	 *                        slug sent with setting the registration status.
1927
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
+	 * @throws EE_Error
1929
+	 * @throws InvalidArgumentException
1930
+	 * @throws InvalidDataTypeException
1931
+	 * @throws InvalidInterfaceException
1932
+	 * @throws ReflectionException
1933
+	 * @throws RuntimeException
1934
+	 * @throws EntityNotFoundException
1935
+	 */
1936
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
+	{
1938
+		$success = false;
1939
+		// typecast $REG_IDs
1940
+		$REG_IDs = (array) $REG_IDs;
1941
+		if (! empty($REG_IDs)) {
1942
+			$success = true;
1943
+			// set default status if none is passed
1944
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
+			$status_context = $notify
1946
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
+			// loop through REG_ID's and change status
1949
+			foreach ($REG_IDs as $REG_ID) {
1950
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
+				if ($registration instanceof EE_Registration) {
1952
+					$registration->set_status(
1953
+						$status,
1954
+						false,
1955
+						new Context(
1956
+							$status_context,
1957
+							esc_html__(
1958
+								'Manually triggered status change on a Registration Admin Page route.',
1959
+								'event_espresso'
1960
+							)
1961
+						)
1962
+					);
1963
+					$result = $registration->save();
1964
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
+					$success = $result !== false ? $success : false;
1966
+				}
1967
+			}
1968
+		}
1969
+
1970
+		// return $success and processed registrations
1971
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
+	}
1973
+
1974
+
1975
+	/**
1976
+	 * Common logic for setting up success message and redirecting to appropriate route
1977
+	 *
1978
+	 * @param  string $STS_ID status id for the registration changed to
1979
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
+	 * @return void
1981
+	 * @throws EE_Error
1982
+	 */
1983
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1984
+	{
1985
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
+			: array('success' => false);
1987
+		$success = isset($result['success']) && $result['success'];
1988
+		// setup success message
1989
+		if ($success) {
1990
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
+				$msg = sprintf(
1992
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
+				);
1995
+			} else {
1996
+				$msg = sprintf(
1997
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
+				);
2000
+			}
2001
+			EE_Error::add_success($msg);
2002
+		} else {
2003
+			EE_Error::add_error(
2004
+				esc_html__(
2005
+					'Something went wrong, and the status was not changed',
2006
+					'event_espresso'
2007
+				),
2008
+				__FILE__,
2009
+				__LINE__,
2010
+				__FUNCTION__
2011
+			);
2012
+		}
2013
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
+		} else {
2016
+			$route = array('action' => 'default');
2017
+		}
2018
+		// unset nonces
2019
+		foreach ($this->_req_data as $ref => $value) {
2020
+			if (strpos($ref, 'nonce') !== false) {
2021
+				unset($this->_req_data[ $ref ]);
2022
+				continue;
2023
+			}
2024
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
2025
+			$this->_req_data[ $ref ] = $value;
2026
+		}
2027
+		// merge request vars so that the reloaded list table contains any existing filter query params
2028
+		$route = array_merge($this->_req_data, $route);
2029
+		$this->_redirect_after_action($success, '', '', $route, true);
2030
+	}
2031
+
2032
+
2033
+	/**
2034
+	 * incoming reg status change from reg details page.
2035
+	 *
2036
+	 * @return void
2037
+	 */
2038
+	protected function _change_reg_status()
2039
+	{
2040
+		$this->_req_data['return'] = 'view_registration';
2041
+		// set notify based on whether the send notifications toggle is set or not
2042
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2043
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2044
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2045
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2046
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2047
+			case EEM_Registration::status_id_approved:
2048
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2049
+				$this->approve_registration($notify);
2050
+				break;
2051
+			case EEM_Registration::status_id_pending_payment:
2052
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2053
+				$this->pending_registration($notify);
2054
+				break;
2055
+			case EEM_Registration::status_id_not_approved:
2056
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2057
+				$this->not_approve_registration($notify);
2058
+				break;
2059
+			case EEM_Registration::status_id_declined:
2060
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2061
+				$this->decline_registration($notify);
2062
+				break;
2063
+			case EEM_Registration::status_id_cancelled:
2064
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2065
+				$this->cancel_registration($notify);
2066
+				break;
2067
+			case EEM_Registration::status_id_wait_list:
2068
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2069
+				$this->wait_list_registration($notify);
2070
+				break;
2071
+			case EEM_Registration::status_id_incomplete:
2072
+			default:
2073
+				$result['success'] = false;
2074
+				unset($this->_req_data['return']);
2075
+				$this->_reg_status_change_return('', false);
2076
+				break;
2077
+		}
2078
+	}
2079
+
2080
+
2081
+	/**
2082
+	 * Callback for bulk action routes.
2083
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2084
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2085
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2086
+	 * when an action is happening on just a single registration).
2087
+	 *
2088
+	 * @param      $action
2089
+	 * @param bool $notify
2090
+	 */
2091
+	protected function bulk_action_on_registrations($action, $notify = false)
2092
+	{
2093
+		do_action(
2094
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2095
+			$this,
2096
+			$action,
2097
+			$notify
2098
+		);
2099
+		$method = $action . '_registration';
2100
+		if (method_exists($this, $method)) {
2101
+			$this->$method($notify);
2102
+		}
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * approve_registration
2108
+	 *
2109
+	 * @access protected
2110
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2111
+	 * @return void
2112
+	 */
2113
+	protected function approve_registration($notify = false)
2114
+	{
2115
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2116
+	}
2117
+
2118
+
2119
+	/**
2120
+	 *        decline_registration
2121
+	 *
2122
+	 * @access protected
2123
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2124
+	 * @return void
2125
+	 */
2126
+	protected function decline_registration($notify = false)
2127
+	{
2128
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2129
+	}
2130
+
2131
+
2132
+	/**
2133
+	 *        cancel_registration
2134
+	 *
2135
+	 * @access protected
2136
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2137
+	 * @return void
2138
+	 */
2139
+	protected function cancel_registration($notify = false)
2140
+	{
2141
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2142
+	}
2143
+
2144
+
2145
+	/**
2146
+	 *        not_approve_registration
2147
+	 *
2148
+	 * @access protected
2149
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2150
+	 * @return void
2151
+	 */
2152
+	protected function not_approve_registration($notify = false)
2153
+	{
2154
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2155
+	}
2156
+
2157
+
2158
+	/**
2159
+	 *        decline_registration
2160
+	 *
2161
+	 * @access protected
2162
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2163
+	 * @return void
2164
+	 */
2165
+	protected function pending_registration($notify = false)
2166
+	{
2167
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2168
+	}
2169
+
2170
+
2171
+	/**
2172
+	 * waitlist_registration
2173
+	 *
2174
+	 * @access protected
2175
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2176
+	 * @return void
2177
+	 */
2178
+	protected function wait_list_registration($notify = false)
2179
+	{
2180
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2181
+	}
2182
+
2183
+
2184
+	/**
2185
+	 *        generates HTML for the Registration main meta box
2186
+	 *
2187
+	 * @access public
2188
+	 * @return void
2189
+	 * @throws DomainException
2190
+	 * @throws EE_Error
2191
+	 * @throws InvalidArgumentException
2192
+	 * @throws InvalidDataTypeException
2193
+	 * @throws InvalidInterfaceException
2194
+	 * @throws ReflectionException
2195
+	 * @throws EntityNotFoundException
2196
+	 */
2197
+	public function _reg_details_meta_box()
2198
+	{
2199
+		EEH_Autoloader::register_line_item_display_autoloaders();
2200
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2201
+		EE_Registry::instance()->load_helper('Line_Item');
2202
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2203
+			: EE_Transaction::new_instance();
2204
+		$this->_session = $transaction->session_data();
2205
+		$filters = new EE_Line_Item_Filter_Collection();
2206
+		// $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2207
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2208
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2209
+			$filters,
2210
+			$transaction->total_line_item()
2211
+		);
2212
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2213
+		$line_item_display = new EE_Line_Item_Display(
2214
+			'reg_admin_table',
2215
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2216
+		);
2217
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2218
+			$filtered_line_item_tree,
2219
+			array('EE_Registration' => $this->_registration)
2220
+		);
2221
+		$attendee = $this->_registration->attendee();
2222
+		if (EE_Registry::instance()->CAP->current_user_can(
2223
+			'ee_read_transaction',
2224
+			'espresso_transactions_view_transaction'
2225
+		)) {
2226
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2227
+				EE_Admin_Page::add_query_args_and_nonce(
2228
+					array(
2229
+						'action' => 'view_transaction',
2230
+						'TXN_ID' => $transaction->ID(),
2231
+					),
2232
+					TXN_ADMIN_URL
2233
+				),
2234
+				esc_html__(' View Transaction', 'event_espresso'),
2235
+				'button secondary-button right',
2236
+				'dashicons dashicons-cart'
2237
+			);
2238
+		} else {
2239
+			$this->_template_args['view_transaction_button'] = '';
2240
+		}
2241
+		if ($attendee instanceof EE_Attendee
2242
+			&& EE_Registry::instance()->CAP->current_user_can(
2243
+				'ee_send_message',
2244
+				'espresso_registrations_resend_registration'
2245
+			)
2246
+		) {
2247
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2248
+				EE_Admin_Page::add_query_args_and_nonce(
2249
+					array(
2250
+						'action'      => 'resend_registration',
2251
+						'_REG_ID'     => $this->_registration->ID(),
2252
+						'redirect_to' => 'view_registration',
2253
+					),
2254
+					REG_ADMIN_URL
2255
+				),
2256
+				esc_html__(' Resend Registration', 'event_espresso'),
2257
+				'button secondary-button right',
2258
+				'dashicons dashicons-email-alt'
2259
+			);
2260
+		} else {
2261
+			$this->_template_args['resend_registration_button'] = '';
2262
+		}
2263
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2264
+		$payment = $transaction->get_first_related('Payment');
2265
+		$payment = ! $payment instanceof EE_Payment
2266
+			? EE_Payment::new_instance()
2267
+			: $payment;
2268
+		$payment_method = $payment->get_first_related('Payment_Method');
2269
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2270
+			? EE_Payment_Method::new_instance()
2271
+			: $payment_method;
2272
+		$reg_details = array(
2273
+			'payment_method'       => $payment_method->name(),
2274
+			'response_msg'         => $payment->gateway_response(),
2275
+			'registration_id'      => $this->_registration->get('REG_code'),
2276
+			'registration_session' => $this->_registration->session_ID(),
2277
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2278
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2279
+		);
2280
+		if (isset($reg_details['registration_id'])) {
2281
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2282
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2283
+				'Registration ID',
2284
+				'event_espresso'
2285
+			);
2286
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2287
+		}
2288
+		if (isset($reg_details['payment_method'])) {
2289
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2290
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2291
+				'Most Recent Payment Method',
2292
+				'event_espresso'
2293
+			);
2294
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2295
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2296
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2297
+				'Payment method response',
2298
+				'event_espresso'
2299
+			);
2300
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2301
+		}
2302
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2303
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2304
+			'Registration Session',
2305
+			'event_espresso'
2306
+		);
2307
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2308
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2309
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2310
+			'Registration placed from IP',
2311
+			'event_espresso'
2312
+		);
2313
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2314
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2315
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2316
+			'Registrant User Agent',
2317
+			'event_espresso'
2318
+		);
2319
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2320
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2321
+			array(
2322
+				'action'   => 'default',
2323
+				'event_id' => $this->_registration->event_ID(),
2324
+			),
2325
+			REG_ADMIN_URL
2326
+		);
2327
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2328
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2329
+		$template_path =
2330
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2331
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2332
+	}
2333
+
2334
+
2335
+	/**
2336
+	 * generates HTML for the Registration Questions meta box.
2337
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2338
+	 * otherwise uses new forms system
2339
+	 *
2340
+	 * @access public
2341
+	 * @return void
2342
+	 * @throws DomainException
2343
+	 * @throws EE_Error
2344
+	 */
2345
+	public function _reg_questions_meta_box()
2346
+	{
2347
+		// allow someone to override this method entirely
2348
+		if (apply_filters(
2349
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2350
+			true,
2351
+			$this,
2352
+			$this->_registration
2353
+		)) {
2354
+			$form = $this->_get_reg_custom_questions_form(
2355
+				$this->_registration->ID()
2356
+			);
2357
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2358
+				? $form->get_html_and_js()
2359
+				: '';
2360
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2361
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2362
+			$template_path =
2363
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2364
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2365
+		}
2366
+	}
2367
+
2368
+
2369
+	/**
2370
+	 * form_before_question_group
2371
+	 *
2372
+	 * @deprecated    as of 4.8.32.rc.000
2373
+	 * @access        public
2374
+	 * @param        string $output
2375
+	 * @return        string
2376
+	 */
2377
+	public function form_before_question_group($output)
2378
+	{
2379
+		EE_Error::doing_it_wrong(
2380
+			__CLASS__ . '::' . __FUNCTION__,
2381
+			esc_html__(
2382
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2383
+				'event_espresso'
2384
+			),
2385
+			'4.8.32.rc.000'
2386
+		);
2387
+		return '
2388 2388
 	<table class="form-table ee-width-100">
2389 2389
 		<tbody>
2390 2390
 			';
2391
-    }
2392
-
2393
-
2394
-    /**
2395
-     * form_after_question_group
2396
-     *
2397
-     * @deprecated    as of 4.8.32.rc.000
2398
-     * @access        public
2399
-     * @param        string $output
2400
-     * @return        string
2401
-     */
2402
-    public function form_after_question_group($output)
2403
-    {
2404
-        EE_Error::doing_it_wrong(
2405
-            __CLASS__ . '::' . __FUNCTION__,
2406
-            esc_html__(
2407
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2408
-                'event_espresso'
2409
-            ),
2410
-            '4.8.32.rc.000'
2411
-        );
2412
-        return '
2391
+	}
2392
+
2393
+
2394
+	/**
2395
+	 * form_after_question_group
2396
+	 *
2397
+	 * @deprecated    as of 4.8.32.rc.000
2398
+	 * @access        public
2399
+	 * @param        string $output
2400
+	 * @return        string
2401
+	 */
2402
+	public function form_after_question_group($output)
2403
+	{
2404
+		EE_Error::doing_it_wrong(
2405
+			__CLASS__ . '::' . __FUNCTION__,
2406
+			esc_html__(
2407
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2408
+				'event_espresso'
2409
+			),
2410
+			'4.8.32.rc.000'
2411
+		);
2412
+		return '
2413 2413
 			<tr class="hide-if-no-js">
2414 2414
 				<th> </th>
2415 2415
 				<td class="reg-admin-edit-attendee-question-td">
2416 2416
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2417
-               . esc_attr__('click to edit question', 'event_espresso')
2418
-               . '">
2417
+			   . esc_attr__('click to edit question', 'event_espresso')
2418
+			   . '">
2419 2419
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2420
-               . esc_html__('edit the above question group', 'event_espresso')
2421
-               . '</span>
2420
+			   . esc_html__('edit the above question group', 'event_espresso')
2421
+			   . '</span>
2422 2422
 						<div class="dashicons dashicons-edit"></div>
2423 2423
 					</a>
2424 2424
 				</td>
@@ -2426,606 +2426,606 @@  discard block
 block discarded – undo
2426 2426
 		</tbody>
2427 2427
 	</table>
2428 2428
 ';
2429
-    }
2430
-
2431
-
2432
-    /**
2433
-     * form_form_field_label_wrap
2434
-     *
2435
-     * @deprecated    as of 4.8.32.rc.000
2436
-     * @access        public
2437
-     * @param        string $label
2438
-     * @return        string
2439
-     */
2440
-    public function form_form_field_label_wrap($label)
2441
-    {
2442
-        EE_Error::doing_it_wrong(
2443
-            __CLASS__ . '::' . __FUNCTION__,
2444
-            esc_html__(
2445
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2446
-                'event_espresso'
2447
-            ),
2448
-            '4.8.32.rc.000'
2449
-        );
2450
-        return '
2429
+	}
2430
+
2431
+
2432
+	/**
2433
+	 * form_form_field_label_wrap
2434
+	 *
2435
+	 * @deprecated    as of 4.8.32.rc.000
2436
+	 * @access        public
2437
+	 * @param        string $label
2438
+	 * @return        string
2439
+	 */
2440
+	public function form_form_field_label_wrap($label)
2441
+	{
2442
+		EE_Error::doing_it_wrong(
2443
+			__CLASS__ . '::' . __FUNCTION__,
2444
+			esc_html__(
2445
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2446
+				'event_espresso'
2447
+			),
2448
+			'4.8.32.rc.000'
2449
+		);
2450
+		return '
2451 2451
 			<tr>
2452 2452
 				<th>
2453 2453
 					' . $label . '
2454 2454
 				</th>';
2455
-    }
2456
-
2457
-
2458
-    /**
2459
-     * form_form_field_input__wrap
2460
-     *
2461
-     * @deprecated    as of 4.8.32.rc.000
2462
-     * @access        public
2463
-     * @param        string $input
2464
-     * @return        string
2465
-     */
2466
-    public function form_form_field_input__wrap($input)
2467
-    {
2468
-        EE_Error::doing_it_wrong(
2469
-            __CLASS__ . '::' . __FUNCTION__,
2470
-            esc_html__(
2471
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2472
-                'event_espresso'
2473
-            ),
2474
-            '4.8.32.rc.000'
2475
-        );
2476
-        return '
2455
+	}
2456
+
2457
+
2458
+	/**
2459
+	 * form_form_field_input__wrap
2460
+	 *
2461
+	 * @deprecated    as of 4.8.32.rc.000
2462
+	 * @access        public
2463
+	 * @param        string $input
2464
+	 * @return        string
2465
+	 */
2466
+	public function form_form_field_input__wrap($input)
2467
+	{
2468
+		EE_Error::doing_it_wrong(
2469
+			__CLASS__ . '::' . __FUNCTION__,
2470
+			esc_html__(
2471
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2472
+				'event_espresso'
2473
+			),
2474
+			'4.8.32.rc.000'
2475
+		);
2476
+		return '
2477 2477
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2478 2478
 					' . $input . '
2479 2479
 				</td>
2480 2480
 			</tr>';
2481
-    }
2482
-
2483
-
2484
-    /**
2485
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2486
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2487
-     * to display the page
2488
-     *
2489
-     * @access protected
2490
-     * @return void
2491
-     * @throws EE_Error
2492
-     */
2493
-    protected function _update_attendee_registration_form()
2494
-    {
2495
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2496
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2497
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2498
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2499
-            if ($success) {
2500
-                $what = esc_html__('Registration Form', 'event_espresso');
2501
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2502
-                    : array('action' => 'default');
2503
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2504
-            }
2505
-        }
2506
-    }
2507
-
2508
-
2509
-    /**
2510
-     * Gets the form for saving registrations custom questions (if done
2511
-     * previously retrieves the cached form object, which may have validation errors in it)
2512
-     *
2513
-     * @param int $REG_ID
2514
-     * @return EE_Registration_Custom_Questions_Form
2515
-     * @throws EE_Error
2516
-     * @throws InvalidArgumentException
2517
-     * @throws InvalidDataTypeException
2518
-     * @throws InvalidInterfaceException
2519
-     */
2520
-    protected function _get_reg_custom_questions_form($REG_ID)
2521
-    {
2522
-        if (! $this->_reg_custom_questions_form) {
2523
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2524
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2525
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2526
-            );
2527
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2528
-        }
2529
-        return $this->_reg_custom_questions_form;
2530
-    }
2531
-
2532
-
2533
-    /**
2534
-     * Saves
2535
-     *
2536
-     * @access private
2537
-     * @param bool $REG_ID
2538
-     * @return bool
2539
-     * @throws EE_Error
2540
-     * @throws InvalidArgumentException
2541
-     * @throws InvalidDataTypeException
2542
-     * @throws InvalidInterfaceException
2543
-     */
2544
-    private function _save_reg_custom_questions_form($REG_ID = false)
2545
-    {
2546
-        if (! $REG_ID) {
2547
-            EE_Error::add_error(
2548
-                esc_html__(
2549
-                    'An error occurred. No registration ID was received.',
2550
-                    'event_espresso'
2551
-                ),
2552
-                __FILE__,
2553
-                __FUNCTION__,
2554
-                __LINE__
2555
-            );
2556
-        }
2557
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2558
-        $form->receive_form_submission($this->_req_data);
2559
-        $success = false;
2560
-        if ($form->is_valid()) {
2561
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2562
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2563
-                    $where_conditions = array(
2564
-                        'QST_ID' => $question_id,
2565
-                        'REG_ID' => $REG_ID,
2566
-                    );
2567
-                    $possibly_new_values = array(
2568
-                        'ANS_value' => $input->normalized_value(),
2569
-                    );
2570
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2571
-                    if ($answer instanceof EE_Answer) {
2572
-                        $success = $answer->save($possibly_new_values);
2573
-                    } else {
2574
-                        // insert it then
2575
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2576
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2577
-                        $success = $answer->save();
2578
-                    }
2579
-                }
2580
-            }
2581
-        } else {
2582
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2583
-        }
2584
-        return $success;
2585
-    }
2586
-
2587
-
2588
-    /**
2589
-     *        generates HTML for the Registration main meta box
2590
-     *
2591
-     * @access public
2592
-     * @return void
2593
-     * @throws DomainException
2594
-     * @throws EE_Error
2595
-     * @throws InvalidArgumentException
2596
-     * @throws InvalidDataTypeException
2597
-     * @throws InvalidInterfaceException
2598
-     */
2599
-    public function _reg_attendees_meta_box()
2600
-    {
2601
-        $REG = EEM_Registration::instance();
2602
-        // get all other registrations on this transaction, and cache
2603
-        // the attendees for them so we don't have to run another query using force_join
2604
-        $registrations = $REG->get_all(
2605
-            array(
2606
-                array(
2607
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2608
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2609
-                ),
2610
-                'force_join' => array('Attendee'),
2611
-            )
2612
-        );
2613
-        $this->_template_args['attendees'] = array();
2614
-        $this->_template_args['attendee_notice'] = '';
2615
-        if (empty($registrations)
2616
-            || (is_array($registrations)
2617
-                && ! EEH_Array::get_one_item_from_array($registrations))
2618
-        ) {
2619
-            EE_Error::add_error(
2620
-                esc_html__(
2621
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2622
-                    'event_espresso'
2623
-                ),
2624
-                __FILE__,
2625
-                __FUNCTION__,
2626
-                __LINE__
2627
-            );
2628
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2629
-        } else {
2630
-            $att_nmbr = 1;
2631
-            foreach ($registrations as $registration) {
2632
-                /* @var $registration EE_Registration */
2633
-                $attendee = $registration->attendee()
2634
-                    ? $registration->attendee()
2635
-                    : EEM_Attendee::instance()
2636
-                                  ->create_default_object();
2637
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2638
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2639
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2640
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2641
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2642
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2643
-                    ', ',
2644
-                    $attendee->full_address_as_array()
2645
-                );
2646
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2647
-                    array(
2648
-                        'action' => 'edit_attendee',
2649
-                        'post'   => $attendee->ID(),
2650
-                    ),
2651
-                    REG_ADMIN_URL
2652
-                );
2653
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2654
-                $att_nmbr++;
2655
-            }
2656
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2657
-        }
2658
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2659
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2660
-    }
2661
-
2662
-
2663
-    /**
2664
-     *        generates HTML for the Edit Registration side meta box
2665
-     *
2666
-     * @access public
2667
-     * @return void
2668
-     * @throws DomainException
2669
-     * @throws EE_Error
2670
-     * @throws InvalidArgumentException
2671
-     * @throws InvalidDataTypeException
2672
-     * @throws InvalidInterfaceException
2673
-     */
2674
-    public function _reg_registrant_side_meta_box()
2675
-    {
2676
-        /*@var $attendee EE_Attendee */
2677
-        $att_check = $this->_registration->attendee();
2678
-        $attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2679
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2680
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2681
-        // primary registration object (that way we know if we need to show create button or not)
2682
-        if (! $this->_registration->is_primary_registrant()) {
2683
-            $primary_registration = $this->_registration->get_primary_registration();
2684
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2685
-                : null;
2686
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2687
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2688
-                // custom attendee object so let's not worry about the primary reg.
2689
-                $primary_registration = null;
2690
-            }
2691
-        } else {
2692
-            $primary_registration = null;
2693
-        }
2694
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2695
-        $this->_template_args['fname'] = $attendee->fname();
2696
-        $this->_template_args['lname'] = $attendee->lname();
2697
-        $this->_template_args['email'] = $attendee->email();
2698
-        $this->_template_args['phone'] = $attendee->phone();
2699
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2700
-        // edit link
2701
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2702
-            array(
2703
-                'action' => 'edit_attendee',
2704
-                'post'   => $attendee->ID(),
2705
-            ),
2706
-            REG_ADMIN_URL
2707
-        );
2708
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2709
-        // create link
2710
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2711
-            ? EE_Admin_Page::add_query_args_and_nonce(
2712
-                array(
2713
-                    'action'  => 'duplicate_attendee',
2714
-                    '_REG_ID' => $this->_registration->ID(),
2715
-                ),
2716
-                REG_ADMIN_URL
2717
-            ) : '';
2718
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2719
-        $this->_template_args['att_check'] = $att_check;
2720
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2721
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2722
-    }
2723
-
2724
-
2725
-    /**
2726
-     * trash or restore registrations
2727
-     *
2728
-     * @param  boolean $trash whether to archive or restore
2729
-     * @return void
2730
-     * @throws EE_Error
2731
-     * @throws InvalidArgumentException
2732
-     * @throws InvalidDataTypeException
2733
-     * @throws InvalidInterfaceException
2734
-     * @throws RuntimeException
2735
-     * @access protected
2736
-     */
2737
-    protected function _trash_or_restore_registrations($trash = true)
2738
-    {
2739
-        // if empty _REG_ID then get out because there's nothing to do
2740
-        if (empty($this->_req_data['_REG_ID'])) {
2741
-            EE_Error::add_error(
2742
-                sprintf(
2743
-                    esc_html__(
2744
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2745
-                        'event_espresso'
2746
-                    ),
2747
-                    $trash ? 'trash' : 'restore'
2748
-                ),
2749
-                __FILE__,
2750
-                __LINE__,
2751
-                __FUNCTION__
2752
-            );
2753
-            $this->_redirect_after_action(false, '', '', array(), true);
2754
-        }
2755
-        $success = 0;
2756
-        $overwrite_msgs = false;
2757
-        // Checkboxes
2758
-        if (! is_array($this->_req_data['_REG_ID'])) {
2759
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2760
-        }
2761
-        $reg_count = count($this->_req_data['_REG_ID']);
2762
-        // cycle thru checkboxes
2763
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2764
-            /** @var EE_Registration $REG */
2765
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2766
-            $payments = $REG->registration_payments();
2767
-            if (! empty($payments)) {
2768
-                $name = $REG->attendee() instanceof EE_Attendee
2769
-                    ? $REG->attendee()->full_name()
2770
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2771
-                $overwrite_msgs = true;
2772
-                EE_Error::add_error(
2773
-                    sprintf(
2774
-                        esc_html__(
2775
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2776
-                            'event_espresso'
2777
-                        ),
2778
-                        $name
2779
-                    ),
2780
-                    __FILE__,
2781
-                    __FUNCTION__,
2782
-                    __LINE__
2783
-                );
2784
-                // can't trash this registration because it has payments.
2785
-                continue;
2786
-            }
2787
-            $updated = $trash ? $REG->delete() : $REG->restore();
2788
-            if ($updated) {
2789
-                $success++;
2790
-            }
2791
-        }
2792
-        $this->_redirect_after_action(
2793
-            $success === $reg_count, // were ALL registrations affected?
2794
-            $success > 1
2795
-                ? esc_html__('Registrations', 'event_espresso')
2796
-                : esc_html__('Registration', 'event_espresso'),
2797
-            $trash
2798
-                ? esc_html__('moved to the trash', 'event_espresso')
2799
-                : esc_html__('restored', 'event_espresso'),
2800
-            array('action' => 'default'),
2801
-            $overwrite_msgs
2802
-        );
2803
-    }
2804
-
2805
-
2806
-    /**
2807
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2808
-     * registration but also.
2809
-     * 1. Removing relations to EE_Attendee
2810
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2811
-     * ALSO trashed.
2812
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2813
-     * 4. Removing relationships between all tickets and the related registrations
2814
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2815
-     * 6. Deleting permanently any related Checkins.
2816
-     *
2817
-     * @return void
2818
-     * @throws EE_Error
2819
-     * @throws InvalidArgumentException
2820
-     * @throws InvalidDataTypeException
2821
-     * @throws InvalidInterfaceException
2822
-     */
2823
-    protected function _delete_registrations()
2824
-    {
2825
-        $REG_MDL = EEM_Registration::instance();
2826
-        $success = 1;
2827
-        // Checkboxes
2828
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2829
-            // if array has more than one element than success message should be plural
2830
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2831
-            // cycle thru checkboxes
2832
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2833
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2834
-                if (! $REG instanceof EE_Registration) {
2835
-                    continue;
2836
-                }
2837
-                $deleted = $this->_delete_registration($REG);
2838
-                if (! $deleted) {
2839
-                    $success = 0;
2840
-                }
2841
-            }
2842
-        } else {
2843
-            // grab single id and delete
2844
-            $REG_ID = $this->_req_data['_REG_ID'];
2845
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2846
-            $deleted = $this->_delete_registration($REG);
2847
-            if (! $deleted) {
2848
-                $success = 0;
2849
-            }
2850
-        }
2851
-        $what = $success > 1
2852
-            ? esc_html__('Registrations', 'event_espresso')
2853
-            : esc_html__('Registration', 'event_espresso');
2854
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2855
-        $this->_redirect_after_action(
2856
-            $success,
2857
-            $what,
2858
-            $action_desc,
2859
-            array('action' => 'default'),
2860
-            true
2861
-        );
2862
-    }
2863
-
2864
-
2865
-    /**
2866
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2867
-     * models get affected.
2868
-     *
2869
-     * @param  EE_Registration $REG registration to be deleted permenantly
2870
-     * @return bool true = successful deletion, false = fail.
2871
-     * @throws EE_Error
2872
-     */
2873
-    protected function _delete_registration(EE_Registration $REG)
2874
-    {
2875
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2876
-        // registrations on the transaction that are NOT trashed.
2877
-        $TXN = $REG->get_first_related('Transaction');
2878
-        $REGS = $TXN->get_many_related('Registration');
2879
-        $all_trashed = true;
2880
-        foreach ($REGS as $registration) {
2881
-            if (! $registration->get('REG_deleted')) {
2882
-                $all_trashed = false;
2883
-            }
2884
-        }
2885
-        if (! $all_trashed) {
2886
-            EE_Error::add_error(
2887
-                esc_html__(
2888
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2889
-                    'event_espresso'
2890
-                ),
2891
-                __FILE__,
2892
-                __FUNCTION__,
2893
-                __LINE__
2894
-            );
2895
-            return false;
2896
-        }
2897
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2898
-        // separately from THIS one).
2899
-        foreach ($REGS as $registration) {
2900
-            // delete related answers
2901
-            $registration->delete_related_permanently('Answer');
2902
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2903
-            $attendee = $registration->get_first_related('Attendee');
2904
-            if ($attendee instanceof EE_Attendee) {
2905
-                $registration->_remove_relation_to($attendee, 'Attendee');
2906
-            }
2907
-            // now remove relationships to tickets on this registration.
2908
-            $registration->_remove_relations('Ticket');
2909
-            // now delete permanently the checkins related to this registration.
2910
-            $registration->delete_related_permanently('Checkin');
2911
-            if ($registration->ID() === $REG->ID()) {
2912
-                continue;
2913
-            } //we don't want to delete permanently the existing registration just yet.
2914
-            // remove relation to transaction for these registrations if NOT the existing registrations
2915
-            $registration->_remove_relations('Transaction');
2916
-            // delete permanently any related messages.
2917
-            $registration->delete_related_permanently('Message');
2918
-            // now delete this registration permanently
2919
-            $registration->delete_permanently();
2920
-        }
2921
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2922
-        // (the transaction and line items should be all that's left).
2923
-        // delete the line items related to the transaction for this registration.
2924
-        $TXN->delete_related_permanently('Line_Item');
2925
-        // we need to remove all the relationships on the transaction
2926
-        $TXN->delete_related_permanently('Payment');
2927
-        $TXN->delete_related_permanently('Extra_Meta');
2928
-        $TXN->delete_related_permanently('Message');
2929
-        // now we can delete this REG permanently (and the transaction of course)
2930
-        $REG->delete_related_permanently('Transaction');
2931
-        return $REG->delete_permanently();
2932
-    }
2933
-
2934
-
2935
-    /**
2936
-     *    generates HTML for the Register New Attendee Admin page
2937
-     *
2938
-     * @access private
2939
-     * @throws DomainException
2940
-     * @throws EE_Error
2941
-     */
2942
-    public function new_registration()
2943
-    {
2944
-        if (! $this->_set_reg_event()) {
2945
-            throw new EE_Error(
2946
-                esc_html__(
2947
-                    'Unable to continue with registering because there is no Event ID in the request',
2948
-                    'event_espresso'
2949
-                )
2950
-            );
2951
-        }
2952
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2953
-        // gotta start with a clean slate if we're not coming here via ajax
2954
-        if (! defined('DOING_AJAX')
2955
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2956
-        ) {
2957
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2958
-        }
2959
-        $this->_template_args['event_name'] = '';
2960
-        // event name
2961
-        if ($this->_reg_event) {
2962
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2963
-            $edit_event_url = self::add_query_args_and_nonce(
2964
-                array(
2965
-                    'action' => 'edit',
2966
-                    'post'   => $this->_reg_event->ID(),
2967
-                ),
2968
-                EVENTS_ADMIN_URL
2969
-            );
2970
-            $edit_event_lnk = '<a href="'
2971
-                              . $edit_event_url
2972
-                              . '" title="'
2973
-                              . esc_attr__('Edit ', 'event_espresso')
2974
-                              . $this->_reg_event->name()
2975
-                              . '">'
2976
-                              . esc_html__('Edit Event', 'event_espresso')
2977
-                              . '</a>';
2978
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2979
-                                                   . $edit_event_lnk
2980
-                                                   . '</span>';
2981
-        }
2982
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2983
-        if (defined('DOING_AJAX')) {
2984
-            $this->_return_json();
2985
-        }
2986
-        // grab header
2987
-        $template_path =
2988
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2989
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2990
-            $template_path,
2991
-            $this->_template_args,
2992
-            true
2993
-        );
2994
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2995
-        // the details template wrapper
2996
-        $this->display_admin_page_with_sidebar();
2997
-    }
2998
-
2999
-
3000
-    /**
3001
-     * This returns the content for a registration step
3002
-     *
3003
-     * @access protected
3004
-     * @return string html
3005
-     * @throws DomainException
3006
-     * @throws EE_Error
3007
-     * @throws InvalidArgumentException
3008
-     * @throws InvalidDataTypeException
3009
-     * @throws InvalidInterfaceException
3010
-     */
3011
-    protected function _get_registration_step_content()
3012
-    {
3013
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3014
-            $warning_msg = sprintf(
3015
-                esc_html__(
3016
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3017
-                    'event_espresso'
3018
-                ),
3019
-                '<br />',
3020
-                '<h3 class="important-notice">',
3021
-                '</h3>',
3022
-                '<div class="float-right">',
3023
-                '<span id="redirect_timer" class="important-notice">30</span>',
3024
-                '</div>',
3025
-                '<b>',
3026
-                '</b>'
3027
-            );
3028
-            return '
2481
+	}
2482
+
2483
+
2484
+	/**
2485
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2486
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2487
+	 * to display the page
2488
+	 *
2489
+	 * @access protected
2490
+	 * @return void
2491
+	 * @throws EE_Error
2492
+	 */
2493
+	protected function _update_attendee_registration_form()
2494
+	{
2495
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2496
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2497
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2498
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2499
+			if ($success) {
2500
+				$what = esc_html__('Registration Form', 'event_espresso');
2501
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2502
+					: array('action' => 'default');
2503
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2504
+			}
2505
+		}
2506
+	}
2507
+
2508
+
2509
+	/**
2510
+	 * Gets the form for saving registrations custom questions (if done
2511
+	 * previously retrieves the cached form object, which may have validation errors in it)
2512
+	 *
2513
+	 * @param int $REG_ID
2514
+	 * @return EE_Registration_Custom_Questions_Form
2515
+	 * @throws EE_Error
2516
+	 * @throws InvalidArgumentException
2517
+	 * @throws InvalidDataTypeException
2518
+	 * @throws InvalidInterfaceException
2519
+	 */
2520
+	protected function _get_reg_custom_questions_form($REG_ID)
2521
+	{
2522
+		if (! $this->_reg_custom_questions_form) {
2523
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2524
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2525
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2526
+			);
2527
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2528
+		}
2529
+		return $this->_reg_custom_questions_form;
2530
+	}
2531
+
2532
+
2533
+	/**
2534
+	 * Saves
2535
+	 *
2536
+	 * @access private
2537
+	 * @param bool $REG_ID
2538
+	 * @return bool
2539
+	 * @throws EE_Error
2540
+	 * @throws InvalidArgumentException
2541
+	 * @throws InvalidDataTypeException
2542
+	 * @throws InvalidInterfaceException
2543
+	 */
2544
+	private function _save_reg_custom_questions_form($REG_ID = false)
2545
+	{
2546
+		if (! $REG_ID) {
2547
+			EE_Error::add_error(
2548
+				esc_html__(
2549
+					'An error occurred. No registration ID was received.',
2550
+					'event_espresso'
2551
+				),
2552
+				__FILE__,
2553
+				__FUNCTION__,
2554
+				__LINE__
2555
+			);
2556
+		}
2557
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2558
+		$form->receive_form_submission($this->_req_data);
2559
+		$success = false;
2560
+		if ($form->is_valid()) {
2561
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2562
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2563
+					$where_conditions = array(
2564
+						'QST_ID' => $question_id,
2565
+						'REG_ID' => $REG_ID,
2566
+					);
2567
+					$possibly_new_values = array(
2568
+						'ANS_value' => $input->normalized_value(),
2569
+					);
2570
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2571
+					if ($answer instanceof EE_Answer) {
2572
+						$success = $answer->save($possibly_new_values);
2573
+					} else {
2574
+						// insert it then
2575
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2576
+						$answer = EE_Answer::new_instance($cols_n_vals);
2577
+						$success = $answer->save();
2578
+					}
2579
+				}
2580
+			}
2581
+		} else {
2582
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2583
+		}
2584
+		return $success;
2585
+	}
2586
+
2587
+
2588
+	/**
2589
+	 *        generates HTML for the Registration main meta box
2590
+	 *
2591
+	 * @access public
2592
+	 * @return void
2593
+	 * @throws DomainException
2594
+	 * @throws EE_Error
2595
+	 * @throws InvalidArgumentException
2596
+	 * @throws InvalidDataTypeException
2597
+	 * @throws InvalidInterfaceException
2598
+	 */
2599
+	public function _reg_attendees_meta_box()
2600
+	{
2601
+		$REG = EEM_Registration::instance();
2602
+		// get all other registrations on this transaction, and cache
2603
+		// the attendees for them so we don't have to run another query using force_join
2604
+		$registrations = $REG->get_all(
2605
+			array(
2606
+				array(
2607
+					'TXN_ID' => $this->_registration->transaction_ID(),
2608
+					'REG_ID' => array('!=', $this->_registration->ID()),
2609
+				),
2610
+				'force_join' => array('Attendee'),
2611
+			)
2612
+		);
2613
+		$this->_template_args['attendees'] = array();
2614
+		$this->_template_args['attendee_notice'] = '';
2615
+		if (empty($registrations)
2616
+			|| (is_array($registrations)
2617
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2618
+		) {
2619
+			EE_Error::add_error(
2620
+				esc_html__(
2621
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2622
+					'event_espresso'
2623
+				),
2624
+				__FILE__,
2625
+				__FUNCTION__,
2626
+				__LINE__
2627
+			);
2628
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2629
+		} else {
2630
+			$att_nmbr = 1;
2631
+			foreach ($registrations as $registration) {
2632
+				/* @var $registration EE_Registration */
2633
+				$attendee = $registration->attendee()
2634
+					? $registration->attendee()
2635
+					: EEM_Attendee::instance()
2636
+								  ->create_default_object();
2637
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2638
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2639
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2640
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2641
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2642
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2643
+					', ',
2644
+					$attendee->full_address_as_array()
2645
+				);
2646
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2647
+					array(
2648
+						'action' => 'edit_attendee',
2649
+						'post'   => $attendee->ID(),
2650
+					),
2651
+					REG_ADMIN_URL
2652
+				);
2653
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2654
+				$att_nmbr++;
2655
+			}
2656
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2657
+		}
2658
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2659
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2660
+	}
2661
+
2662
+
2663
+	/**
2664
+	 *        generates HTML for the Edit Registration side meta box
2665
+	 *
2666
+	 * @access public
2667
+	 * @return void
2668
+	 * @throws DomainException
2669
+	 * @throws EE_Error
2670
+	 * @throws InvalidArgumentException
2671
+	 * @throws InvalidDataTypeException
2672
+	 * @throws InvalidInterfaceException
2673
+	 */
2674
+	public function _reg_registrant_side_meta_box()
2675
+	{
2676
+		/*@var $attendee EE_Attendee */
2677
+		$att_check = $this->_registration->attendee();
2678
+		$attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2679
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2680
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2681
+		// primary registration object (that way we know if we need to show create button or not)
2682
+		if (! $this->_registration->is_primary_registrant()) {
2683
+			$primary_registration = $this->_registration->get_primary_registration();
2684
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2685
+				: null;
2686
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2687
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2688
+				// custom attendee object so let's not worry about the primary reg.
2689
+				$primary_registration = null;
2690
+			}
2691
+		} else {
2692
+			$primary_registration = null;
2693
+		}
2694
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2695
+		$this->_template_args['fname'] = $attendee->fname();
2696
+		$this->_template_args['lname'] = $attendee->lname();
2697
+		$this->_template_args['email'] = $attendee->email();
2698
+		$this->_template_args['phone'] = $attendee->phone();
2699
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2700
+		// edit link
2701
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2702
+			array(
2703
+				'action' => 'edit_attendee',
2704
+				'post'   => $attendee->ID(),
2705
+			),
2706
+			REG_ADMIN_URL
2707
+		);
2708
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2709
+		// create link
2710
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2711
+			? EE_Admin_Page::add_query_args_and_nonce(
2712
+				array(
2713
+					'action'  => 'duplicate_attendee',
2714
+					'_REG_ID' => $this->_registration->ID(),
2715
+				),
2716
+				REG_ADMIN_URL
2717
+			) : '';
2718
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2719
+		$this->_template_args['att_check'] = $att_check;
2720
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2721
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2722
+	}
2723
+
2724
+
2725
+	/**
2726
+	 * trash or restore registrations
2727
+	 *
2728
+	 * @param  boolean $trash whether to archive or restore
2729
+	 * @return void
2730
+	 * @throws EE_Error
2731
+	 * @throws InvalidArgumentException
2732
+	 * @throws InvalidDataTypeException
2733
+	 * @throws InvalidInterfaceException
2734
+	 * @throws RuntimeException
2735
+	 * @access protected
2736
+	 */
2737
+	protected function _trash_or_restore_registrations($trash = true)
2738
+	{
2739
+		// if empty _REG_ID then get out because there's nothing to do
2740
+		if (empty($this->_req_data['_REG_ID'])) {
2741
+			EE_Error::add_error(
2742
+				sprintf(
2743
+					esc_html__(
2744
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2745
+						'event_espresso'
2746
+					),
2747
+					$trash ? 'trash' : 'restore'
2748
+				),
2749
+				__FILE__,
2750
+				__LINE__,
2751
+				__FUNCTION__
2752
+			);
2753
+			$this->_redirect_after_action(false, '', '', array(), true);
2754
+		}
2755
+		$success = 0;
2756
+		$overwrite_msgs = false;
2757
+		// Checkboxes
2758
+		if (! is_array($this->_req_data['_REG_ID'])) {
2759
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2760
+		}
2761
+		$reg_count = count($this->_req_data['_REG_ID']);
2762
+		// cycle thru checkboxes
2763
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2764
+			/** @var EE_Registration $REG */
2765
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2766
+			$payments = $REG->registration_payments();
2767
+			if (! empty($payments)) {
2768
+				$name = $REG->attendee() instanceof EE_Attendee
2769
+					? $REG->attendee()->full_name()
2770
+					: esc_html__('Unknown Attendee', 'event_espresso');
2771
+				$overwrite_msgs = true;
2772
+				EE_Error::add_error(
2773
+					sprintf(
2774
+						esc_html__(
2775
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2776
+							'event_espresso'
2777
+						),
2778
+						$name
2779
+					),
2780
+					__FILE__,
2781
+					__FUNCTION__,
2782
+					__LINE__
2783
+				);
2784
+				// can't trash this registration because it has payments.
2785
+				continue;
2786
+			}
2787
+			$updated = $trash ? $REG->delete() : $REG->restore();
2788
+			if ($updated) {
2789
+				$success++;
2790
+			}
2791
+		}
2792
+		$this->_redirect_after_action(
2793
+			$success === $reg_count, // were ALL registrations affected?
2794
+			$success > 1
2795
+				? esc_html__('Registrations', 'event_espresso')
2796
+				: esc_html__('Registration', 'event_espresso'),
2797
+			$trash
2798
+				? esc_html__('moved to the trash', 'event_espresso')
2799
+				: esc_html__('restored', 'event_espresso'),
2800
+			array('action' => 'default'),
2801
+			$overwrite_msgs
2802
+		);
2803
+	}
2804
+
2805
+
2806
+	/**
2807
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2808
+	 * registration but also.
2809
+	 * 1. Removing relations to EE_Attendee
2810
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2811
+	 * ALSO trashed.
2812
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2813
+	 * 4. Removing relationships between all tickets and the related registrations
2814
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2815
+	 * 6. Deleting permanently any related Checkins.
2816
+	 *
2817
+	 * @return void
2818
+	 * @throws EE_Error
2819
+	 * @throws InvalidArgumentException
2820
+	 * @throws InvalidDataTypeException
2821
+	 * @throws InvalidInterfaceException
2822
+	 */
2823
+	protected function _delete_registrations()
2824
+	{
2825
+		$REG_MDL = EEM_Registration::instance();
2826
+		$success = 1;
2827
+		// Checkboxes
2828
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2829
+			// if array has more than one element than success message should be plural
2830
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2831
+			// cycle thru checkboxes
2832
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2833
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2834
+				if (! $REG instanceof EE_Registration) {
2835
+					continue;
2836
+				}
2837
+				$deleted = $this->_delete_registration($REG);
2838
+				if (! $deleted) {
2839
+					$success = 0;
2840
+				}
2841
+			}
2842
+		} else {
2843
+			// grab single id and delete
2844
+			$REG_ID = $this->_req_data['_REG_ID'];
2845
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2846
+			$deleted = $this->_delete_registration($REG);
2847
+			if (! $deleted) {
2848
+				$success = 0;
2849
+			}
2850
+		}
2851
+		$what = $success > 1
2852
+			? esc_html__('Registrations', 'event_espresso')
2853
+			: esc_html__('Registration', 'event_espresso');
2854
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2855
+		$this->_redirect_after_action(
2856
+			$success,
2857
+			$what,
2858
+			$action_desc,
2859
+			array('action' => 'default'),
2860
+			true
2861
+		);
2862
+	}
2863
+
2864
+
2865
+	/**
2866
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2867
+	 * models get affected.
2868
+	 *
2869
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2870
+	 * @return bool true = successful deletion, false = fail.
2871
+	 * @throws EE_Error
2872
+	 */
2873
+	protected function _delete_registration(EE_Registration $REG)
2874
+	{
2875
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2876
+		// registrations on the transaction that are NOT trashed.
2877
+		$TXN = $REG->get_first_related('Transaction');
2878
+		$REGS = $TXN->get_many_related('Registration');
2879
+		$all_trashed = true;
2880
+		foreach ($REGS as $registration) {
2881
+			if (! $registration->get('REG_deleted')) {
2882
+				$all_trashed = false;
2883
+			}
2884
+		}
2885
+		if (! $all_trashed) {
2886
+			EE_Error::add_error(
2887
+				esc_html__(
2888
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2889
+					'event_espresso'
2890
+				),
2891
+				__FILE__,
2892
+				__FUNCTION__,
2893
+				__LINE__
2894
+			);
2895
+			return false;
2896
+		}
2897
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2898
+		// separately from THIS one).
2899
+		foreach ($REGS as $registration) {
2900
+			// delete related answers
2901
+			$registration->delete_related_permanently('Answer');
2902
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2903
+			$attendee = $registration->get_first_related('Attendee');
2904
+			if ($attendee instanceof EE_Attendee) {
2905
+				$registration->_remove_relation_to($attendee, 'Attendee');
2906
+			}
2907
+			// now remove relationships to tickets on this registration.
2908
+			$registration->_remove_relations('Ticket');
2909
+			// now delete permanently the checkins related to this registration.
2910
+			$registration->delete_related_permanently('Checkin');
2911
+			if ($registration->ID() === $REG->ID()) {
2912
+				continue;
2913
+			} //we don't want to delete permanently the existing registration just yet.
2914
+			// remove relation to transaction for these registrations if NOT the existing registrations
2915
+			$registration->_remove_relations('Transaction');
2916
+			// delete permanently any related messages.
2917
+			$registration->delete_related_permanently('Message');
2918
+			// now delete this registration permanently
2919
+			$registration->delete_permanently();
2920
+		}
2921
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2922
+		// (the transaction and line items should be all that's left).
2923
+		// delete the line items related to the transaction for this registration.
2924
+		$TXN->delete_related_permanently('Line_Item');
2925
+		// we need to remove all the relationships on the transaction
2926
+		$TXN->delete_related_permanently('Payment');
2927
+		$TXN->delete_related_permanently('Extra_Meta');
2928
+		$TXN->delete_related_permanently('Message');
2929
+		// now we can delete this REG permanently (and the transaction of course)
2930
+		$REG->delete_related_permanently('Transaction');
2931
+		return $REG->delete_permanently();
2932
+	}
2933
+
2934
+
2935
+	/**
2936
+	 *    generates HTML for the Register New Attendee Admin page
2937
+	 *
2938
+	 * @access private
2939
+	 * @throws DomainException
2940
+	 * @throws EE_Error
2941
+	 */
2942
+	public function new_registration()
2943
+	{
2944
+		if (! $this->_set_reg_event()) {
2945
+			throw new EE_Error(
2946
+				esc_html__(
2947
+					'Unable to continue with registering because there is no Event ID in the request',
2948
+					'event_espresso'
2949
+				)
2950
+			);
2951
+		}
2952
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2953
+		// gotta start with a clean slate if we're not coming here via ajax
2954
+		if (! defined('DOING_AJAX')
2955
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2956
+		) {
2957
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2958
+		}
2959
+		$this->_template_args['event_name'] = '';
2960
+		// event name
2961
+		if ($this->_reg_event) {
2962
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2963
+			$edit_event_url = self::add_query_args_and_nonce(
2964
+				array(
2965
+					'action' => 'edit',
2966
+					'post'   => $this->_reg_event->ID(),
2967
+				),
2968
+				EVENTS_ADMIN_URL
2969
+			);
2970
+			$edit_event_lnk = '<a href="'
2971
+							  . $edit_event_url
2972
+							  . '" title="'
2973
+							  . esc_attr__('Edit ', 'event_espresso')
2974
+							  . $this->_reg_event->name()
2975
+							  . '">'
2976
+							  . esc_html__('Edit Event', 'event_espresso')
2977
+							  . '</a>';
2978
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2979
+												   . $edit_event_lnk
2980
+												   . '</span>';
2981
+		}
2982
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2983
+		if (defined('DOING_AJAX')) {
2984
+			$this->_return_json();
2985
+		}
2986
+		// grab header
2987
+		$template_path =
2988
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2989
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2990
+			$template_path,
2991
+			$this->_template_args,
2992
+			true
2993
+		);
2994
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2995
+		// the details template wrapper
2996
+		$this->display_admin_page_with_sidebar();
2997
+	}
2998
+
2999
+
3000
+	/**
3001
+	 * This returns the content for a registration step
3002
+	 *
3003
+	 * @access protected
3004
+	 * @return string html
3005
+	 * @throws DomainException
3006
+	 * @throws EE_Error
3007
+	 * @throws InvalidArgumentException
3008
+	 * @throws InvalidDataTypeException
3009
+	 * @throws InvalidInterfaceException
3010
+	 */
3011
+	protected function _get_registration_step_content()
3012
+	{
3013
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3014
+			$warning_msg = sprintf(
3015
+				esc_html__(
3016
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3017
+					'event_espresso'
3018
+				),
3019
+				'<br />',
3020
+				'<h3 class="important-notice">',
3021
+				'</h3>',
3022
+				'<div class="float-right">',
3023
+				'<span id="redirect_timer" class="important-notice">30</span>',
3024
+				'</div>',
3025
+				'<b>',
3026
+				'</b>'
3027
+			);
3028
+			return '
3029 3029
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3030 3030
 	<script >
3031 3031
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -3038,855 +3038,855 @@  discard block
 block discarded – undo
3038 3038
 	        }
3039 3039
 	    }, 800 );
3040 3040
 	</script >';
3041
-        }
3042
-        $template_args = array(
3043
-            'title'                    => '',
3044
-            'content'                  => '',
3045
-            'step_button_text'         => '',
3046
-            'show_notification_toggle' => false,
3047
-        );
3048
-        // to indicate we're processing a new registration
3049
-        $hidden_fields = array(
3050
-            'processing_registration' => array(
3051
-                'type'  => 'hidden',
3052
-                'value' => 0,
3053
-            ),
3054
-            'event_id'                => array(
3055
-                'type'  => 'hidden',
3056
-                'value' => $this->_reg_event->ID(),
3057
-            ),
3058
-        );
3059
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
3060
-        $cart = EE_Registry::instance()->SSN->cart();
3061
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3062
-        switch ($step) {
3063
-            case 'ticket':
3064
-                $hidden_fields['processing_registration']['value'] = 1;
3065
-                $template_args['title'] = esc_html__(
3066
-                    'Step One: Select the Ticket for this registration',
3067
-                    'event_espresso'
3068
-                );
3069
-                $template_args['content'] =
3070
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3071
-                $template_args['step_button_text'] = esc_html__(
3072
-                    'Add Tickets and Continue to Registrant Details',
3073
-                    'event_espresso'
3074
-                );
3075
-                $template_args['show_notification_toggle'] = false;
3076
-                break;
3077
-            case 'questions':
3078
-                $hidden_fields['processing_registration']['value'] = 2;
3079
-                $template_args['title'] = esc_html__(
3080
-                    'Step Two: Add Registrant Details for this Registration',
3081
-                    'event_espresso'
3082
-                );
3083
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3084
-                // properly by the first process_reg_step run.
3085
-                $template_args['content'] =
3086
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3087
-                $template_args['step_button_text'] = esc_html__(
3088
-                    'Save Registration and Continue to Details',
3089
-                    'event_espresso'
3090
-                );
3091
-                $template_args['show_notification_toggle'] = true;
3092
-                break;
3093
-        }
3094
-        // we come back to the process_registration_step route.
3095
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3096
-        return EEH_Template::display_template(
3097
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3098
-            $template_args,
3099
-            true
3100
-        );
3101
-    }
3102
-
3103
-
3104
-    /**
3105
-     *        set_reg_event
3106
-     *
3107
-     * @access private
3108
-     * @return bool
3109
-     * @throws EE_Error
3110
-     * @throws InvalidArgumentException
3111
-     * @throws InvalidDataTypeException
3112
-     * @throws InvalidInterfaceException
3113
-     */
3114
-    private function _set_reg_event()
3115
-    {
3116
-        if (is_object($this->_reg_event)) {
3117
-            return true;
3118
-        }
3119
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3120
-        if (! $EVT_ID) {
3121
-            return false;
3122
-        }
3123
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3124
-        return true;
3125
-    }
3126
-
3127
-
3128
-    /**
3129
-     * process_reg_step
3130
-     *
3131
-     * @access        public
3132
-     * @return string
3133
-     * @throws DomainException
3134
-     * @throws EE_Error
3135
-     * @throws InvalidArgumentException
3136
-     * @throws InvalidDataTypeException
3137
-     * @throws InvalidInterfaceException
3138
-     * @throws ReflectionException
3139
-     * @throws RuntimeException
3140
-     */
3141
-    public function process_reg_step()
3142
-    {
3143
-        EE_System::do_not_cache();
3144
-        $this->_set_reg_event();
3145
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3146
-        EE_Registry::instance()->REQ->set('uts', time());
3147
-        // what step are we on?
3148
-        $cart = EE_Registry::instance()->SSN->cart();
3149
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3150
-        // if doing ajax then we need to verify the nonce
3151
-        if (defined('DOING_AJAX')) {
3152
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3153
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3154
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3155
-        }
3156
-        switch ($step) {
3157
-            case 'ticket':
3158
-                // process ticket selection
3159
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3160
-                if ($success) {
3161
-                    EE_Error::add_success(
3162
-                        esc_html__(
3163
-                            'Tickets Selected. Now complete the registration.',
3164
-                            'event_espresso'
3165
-                        )
3166
-                    );
3167
-                } else {
3168
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3169
-                }
3170
-                if (defined('DOING_AJAX')) {
3171
-                    $this->new_registration(); // display next step
3172
-                } else {
3173
-                    $query_args = array(
3174
-                        'action'                  => 'new_registration',
3175
-                        'processing_registration' => 1,
3176
-                        'event_id'                => $this->_reg_event->ID(),
3177
-                        'uts'                     => time(),
3178
-                    );
3179
-                    $this->_redirect_after_action(
3180
-                        false,
3181
-                        '',
3182
-                        '',
3183
-                        $query_args,
3184
-                        true
3185
-                    );
3186
-                }
3187
-                break;
3188
-            case 'questions':
3189
-                if (! isset(
3190
-                    $this->_req_data['txn_reg_status_change'],
3191
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3192
-                )
3193
-                ) {
3194
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3195
-                }
3196
-                // process registration
3197
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3198
-                if ($cart instanceof EE_Cart) {
3199
-                    $grand_total = $cart->get_cart_grand_total();
3200
-                    if ($grand_total instanceof EE_Line_Item) {
3201
-                        $grand_total->save_this_and_descendants_to_txn();
3202
-                    }
3203
-                }
3204
-                if (! $transaction instanceof EE_Transaction) {
3205
-                    $query_args = array(
3206
-                        'action'                  => 'new_registration',
3207
-                        'processing_registration' => 2,
3208
-                        'event_id'                => $this->_reg_event->ID(),
3209
-                        'uts'                     => time(),
3210
-                    );
3211
-                    if (defined('DOING_AJAX')) {
3212
-                        // display registration form again because there are errors (maybe validation?)
3213
-                        $this->new_registration();
3214
-                        return;
3215
-                    } else {
3216
-                        $this->_redirect_after_action(
3217
-                            false,
3218
-                            '',
3219
-                            '',
3220
-                            $query_args,
3221
-                            true
3222
-                        );
3223
-                        return;
3224
-                    }
3225
-                }
3226
-                // maybe update status, and make sure to save transaction if not done already
3227
-                if (! $transaction->update_status_based_on_total_paid()) {
3228
-                    $transaction->save();
3229
-                }
3230
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3231
-                $this->_req_data = array();
3232
-                $query_args = array(
3233
-                    'action'        => 'redirect_to_txn',
3234
-                    'TXN_ID'        => $transaction->ID(),
3235
-                    'EVT_ID'        => $this->_reg_event->ID(),
3236
-                    'event_name'    => urlencode($this->_reg_event->name()),
3237
-                    'redirect_from' => 'new_registration',
3238
-                );
3239
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3240
-                break;
3241
-        }
3242
-        // what are you looking here for?  Should be nothing to do at this point.
3243
-    }
3244
-
3245
-
3246
-    /**
3247
-     * redirect_to_txn
3248
-     *
3249
-     * @access public
3250
-     * @return void
3251
-     * @throws EE_Error
3252
-     * @throws InvalidArgumentException
3253
-     * @throws InvalidDataTypeException
3254
-     * @throws InvalidInterfaceException
3255
-     */
3256
-    public function redirect_to_txn()
3257
-    {
3258
-        EE_System::do_not_cache();
3259
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3260
-        $query_args = array(
3261
-            'action' => 'view_transaction',
3262
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3263
-            'page'   => 'espresso_transactions',
3264
-        );
3265
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3266
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3267
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3268
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3269
-        }
3270
-        EE_Error::add_success(
3271
-            esc_html__(
3272
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3273
-                'event_espresso'
3274
-            )
3275
-        );
3276
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3277
-    }
3278
-
3279
-
3280
-    /**
3281
-     *        generates HTML for the Attendee Contact List
3282
-     *
3283
-     * @access protected
3284
-     * @return void
3285
-     */
3286
-    protected function _attendee_contact_list_table()
3287
-    {
3288
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3289
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3290
-        $this->display_admin_list_table_page_with_no_sidebar();
3291
-    }
3292
-
3293
-
3294
-    /**
3295
-     *        get_attendees
3296
-     *
3297
-     * @param      $per_page
3298
-     * @param bool $count whether to return count or data.
3299
-     * @param bool $trash
3300
-     * @return array
3301
-     * @throws EE_Error
3302
-     * @throws InvalidArgumentException
3303
-     * @throws InvalidDataTypeException
3304
-     * @throws InvalidInterfaceException
3305
-     * @access public
3306
-     */
3307
-    public function get_attendees($per_page, $count = false, $trash = false)
3308
-    {
3309
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3310
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3311
-        $ATT_MDL = EEM_Attendee::instance();
3312
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3313
-        switch ($this->_req_data['orderby']) {
3314
-            case 'ATT_ID':
3315
-                $orderby = 'ATT_ID';
3316
-                break;
3317
-            case 'ATT_fname':
3318
-                $orderby = 'ATT_fname';
3319
-                break;
3320
-            case 'ATT_email':
3321
-                $orderby = 'ATT_email';
3322
-                break;
3323
-            case 'ATT_city':
3324
-                $orderby = 'ATT_city';
3325
-                break;
3326
-            case 'STA_ID':
3327
-                $orderby = 'STA_ID';
3328
-                break;
3329
-            case 'CNT_ID':
3330
-                $orderby = 'CNT_ID';
3331
-                break;
3332
-            case 'Registration_Count':
3333
-                $orderby = 'Registration_Count';
3334
-                break;
3335
-            default:
3336
-                $orderby = 'ATT_lname';
3337
-        }
3338
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3339
-            ? $this->_req_data['order']
3340
-            : 'ASC';
3341
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3342
-            ? $this->_req_data['paged']
3343
-            : 1;
3344
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3345
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3346
-            ? $this->_req_data['perpage']
3347
-            : $per_page;
3348
-        $_where = array();
3349
-        if (! empty($this->_req_data['s'])) {
3350
-            $sstr = '%' . $this->_req_data['s'] . '%';
3351
-            $_where['OR'] = array(
3352
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3353
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3354
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3355
-                'ATT_fname'                         => array('LIKE', $sstr),
3356
-                'ATT_lname'                         => array('LIKE', $sstr),
3357
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3358
-                'ATT_email'                         => array('LIKE', $sstr),
3359
-                'ATT_address'                       => array('LIKE', $sstr),
3360
-                'ATT_address2'                      => array('LIKE', $sstr),
3361
-                'ATT_city'                          => array('LIKE', $sstr),
3362
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3363
-                'State.STA_name'                    => array('LIKE', $sstr),
3364
-                'ATT_phone'                         => array('LIKE', $sstr),
3365
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3366
-                'Registration.REG_code'             => array('LIKE', $sstr),
3367
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3368
-            );
3369
-        }
3370
-        $offset = ($current_page - 1) * $per_page;
3371
-        $limit = $count ? null : array($offset, $per_page);
3372
-        $query_args = array(
3373
-            $_where,
3374
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3375
-            'limit'         => $limit,
3376
-        );
3377
-        if (! $count) {
3378
-            $query_args['order_by'] = array($orderby => $sort);
3379
-        }
3380
-        if ($trash) {
3381
-            $query_args[0]['status'] = array('!=', 'publish');
3382
-            $all_attendees = $count
3383
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3384
-                : $ATT_MDL->get_all($query_args);
3385
-        } else {
3386
-            $query_args[0]['status'] = array('IN', array('publish'));
3387
-            $all_attendees = $count
3388
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3389
-                : $ATT_MDL->get_all($query_args);
3390
-        }
3391
-        return $all_attendees;
3392
-    }
3393
-
3394
-
3395
-    /**
3396
-     * This is just taking care of resending the registration confirmation
3397
-     *
3398
-     * @access protected
3399
-     * @return void
3400
-     */
3401
-    protected function _resend_registration()
3402
-    {
3403
-        $this->_process_resend_registration();
3404
-        $query_args = isset($this->_req_data['redirect_to'])
3405
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3406
-            : array('action' => 'default');
3407
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3408
-    }
3409
-
3410
-    /**
3411
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3412
-     * to use when selecting registrations
3413
-     *
3414
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3415
-     *                                                     the query parameters from the request
3416
-     * @return void ends the request with a redirect or download
3417
-     */
3418
-    public function _registrations_report_base($method_name_for_getting_query_params)
3419
-    {
3420
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3421
-            wp_redirect(
3422
-                EE_Admin_Page::add_query_args_and_nonce(
3423
-                    array(
3424
-                        'page'        => 'espresso_batch',
3425
-                        'batch'       => 'file',
3426
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3427
-                        'filters'     => urlencode(
3428
-                            serialize(
3429
-                                call_user_func(
3430
-                                    array($this, $method_name_for_getting_query_params),
3431
-                                    EEH_Array::is_set(
3432
-                                        $this->_req_data,
3433
-                                        'filters',
3434
-                                        array()
3435
-                                    )
3436
-                                )
3437
-                            )
3438
-                        ),
3439
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3440
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3441
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3442
-                    )
3443
-                )
3444
-            );
3445
-        } else {
3446
-            $new_request_args = array(
3447
-                'export' => 'report',
3448
-                'action' => 'registrations_report_for_event',
3449
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3450
-            );
3451
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3452
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3453
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3454
-                $EE_Export = EE_Export::instance($this->_req_data);
3455
-                $EE_Export->export();
3456
-            }
3457
-        }
3458
-    }
3459
-
3460
-
3461
-    /**
3462
-     * Creates a registration report using only query parameters in the request
3463
-     *
3464
-     * @return void
3465
-     */
3466
-    public function _registrations_report()
3467
-    {
3468
-        $this->_registrations_report_base('_get_registration_query_parameters');
3469
-    }
3470
-
3471
-
3472
-    public function _contact_list_export()
3473
-    {
3474
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3475
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3476
-            $EE_Export = EE_Export::instance($this->_req_data);
3477
-            $EE_Export->export_attendees();
3478
-        }
3479
-    }
3480
-
3481
-
3482
-    public function _contact_list_report()
3483
-    {
3484
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3485
-            wp_redirect(
3486
-                EE_Admin_Page::add_query_args_and_nonce(
3487
-                    array(
3488
-                        'page'        => 'espresso_batch',
3489
-                        'batch'       => 'file',
3490
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3491
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3492
-                    )
3493
-                )
3494
-            );
3495
-        } else {
3496
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3497
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3498
-                $EE_Export = EE_Export::instance($this->_req_data);
3499
-                $EE_Export->report_attendees();
3500
-            }
3501
-        }
3502
-    }
3503
-
3504
-
3505
-
3506
-
3507
-
3508
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3509
-    /**
3510
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3511
-     *
3512
-     * @return void
3513
-     * @throws EE_Error
3514
-     * @throws InvalidArgumentException
3515
-     * @throws InvalidDataTypeException
3516
-     * @throws InvalidInterfaceException
3517
-     */
3518
-    protected function _duplicate_attendee()
3519
-    {
3520
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3521
-        // verify we have necessary info
3522
-        if (empty($this->_req_data['_REG_ID'])) {
3523
-            EE_Error::add_error(
3524
-                esc_html__(
3525
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3526
-                    'event_espresso'
3527
-                ),
3528
-                __FILE__,
3529
-                __LINE__,
3530
-                __FUNCTION__
3531
-            );
3532
-            $query_args = array('action' => $action);
3533
-            $this->_redirect_after_action('', '', '', $query_args, true);
3534
-        }
3535
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3536
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3537
-        $attendee = $registration->attendee();
3538
-        // remove relation of existing attendee on registration
3539
-        $registration->_remove_relation_to($attendee, 'Attendee');
3540
-        // new attendee
3541
-        $new_attendee = clone $attendee;
3542
-        $new_attendee->set('ATT_ID', 0);
3543
-        $new_attendee->save();
3544
-        // add new attendee to reg
3545
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3546
-        EE_Error::add_success(
3547
-            esc_html__(
3548
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3549
-                'event_espresso'
3550
-            )
3551
-        );
3552
-        // redirect to edit page for attendee
3553
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3554
-        $this->_redirect_after_action('', '', '', $query_args, true);
3555
-    }
3556
-
3557
-
3558
-    /**
3559
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3560
-     *
3561
-     * @param int     $post_id
3562
-     * @param WP_POST $post
3563
-     * @throws DomainException
3564
-     * @throws EE_Error
3565
-     * @throws InvalidArgumentException
3566
-     * @throws InvalidDataTypeException
3567
-     * @throws InvalidInterfaceException
3568
-     * @throws LogicException
3569
-     * @throws InvalidFormSubmissionException
3570
-     */
3571
-    protected function _insert_update_cpt_item($post_id, $post)
3572
-    {
3573
-        $success = true;
3574
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3575
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3576
-            : null;
3577
-        // for attendee updates
3578
-        if ($attendee instanceof EE_Attendee) {
3579
-            // note we should only be UPDATING attendees at this point.
3580
-            $updated_fields = array(
3581
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3582
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3583
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3584
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3585
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3586
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3587
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3588
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3589
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3590
-            );
3591
-            foreach ($updated_fields as $field => $value) {
3592
-                $attendee->set($field, $value);
3593
-            }
3594
-
3595
-            // process contact details metabox form handler (which will also save the attendee)
3596
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3597
-            $success = $contact_details_form->process($this->_req_data);
3598
-
3599
-            $attendee_update_callbacks = apply_filters(
3600
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3601
-                array()
3602
-            );
3603
-            foreach ($attendee_update_callbacks as $a_callback) {
3604
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3605
-                    throw new EE_Error(
3606
-                        sprintf(
3607
-                            esc_html__(
3608
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3609
-                                'event_espresso'
3610
-                            ),
3611
-                            $a_callback
3612
-                        )
3613
-                    );
3614
-                }
3615
-            }
3616
-        }
3617
-
3618
-        if ($success === false) {
3619
-            EE_Error::add_error(
3620
-                esc_html__(
3621
-                    'Something went wrong with updating the meta table data for the registration.',
3622
-                    'event_espresso'
3623
-                ),
3624
-                __FILE__,
3625
-                __FUNCTION__,
3626
-                __LINE__
3627
-            );
3628
-        }
3629
-    }
3630
-
3631
-
3632
-    public function trash_cpt_item($post_id)
3633
-    {
3634
-    }
3635
-
3636
-
3637
-    public function delete_cpt_item($post_id)
3638
-    {
3639
-    }
3640
-
3641
-
3642
-    public function restore_cpt_item($post_id)
3643
-    {
3644
-    }
3645
-
3646
-
3647
-    protected function _restore_cpt_item($post_id, $revision_id)
3648
-    {
3649
-    }
3650
-
3651
-
3652
-    public function attendee_editor_metaboxes()
3653
-    {
3654
-        $this->verify_cpt_object();
3655
-        remove_meta_box(
3656
-            'postexcerpt',
3657
-            esc_html__('Excerpt', 'event_espresso'),
3658
-            'post_excerpt_meta_box',
3659
-            $this->_cpt_routes[ $this->_req_action ],
3660
-            'normal',
3661
-            'core'
3662
-        );
3663
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3664
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3665
-            add_meta_box(
3666
-                'postexcerpt',
3667
-                esc_html__('Short Biography', 'event_espresso'),
3668
-                'post_excerpt_meta_box',
3669
-                $this->_cpt_routes[ $this->_req_action ],
3670
-                'normal'
3671
-            );
3672
-        }
3673
-        if (post_type_supports('espresso_attendees', 'comments')) {
3674
-            add_meta_box(
3675
-                'commentsdiv',
3676
-                esc_html__('Notes on the Contact', 'event_espresso'),
3677
-                'post_comment_meta_box',
3678
-                $this->_cpt_routes[ $this->_req_action ],
3679
-                'normal',
3680
-                'core'
3681
-            );
3682
-        }
3683
-        add_meta_box(
3684
-            'attendee_contact_info',
3685
-            esc_html__('Contact Info', 'event_espresso'),
3686
-            array($this, 'attendee_contact_info'),
3687
-            $this->_cpt_routes[ $this->_req_action ],
3688
-            'side',
3689
-            'core'
3690
-        );
3691
-        add_meta_box(
3692
-            'attendee_details_address',
3693
-            esc_html__('Address Details', 'event_espresso'),
3694
-            array($this, 'attendee_address_details'),
3695
-            $this->_cpt_routes[ $this->_req_action ],
3696
-            'normal',
3697
-            'core'
3698
-        );
3699
-        add_meta_box(
3700
-            'attendee_registrations',
3701
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3702
-            array($this, 'attendee_registrations_meta_box'),
3703
-            $this->_cpt_routes[ $this->_req_action ],
3704
-            'normal',
3705
-            'high'
3706
-        );
3707
-    }
3708
-
3709
-
3710
-    /**
3711
-     * Metabox for attendee contact info
3712
-     *
3713
-     * @param  WP_Post $post wp post object
3714
-     * @return string attendee contact info ( and form )
3715
-     * @throws EE_Error
3716
-     * @throws InvalidArgumentException
3717
-     * @throws InvalidDataTypeException
3718
-     * @throws InvalidInterfaceException
3719
-     * @throws LogicException
3720
-     * @throws DomainException
3721
-     */
3722
-    public function attendee_contact_info($post)
3723
-    {
3724
-        // get attendee object ( should already have it )
3725
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3726
-        $form->enqueueStylesAndScripts();
3727
-        echo $form->display();
3728
-    }
3729
-
3730
-
3731
-    /**
3732
-     * Return form handler for the contact details metabox
3733
-     *
3734
-     * @param EE_Attendee $attendee
3735
-     * @return AttendeeContactDetailsMetaboxFormHandler
3736
-     * @throws DomainException
3737
-     * @throws InvalidArgumentException
3738
-     * @throws InvalidDataTypeException
3739
-     * @throws InvalidInterfaceException
3740
-     */
3741
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3742
-    {
3743
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3744
-    }
3745
-
3746
-
3747
-    /**
3748
-     * Metabox for attendee details
3749
-     *
3750
-     * @param  WP_Post $post wp post object
3751
-     * @throws DomainException
3752
-     */
3753
-    public function attendee_address_details($post)
3754
-    {
3755
-        // get attendee object (should already have it)
3756
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3757
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3758
-            new EE_Question_Form_Input(
3759
-                EE_Question::new_instance(
3760
-                    array(
3761
-                        'QST_ID'           => 0,
3762
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3763
-                        'QST_system'       => 'admin-state',
3764
-                    )
3765
-                ),
3766
-                EE_Answer::new_instance(
3767
-                    array(
3768
-                        'ANS_ID'    => 0,
3769
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3770
-                    )
3771
-                ),
3772
-                array(
3773
-                    'input_id'       => 'STA_ID',
3774
-                    'input_name'     => 'STA_ID',
3775
-                    'input_prefix'   => '',
3776
-                    'append_qstn_id' => false,
3777
-                )
3778
-            )
3779
-        );
3780
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3781
-            new EE_Question_Form_Input(
3782
-                EE_Question::new_instance(
3783
-                    array(
3784
-                        'QST_ID'           => 0,
3785
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3786
-                        'QST_system'       => 'admin-country',
3787
-                    )
3788
-                ),
3789
-                EE_Answer::new_instance(
3790
-                    array(
3791
-                        'ANS_ID'    => 0,
3792
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3793
-                    )
3794
-                ),
3795
-                array(
3796
-                    'input_id'       => 'CNT_ISO',
3797
-                    'input_name'     => 'CNT_ISO',
3798
-                    'input_prefix'   => '',
3799
-                    'append_qstn_id' => false,
3800
-                )
3801
-            )
3802
-        );
3803
-        $template =
3804
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3805
-        EEH_Template::display_template($template, $this->_template_args);
3806
-    }
3807
-
3808
-
3809
-    /**
3810
-     *        _attendee_details
3811
-     *
3812
-     * @access protected
3813
-     * @param $post
3814
-     * @return void
3815
-     * @throws DomainException
3816
-     * @throws EE_Error
3817
-     */
3818
-    public function attendee_registrations_meta_box($post)
3819
-    {
3820
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3821
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3822
-        $template =
3823
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3824
-        EEH_Template::display_template($template, $this->_template_args);
3825
-    }
3826
-
3827
-
3828
-    /**
3829
-     * add in the form fields for the attendee edit
3830
-     *
3831
-     * @param  WP_Post $post wp post object
3832
-     * @return string html for new form.
3833
-     * @throws DomainException
3834
-     */
3835
-    public function after_title_form_fields($post)
3836
-    {
3837
-        if ($post->post_type == 'espresso_attendees') {
3838
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3839
-            $template_args['attendee'] = $this->_cpt_model_obj;
3840
-            EEH_Template::display_template($template, $template_args);
3841
-        }
3842
-    }
3843
-
3844
-
3845
-    /**
3846
-     *        _trash_or_restore_attendee
3847
-     *
3848
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3849
-     * @return void
3850
-     * @throws EE_Error
3851
-     * @throws InvalidArgumentException
3852
-     * @throws InvalidDataTypeException
3853
-     * @throws InvalidInterfaceException
3854
-     * @access protected
3855
-     */
3856
-    protected function _trash_or_restore_attendees($trash = true)
3857
-    {
3858
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3859
-        $ATT_MDL = EEM_Attendee::instance();
3860
-        $success = 1;
3861
-        // Checkboxes
3862
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3863
-            // if array has more than one element than success message should be plural
3864
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3865
-            // cycle thru checkboxes
3866
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3867
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3868
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3869
-                if (! $updated) {
3870
-                    $success = 0;
3871
-                }
3872
-            }
3873
-        } else {
3874
-            // grab single id and delete
3875
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3876
-            // get attendee
3877
-            $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3878
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3879
-            $updated = $att->save();
3880
-            if (! $updated) {
3881
-                $success = 0;
3882
-            }
3883
-        }
3884
-        $what = $success > 1
3885
-            ? esc_html__('Contacts', 'event_espresso')
3886
-            : esc_html__('Contact', 'event_espresso');
3887
-        $action_desc = $trash
3888
-            ? esc_html__('moved to the trash', 'event_espresso')
3889
-            : esc_html__('restored', 'event_espresso');
3890
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3891
-    }
3041
+		}
3042
+		$template_args = array(
3043
+			'title'                    => '',
3044
+			'content'                  => '',
3045
+			'step_button_text'         => '',
3046
+			'show_notification_toggle' => false,
3047
+		);
3048
+		// to indicate we're processing a new registration
3049
+		$hidden_fields = array(
3050
+			'processing_registration' => array(
3051
+				'type'  => 'hidden',
3052
+				'value' => 0,
3053
+			),
3054
+			'event_id'                => array(
3055
+				'type'  => 'hidden',
3056
+				'value' => $this->_reg_event->ID(),
3057
+			),
3058
+		);
3059
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
3060
+		$cart = EE_Registry::instance()->SSN->cart();
3061
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3062
+		switch ($step) {
3063
+			case 'ticket':
3064
+				$hidden_fields['processing_registration']['value'] = 1;
3065
+				$template_args['title'] = esc_html__(
3066
+					'Step One: Select the Ticket for this registration',
3067
+					'event_espresso'
3068
+				);
3069
+				$template_args['content'] =
3070
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3071
+				$template_args['step_button_text'] = esc_html__(
3072
+					'Add Tickets and Continue to Registrant Details',
3073
+					'event_espresso'
3074
+				);
3075
+				$template_args['show_notification_toggle'] = false;
3076
+				break;
3077
+			case 'questions':
3078
+				$hidden_fields['processing_registration']['value'] = 2;
3079
+				$template_args['title'] = esc_html__(
3080
+					'Step Two: Add Registrant Details for this Registration',
3081
+					'event_espresso'
3082
+				);
3083
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3084
+				// properly by the first process_reg_step run.
3085
+				$template_args['content'] =
3086
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3087
+				$template_args['step_button_text'] = esc_html__(
3088
+					'Save Registration and Continue to Details',
3089
+					'event_espresso'
3090
+				);
3091
+				$template_args['show_notification_toggle'] = true;
3092
+				break;
3093
+		}
3094
+		// we come back to the process_registration_step route.
3095
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3096
+		return EEH_Template::display_template(
3097
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3098
+			$template_args,
3099
+			true
3100
+		);
3101
+	}
3102
+
3103
+
3104
+	/**
3105
+	 *        set_reg_event
3106
+	 *
3107
+	 * @access private
3108
+	 * @return bool
3109
+	 * @throws EE_Error
3110
+	 * @throws InvalidArgumentException
3111
+	 * @throws InvalidDataTypeException
3112
+	 * @throws InvalidInterfaceException
3113
+	 */
3114
+	private function _set_reg_event()
3115
+	{
3116
+		if (is_object($this->_reg_event)) {
3117
+			return true;
3118
+		}
3119
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3120
+		if (! $EVT_ID) {
3121
+			return false;
3122
+		}
3123
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3124
+		return true;
3125
+	}
3126
+
3127
+
3128
+	/**
3129
+	 * process_reg_step
3130
+	 *
3131
+	 * @access        public
3132
+	 * @return string
3133
+	 * @throws DomainException
3134
+	 * @throws EE_Error
3135
+	 * @throws InvalidArgumentException
3136
+	 * @throws InvalidDataTypeException
3137
+	 * @throws InvalidInterfaceException
3138
+	 * @throws ReflectionException
3139
+	 * @throws RuntimeException
3140
+	 */
3141
+	public function process_reg_step()
3142
+	{
3143
+		EE_System::do_not_cache();
3144
+		$this->_set_reg_event();
3145
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3146
+		EE_Registry::instance()->REQ->set('uts', time());
3147
+		// what step are we on?
3148
+		$cart = EE_Registry::instance()->SSN->cart();
3149
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3150
+		// if doing ajax then we need to verify the nonce
3151
+		if (defined('DOING_AJAX')) {
3152
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3153
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3154
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3155
+		}
3156
+		switch ($step) {
3157
+			case 'ticket':
3158
+				// process ticket selection
3159
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3160
+				if ($success) {
3161
+					EE_Error::add_success(
3162
+						esc_html__(
3163
+							'Tickets Selected. Now complete the registration.',
3164
+							'event_espresso'
3165
+						)
3166
+					);
3167
+				} else {
3168
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3169
+				}
3170
+				if (defined('DOING_AJAX')) {
3171
+					$this->new_registration(); // display next step
3172
+				} else {
3173
+					$query_args = array(
3174
+						'action'                  => 'new_registration',
3175
+						'processing_registration' => 1,
3176
+						'event_id'                => $this->_reg_event->ID(),
3177
+						'uts'                     => time(),
3178
+					);
3179
+					$this->_redirect_after_action(
3180
+						false,
3181
+						'',
3182
+						'',
3183
+						$query_args,
3184
+						true
3185
+					);
3186
+				}
3187
+				break;
3188
+			case 'questions':
3189
+				if (! isset(
3190
+					$this->_req_data['txn_reg_status_change'],
3191
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3192
+				)
3193
+				) {
3194
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3195
+				}
3196
+				// process registration
3197
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3198
+				if ($cart instanceof EE_Cart) {
3199
+					$grand_total = $cart->get_cart_grand_total();
3200
+					if ($grand_total instanceof EE_Line_Item) {
3201
+						$grand_total->save_this_and_descendants_to_txn();
3202
+					}
3203
+				}
3204
+				if (! $transaction instanceof EE_Transaction) {
3205
+					$query_args = array(
3206
+						'action'                  => 'new_registration',
3207
+						'processing_registration' => 2,
3208
+						'event_id'                => $this->_reg_event->ID(),
3209
+						'uts'                     => time(),
3210
+					);
3211
+					if (defined('DOING_AJAX')) {
3212
+						// display registration form again because there are errors (maybe validation?)
3213
+						$this->new_registration();
3214
+						return;
3215
+					} else {
3216
+						$this->_redirect_after_action(
3217
+							false,
3218
+							'',
3219
+							'',
3220
+							$query_args,
3221
+							true
3222
+						);
3223
+						return;
3224
+					}
3225
+				}
3226
+				// maybe update status, and make sure to save transaction if not done already
3227
+				if (! $transaction->update_status_based_on_total_paid()) {
3228
+					$transaction->save();
3229
+				}
3230
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3231
+				$this->_req_data = array();
3232
+				$query_args = array(
3233
+					'action'        => 'redirect_to_txn',
3234
+					'TXN_ID'        => $transaction->ID(),
3235
+					'EVT_ID'        => $this->_reg_event->ID(),
3236
+					'event_name'    => urlencode($this->_reg_event->name()),
3237
+					'redirect_from' => 'new_registration',
3238
+				);
3239
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3240
+				break;
3241
+		}
3242
+		// what are you looking here for?  Should be nothing to do at this point.
3243
+	}
3244
+
3245
+
3246
+	/**
3247
+	 * redirect_to_txn
3248
+	 *
3249
+	 * @access public
3250
+	 * @return void
3251
+	 * @throws EE_Error
3252
+	 * @throws InvalidArgumentException
3253
+	 * @throws InvalidDataTypeException
3254
+	 * @throws InvalidInterfaceException
3255
+	 */
3256
+	public function redirect_to_txn()
3257
+	{
3258
+		EE_System::do_not_cache();
3259
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3260
+		$query_args = array(
3261
+			'action' => 'view_transaction',
3262
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3263
+			'page'   => 'espresso_transactions',
3264
+		);
3265
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3266
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3267
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3268
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3269
+		}
3270
+		EE_Error::add_success(
3271
+			esc_html__(
3272
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3273
+				'event_espresso'
3274
+			)
3275
+		);
3276
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3277
+	}
3278
+
3279
+
3280
+	/**
3281
+	 *        generates HTML for the Attendee Contact List
3282
+	 *
3283
+	 * @access protected
3284
+	 * @return void
3285
+	 */
3286
+	protected function _attendee_contact_list_table()
3287
+	{
3288
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3289
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3290
+		$this->display_admin_list_table_page_with_no_sidebar();
3291
+	}
3292
+
3293
+
3294
+	/**
3295
+	 *        get_attendees
3296
+	 *
3297
+	 * @param      $per_page
3298
+	 * @param bool $count whether to return count or data.
3299
+	 * @param bool $trash
3300
+	 * @return array
3301
+	 * @throws EE_Error
3302
+	 * @throws InvalidArgumentException
3303
+	 * @throws InvalidDataTypeException
3304
+	 * @throws InvalidInterfaceException
3305
+	 * @access public
3306
+	 */
3307
+	public function get_attendees($per_page, $count = false, $trash = false)
3308
+	{
3309
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3310
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3311
+		$ATT_MDL = EEM_Attendee::instance();
3312
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3313
+		switch ($this->_req_data['orderby']) {
3314
+			case 'ATT_ID':
3315
+				$orderby = 'ATT_ID';
3316
+				break;
3317
+			case 'ATT_fname':
3318
+				$orderby = 'ATT_fname';
3319
+				break;
3320
+			case 'ATT_email':
3321
+				$orderby = 'ATT_email';
3322
+				break;
3323
+			case 'ATT_city':
3324
+				$orderby = 'ATT_city';
3325
+				break;
3326
+			case 'STA_ID':
3327
+				$orderby = 'STA_ID';
3328
+				break;
3329
+			case 'CNT_ID':
3330
+				$orderby = 'CNT_ID';
3331
+				break;
3332
+			case 'Registration_Count':
3333
+				$orderby = 'Registration_Count';
3334
+				break;
3335
+			default:
3336
+				$orderby = 'ATT_lname';
3337
+		}
3338
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3339
+			? $this->_req_data['order']
3340
+			: 'ASC';
3341
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3342
+			? $this->_req_data['paged']
3343
+			: 1;
3344
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3345
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3346
+			? $this->_req_data['perpage']
3347
+			: $per_page;
3348
+		$_where = array();
3349
+		if (! empty($this->_req_data['s'])) {
3350
+			$sstr = '%' . $this->_req_data['s'] . '%';
3351
+			$_where['OR'] = array(
3352
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3353
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3354
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3355
+				'ATT_fname'                         => array('LIKE', $sstr),
3356
+				'ATT_lname'                         => array('LIKE', $sstr),
3357
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3358
+				'ATT_email'                         => array('LIKE', $sstr),
3359
+				'ATT_address'                       => array('LIKE', $sstr),
3360
+				'ATT_address2'                      => array('LIKE', $sstr),
3361
+				'ATT_city'                          => array('LIKE', $sstr),
3362
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3363
+				'State.STA_name'                    => array('LIKE', $sstr),
3364
+				'ATT_phone'                         => array('LIKE', $sstr),
3365
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3366
+				'Registration.REG_code'             => array('LIKE', $sstr),
3367
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3368
+			);
3369
+		}
3370
+		$offset = ($current_page - 1) * $per_page;
3371
+		$limit = $count ? null : array($offset, $per_page);
3372
+		$query_args = array(
3373
+			$_where,
3374
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3375
+			'limit'         => $limit,
3376
+		);
3377
+		if (! $count) {
3378
+			$query_args['order_by'] = array($orderby => $sort);
3379
+		}
3380
+		if ($trash) {
3381
+			$query_args[0]['status'] = array('!=', 'publish');
3382
+			$all_attendees = $count
3383
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3384
+				: $ATT_MDL->get_all($query_args);
3385
+		} else {
3386
+			$query_args[0]['status'] = array('IN', array('publish'));
3387
+			$all_attendees = $count
3388
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3389
+				: $ATT_MDL->get_all($query_args);
3390
+		}
3391
+		return $all_attendees;
3392
+	}
3393
+
3394
+
3395
+	/**
3396
+	 * This is just taking care of resending the registration confirmation
3397
+	 *
3398
+	 * @access protected
3399
+	 * @return void
3400
+	 */
3401
+	protected function _resend_registration()
3402
+	{
3403
+		$this->_process_resend_registration();
3404
+		$query_args = isset($this->_req_data['redirect_to'])
3405
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3406
+			: array('action' => 'default');
3407
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3408
+	}
3409
+
3410
+	/**
3411
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3412
+	 * to use when selecting registrations
3413
+	 *
3414
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3415
+	 *                                                     the query parameters from the request
3416
+	 * @return void ends the request with a redirect or download
3417
+	 */
3418
+	public function _registrations_report_base($method_name_for_getting_query_params)
3419
+	{
3420
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3421
+			wp_redirect(
3422
+				EE_Admin_Page::add_query_args_and_nonce(
3423
+					array(
3424
+						'page'        => 'espresso_batch',
3425
+						'batch'       => 'file',
3426
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3427
+						'filters'     => urlencode(
3428
+							serialize(
3429
+								call_user_func(
3430
+									array($this, $method_name_for_getting_query_params),
3431
+									EEH_Array::is_set(
3432
+										$this->_req_data,
3433
+										'filters',
3434
+										array()
3435
+									)
3436
+								)
3437
+							)
3438
+						),
3439
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3440
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3441
+						'return_url'  => urlencode($this->_req_data['return_url']),
3442
+					)
3443
+				)
3444
+			);
3445
+		} else {
3446
+			$new_request_args = array(
3447
+				'export' => 'report',
3448
+				'action' => 'registrations_report_for_event',
3449
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3450
+			);
3451
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3452
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3453
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3454
+				$EE_Export = EE_Export::instance($this->_req_data);
3455
+				$EE_Export->export();
3456
+			}
3457
+		}
3458
+	}
3459
+
3460
+
3461
+	/**
3462
+	 * Creates a registration report using only query parameters in the request
3463
+	 *
3464
+	 * @return void
3465
+	 */
3466
+	public function _registrations_report()
3467
+	{
3468
+		$this->_registrations_report_base('_get_registration_query_parameters');
3469
+	}
3470
+
3471
+
3472
+	public function _contact_list_export()
3473
+	{
3474
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3475
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3476
+			$EE_Export = EE_Export::instance($this->_req_data);
3477
+			$EE_Export->export_attendees();
3478
+		}
3479
+	}
3480
+
3481
+
3482
+	public function _contact_list_report()
3483
+	{
3484
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3485
+			wp_redirect(
3486
+				EE_Admin_Page::add_query_args_and_nonce(
3487
+					array(
3488
+						'page'        => 'espresso_batch',
3489
+						'batch'       => 'file',
3490
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3491
+						'return_url'  => urlencode($this->_req_data['return_url']),
3492
+					)
3493
+				)
3494
+			);
3495
+		} else {
3496
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3497
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3498
+				$EE_Export = EE_Export::instance($this->_req_data);
3499
+				$EE_Export->report_attendees();
3500
+			}
3501
+		}
3502
+	}
3503
+
3504
+
3505
+
3506
+
3507
+
3508
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3509
+	/**
3510
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3511
+	 *
3512
+	 * @return void
3513
+	 * @throws EE_Error
3514
+	 * @throws InvalidArgumentException
3515
+	 * @throws InvalidDataTypeException
3516
+	 * @throws InvalidInterfaceException
3517
+	 */
3518
+	protected function _duplicate_attendee()
3519
+	{
3520
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3521
+		// verify we have necessary info
3522
+		if (empty($this->_req_data['_REG_ID'])) {
3523
+			EE_Error::add_error(
3524
+				esc_html__(
3525
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3526
+					'event_espresso'
3527
+				),
3528
+				__FILE__,
3529
+				__LINE__,
3530
+				__FUNCTION__
3531
+			);
3532
+			$query_args = array('action' => $action);
3533
+			$this->_redirect_after_action('', '', '', $query_args, true);
3534
+		}
3535
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3536
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3537
+		$attendee = $registration->attendee();
3538
+		// remove relation of existing attendee on registration
3539
+		$registration->_remove_relation_to($attendee, 'Attendee');
3540
+		// new attendee
3541
+		$new_attendee = clone $attendee;
3542
+		$new_attendee->set('ATT_ID', 0);
3543
+		$new_attendee->save();
3544
+		// add new attendee to reg
3545
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3546
+		EE_Error::add_success(
3547
+			esc_html__(
3548
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3549
+				'event_espresso'
3550
+			)
3551
+		);
3552
+		// redirect to edit page for attendee
3553
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3554
+		$this->_redirect_after_action('', '', '', $query_args, true);
3555
+	}
3556
+
3557
+
3558
+	/**
3559
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3560
+	 *
3561
+	 * @param int     $post_id
3562
+	 * @param WP_POST $post
3563
+	 * @throws DomainException
3564
+	 * @throws EE_Error
3565
+	 * @throws InvalidArgumentException
3566
+	 * @throws InvalidDataTypeException
3567
+	 * @throws InvalidInterfaceException
3568
+	 * @throws LogicException
3569
+	 * @throws InvalidFormSubmissionException
3570
+	 */
3571
+	protected function _insert_update_cpt_item($post_id, $post)
3572
+	{
3573
+		$success = true;
3574
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3575
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3576
+			: null;
3577
+		// for attendee updates
3578
+		if ($attendee instanceof EE_Attendee) {
3579
+			// note we should only be UPDATING attendees at this point.
3580
+			$updated_fields = array(
3581
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3582
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3583
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3584
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3585
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3586
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3587
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3588
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3589
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3590
+			);
3591
+			foreach ($updated_fields as $field => $value) {
3592
+				$attendee->set($field, $value);
3593
+			}
3594
+
3595
+			// process contact details metabox form handler (which will also save the attendee)
3596
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3597
+			$success = $contact_details_form->process($this->_req_data);
3598
+
3599
+			$attendee_update_callbacks = apply_filters(
3600
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3601
+				array()
3602
+			);
3603
+			foreach ($attendee_update_callbacks as $a_callback) {
3604
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3605
+					throw new EE_Error(
3606
+						sprintf(
3607
+							esc_html__(
3608
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3609
+								'event_espresso'
3610
+							),
3611
+							$a_callback
3612
+						)
3613
+					);
3614
+				}
3615
+			}
3616
+		}
3617
+
3618
+		if ($success === false) {
3619
+			EE_Error::add_error(
3620
+				esc_html__(
3621
+					'Something went wrong with updating the meta table data for the registration.',
3622
+					'event_espresso'
3623
+				),
3624
+				__FILE__,
3625
+				__FUNCTION__,
3626
+				__LINE__
3627
+			);
3628
+		}
3629
+	}
3630
+
3631
+
3632
+	public function trash_cpt_item($post_id)
3633
+	{
3634
+	}
3635
+
3636
+
3637
+	public function delete_cpt_item($post_id)
3638
+	{
3639
+	}
3640
+
3641
+
3642
+	public function restore_cpt_item($post_id)
3643
+	{
3644
+	}
3645
+
3646
+
3647
+	protected function _restore_cpt_item($post_id, $revision_id)
3648
+	{
3649
+	}
3650
+
3651
+
3652
+	public function attendee_editor_metaboxes()
3653
+	{
3654
+		$this->verify_cpt_object();
3655
+		remove_meta_box(
3656
+			'postexcerpt',
3657
+			esc_html__('Excerpt', 'event_espresso'),
3658
+			'post_excerpt_meta_box',
3659
+			$this->_cpt_routes[ $this->_req_action ],
3660
+			'normal',
3661
+			'core'
3662
+		);
3663
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3664
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3665
+			add_meta_box(
3666
+				'postexcerpt',
3667
+				esc_html__('Short Biography', 'event_espresso'),
3668
+				'post_excerpt_meta_box',
3669
+				$this->_cpt_routes[ $this->_req_action ],
3670
+				'normal'
3671
+			);
3672
+		}
3673
+		if (post_type_supports('espresso_attendees', 'comments')) {
3674
+			add_meta_box(
3675
+				'commentsdiv',
3676
+				esc_html__('Notes on the Contact', 'event_espresso'),
3677
+				'post_comment_meta_box',
3678
+				$this->_cpt_routes[ $this->_req_action ],
3679
+				'normal',
3680
+				'core'
3681
+			);
3682
+		}
3683
+		add_meta_box(
3684
+			'attendee_contact_info',
3685
+			esc_html__('Contact Info', 'event_espresso'),
3686
+			array($this, 'attendee_contact_info'),
3687
+			$this->_cpt_routes[ $this->_req_action ],
3688
+			'side',
3689
+			'core'
3690
+		);
3691
+		add_meta_box(
3692
+			'attendee_details_address',
3693
+			esc_html__('Address Details', 'event_espresso'),
3694
+			array($this, 'attendee_address_details'),
3695
+			$this->_cpt_routes[ $this->_req_action ],
3696
+			'normal',
3697
+			'core'
3698
+		);
3699
+		add_meta_box(
3700
+			'attendee_registrations',
3701
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3702
+			array($this, 'attendee_registrations_meta_box'),
3703
+			$this->_cpt_routes[ $this->_req_action ],
3704
+			'normal',
3705
+			'high'
3706
+		);
3707
+	}
3708
+
3709
+
3710
+	/**
3711
+	 * Metabox for attendee contact info
3712
+	 *
3713
+	 * @param  WP_Post $post wp post object
3714
+	 * @return string attendee contact info ( and form )
3715
+	 * @throws EE_Error
3716
+	 * @throws InvalidArgumentException
3717
+	 * @throws InvalidDataTypeException
3718
+	 * @throws InvalidInterfaceException
3719
+	 * @throws LogicException
3720
+	 * @throws DomainException
3721
+	 */
3722
+	public function attendee_contact_info($post)
3723
+	{
3724
+		// get attendee object ( should already have it )
3725
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3726
+		$form->enqueueStylesAndScripts();
3727
+		echo $form->display();
3728
+	}
3729
+
3730
+
3731
+	/**
3732
+	 * Return form handler for the contact details metabox
3733
+	 *
3734
+	 * @param EE_Attendee $attendee
3735
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3736
+	 * @throws DomainException
3737
+	 * @throws InvalidArgumentException
3738
+	 * @throws InvalidDataTypeException
3739
+	 * @throws InvalidInterfaceException
3740
+	 */
3741
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3742
+	{
3743
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3744
+	}
3745
+
3746
+
3747
+	/**
3748
+	 * Metabox for attendee details
3749
+	 *
3750
+	 * @param  WP_Post $post wp post object
3751
+	 * @throws DomainException
3752
+	 */
3753
+	public function attendee_address_details($post)
3754
+	{
3755
+		// get attendee object (should already have it)
3756
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3757
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3758
+			new EE_Question_Form_Input(
3759
+				EE_Question::new_instance(
3760
+					array(
3761
+						'QST_ID'           => 0,
3762
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3763
+						'QST_system'       => 'admin-state',
3764
+					)
3765
+				),
3766
+				EE_Answer::new_instance(
3767
+					array(
3768
+						'ANS_ID'    => 0,
3769
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3770
+					)
3771
+				),
3772
+				array(
3773
+					'input_id'       => 'STA_ID',
3774
+					'input_name'     => 'STA_ID',
3775
+					'input_prefix'   => '',
3776
+					'append_qstn_id' => false,
3777
+				)
3778
+			)
3779
+		);
3780
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3781
+			new EE_Question_Form_Input(
3782
+				EE_Question::new_instance(
3783
+					array(
3784
+						'QST_ID'           => 0,
3785
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3786
+						'QST_system'       => 'admin-country',
3787
+					)
3788
+				),
3789
+				EE_Answer::new_instance(
3790
+					array(
3791
+						'ANS_ID'    => 0,
3792
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3793
+					)
3794
+				),
3795
+				array(
3796
+					'input_id'       => 'CNT_ISO',
3797
+					'input_name'     => 'CNT_ISO',
3798
+					'input_prefix'   => '',
3799
+					'append_qstn_id' => false,
3800
+				)
3801
+			)
3802
+		);
3803
+		$template =
3804
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3805
+		EEH_Template::display_template($template, $this->_template_args);
3806
+	}
3807
+
3808
+
3809
+	/**
3810
+	 *        _attendee_details
3811
+	 *
3812
+	 * @access protected
3813
+	 * @param $post
3814
+	 * @return void
3815
+	 * @throws DomainException
3816
+	 * @throws EE_Error
3817
+	 */
3818
+	public function attendee_registrations_meta_box($post)
3819
+	{
3820
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3821
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3822
+		$template =
3823
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3824
+		EEH_Template::display_template($template, $this->_template_args);
3825
+	}
3826
+
3827
+
3828
+	/**
3829
+	 * add in the form fields for the attendee edit
3830
+	 *
3831
+	 * @param  WP_Post $post wp post object
3832
+	 * @return string html for new form.
3833
+	 * @throws DomainException
3834
+	 */
3835
+	public function after_title_form_fields($post)
3836
+	{
3837
+		if ($post->post_type == 'espresso_attendees') {
3838
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3839
+			$template_args['attendee'] = $this->_cpt_model_obj;
3840
+			EEH_Template::display_template($template, $template_args);
3841
+		}
3842
+	}
3843
+
3844
+
3845
+	/**
3846
+	 *        _trash_or_restore_attendee
3847
+	 *
3848
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3849
+	 * @return void
3850
+	 * @throws EE_Error
3851
+	 * @throws InvalidArgumentException
3852
+	 * @throws InvalidDataTypeException
3853
+	 * @throws InvalidInterfaceException
3854
+	 * @access protected
3855
+	 */
3856
+	protected function _trash_or_restore_attendees($trash = true)
3857
+	{
3858
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3859
+		$ATT_MDL = EEM_Attendee::instance();
3860
+		$success = 1;
3861
+		// Checkboxes
3862
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3863
+			// if array has more than one element than success message should be plural
3864
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3865
+			// cycle thru checkboxes
3866
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3867
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3868
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3869
+				if (! $updated) {
3870
+					$success = 0;
3871
+				}
3872
+			}
3873
+		} else {
3874
+			// grab single id and delete
3875
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3876
+			// get attendee
3877
+			$att = $ATT_MDL->get_one_by_ID($ATT_ID);
3878
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3879
+			$updated = $att->save();
3880
+			if (! $updated) {
3881
+				$success = 0;
3882
+			}
3883
+		}
3884
+		$what = $success > 1
3885
+			? esc_html__('Contacts', 'event_espresso')
3886
+			: esc_html__('Contact', 'event_espresso');
3887
+		$action_desc = $trash
3888
+			? esc_html__('moved to the trash', 'event_espresso')
3889
+			: esc_html__('restored', 'event_espresso');
3890
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3891
+	}
3892 3892
 }
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page.core.php 1 patch
Indentation   +695 added lines, -695 removed lines patch added patch discarded remove patch
@@ -15,646 +15,646 @@  discard block
 block discarded – undo
15 15
 class Registration_Form_Admin_Page extends EE_Admin_Page
16 16
 {
17 17
 
18
-    /**
19
-     * _question
20
-     * holds the specific question object for the question details screen
21
-     *
22
-     * @var EE_Question $_question
23
-     */
24
-    protected $_question;
25
-
26
-    /**
27
-     * _question_group
28
-     * holds the specific question group object for the question group details screen
29
-     *
30
-     * @var EE_Question_Group $_question_group
31
-     */
32
-    protected $_question_group;
33
-
34
-    /**
35
-     *_question_model EEM_Question model instance (for queries)
36
-     *
37
-     * @var EEM_Question $_question_model ;
38
-     */
39
-    protected $_question_model;
40
-
41
-    /**
42
-     * _question_group_model EEM_Question_group instance (for queries)
43
-     *
44
-     * @var EEM_Question_Group $_question_group_model
45
-     */
46
-    protected $_question_group_model;
47
-
48
-
49
-    /**
50
-     * @Constructor
51
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
52
-     * @access public
53
-     */
54
-    public function __construct($routing = true)
55
-    {
56
-        require_once(EE_MODELS . 'EEM_Question.model.php');
57
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
-        $this->_question_model = EEM_Question::instance();
59
-        $this->_question_group_model = EEM_Question_Group::instance();
60
-        parent::__construct($routing);
61
-    }
62
-
63
-
64
-    protected function _init_page_props()
65
-    {
66
-        $this->page_slug = REGISTRATION_FORM_PG_SLUG;
67
-        $this->page_label = esc_html__('Registration Form', 'event_espresso');
68
-        $this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL;
69
-        $this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
-    }
71
-
72
-
73
-    protected function _ajax_hooks()
74
-    {
75
-    }
76
-
77
-
78
-    protected function _define_page_props()
79
-    {
80
-        $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
-        $this->_labels = array(
82
-            'buttons' => array(
83
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
-            ),
85
-        );
86
-    }
87
-
88
-
89
-    /**
90
-     *_set_page_routes
91
-     */
92
-    protected function _set_page_routes()
93
-    {
94
-        $qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0;
95
-        $this->_page_routes = array(
96
-            'default' => array(
97
-                'func'       => '_questions_overview_list_table',
98
-                'capability' => 'ee_read_questions',
99
-            ),
100
-
101
-            'edit_question' => array(
102
-                'func'       => '_edit_question',
103
-                'capability' => 'ee_edit_question',
104
-                'obj_id'     => $qst_id,
105
-                'args'       => array('edit'),
106
-            ),
107
-
108
-            'question_groups' => array(
109
-                'func'       => '_questions_groups_preview',
110
-                'capability' => 'ee_read_question_groups',
111
-            ),
112
-
113
-            'update_question' => array(
114
-                'func'       => '_insert_or_update_question',
115
-                'args'       => array('new_question' => false),
116
-                'capability' => 'ee_edit_question',
117
-                'obj_id'     => $qst_id,
118
-                'noheader'   => true,
119
-            ),
120
-        );
121
-    }
122
-
123
-
124
-    protected function _set_page_config()
125
-    {
126
-        $this->_page_config = array(
127
-            'default' => array(
128
-                'nav'           => array(
129
-                    'label' => esc_html__('Questions', 'event_espresso'),
130
-                    'order' => 10,
131
-                ),
132
-                'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
133
-                'metaboxes'     => $this->_default_espresso_metaboxes,
134
-                'help_tabs'     => array(
135
-                    'registration_form_questions_overview_help_tab'                           => array(
136
-                        'title'    => esc_html__('Questions Overview', 'event_espresso'),
137
-                        'filename' => 'registration_form_questions_overview',
138
-                    ),
139
-                    'registration_form_questions_overview_table_column_headings_help_tab'     => array(
140
-                        'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
141
-                        'filename' => 'registration_form_questions_overview_table_column_headings',
142
-                    ),
143
-                    'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array(
144
-                        'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
145
-                        'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
146
-                    ),
147
-                ),
148
-                'help_tour'     => array('Registration_Form_Questions_Overview_Help_Tour'),
149
-                'require_nonce' => false,
150
-                'qtips'         => array(
151
-                    'EE_Registration_Form_Tips',
152
-                )/**/
153
-            ),
154
-
155
-            'question_groups' => array(
156
-                'nav'           => array(
157
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
158
-                    'order' => 20,
159
-                ),
160
-                'metaboxes'     => $this->_default_espresso_metaboxes,
161
-                'help_tabs'     => array(
162
-                    'registration_form_question_groups_help_tab' => array(
163
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
164
-                        'filename' => 'registration_form_question_groups',
165
-                    ),
166
-                ),
167
-                'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
168
-                'require_nonce' => false,
169
-            ),
170
-
171
-            'edit_question' => array(
172
-                'nav'           => array(
173
-                    'label'      => esc_html__('Edit Question', 'event_espresso'),
174
-                    'order'      => 15,
175
-                    'persistent' => false,
176
-                    'url'        => isset($this->_req_data['question_id']) ? add_query_arg(
177
-                        array('question_id' => $this->_req_data['question_id']),
178
-                        $this->_current_page_view_url
179
-                    ) : $this->_admin_base_url,
180
-                ),
181
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
182
-                'help_tabs'     => array(
183
-                    'registration_form_edit_question_group_help_tab' => array(
184
-                        'title'    => esc_html__('Edit Question', 'event_espresso'),
185
-                        'filename' => 'registration_form_edit_question',
186
-                    ),
187
-                ),
188
-                'help_tour'     => array('Registration_Form_Edit_Question_Help_Tour'),
189
-                'require_nonce' => false,
190
-            ),
191
-        );
192
-    }
193
-
194
-
195
-    protected function _add_screen_options()
196
-    {
197
-        // todo
198
-    }
199
-
200
-    protected function _add_screen_options_default()
201
-    {
202
-        $page_title = $this->_admin_page_title;
203
-        $this->_admin_page_title = esc_html__('Questions', 'event_espresso');
204
-        $this->_per_page_screen_option();
205
-        $this->_admin_page_title = $page_title;
206
-    }
207
-
208
-    protected function _add_screen_options_question_groups()
209
-    {
210
-        $page_title = $this->_admin_page_title;
211
-        $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
212
-        $this->_per_page_screen_option();
213
-        $this->_admin_page_title = $page_title;
214
-    }
215
-
216
-    // none of the below group are currently used for Event Categories
217
-    protected function _add_feature_pointers()
218
-    {
219
-    }
220
-
221
-    public function load_scripts_styles()
222
-    {
223
-        wp_register_style(
224
-            'espresso_registration',
225
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
226
-            array(),
227
-            EVENT_ESPRESSO_VERSION
228
-        );
229
-        wp_enqueue_style('espresso_registration');
230
-    }
231
-
232
-    public function admin_init()
233
-    {
234
-    }
235
-
236
-    public function admin_notices()
237
-    {
238
-    }
239
-
240
-    public function admin_footer_scripts()
241
-    {
242
-    }
243
-
244
-
245
-    public function load_scripts_styles_default()
246
-    {
247
-    }
248
-
249
-
250
-    public function load_scripts_styles_add_question()
251
-    {
252
-        $this->load_scripts_styles_question_details();
253
-    }
254
-
255
-    public function load_scripts_styles_edit_question()
256
-    {
257
-        $this->load_scripts_styles_question_details();
258
-    }
259
-
260
-    /**
261
-     * Loads the JS required for adding or editing a question
262
-     */
263
-    protected function load_scripts_styles_question_details()
264
-    {
265
-        $this->load_scripts_styles_forms();
266
-        wp_register_script(
267
-            'espresso_registration_form_single',
268
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
269
-            array('jquery-ui-sortable'),
270
-            EVENT_ESPRESSO_VERSION,
271
-            true
272
-        );
273
-        wp_enqueue_script('espresso_registration_form_single');
274
-        wp_localize_script(
275
-            'espresso_registration_form_single',
276
-            'ee_question_data',
277
-            array(
278
-                'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
279
-                'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
280
-            )
281
-        );
282
-    }
283
-
284
-
285
-    public function recaptcha_info_help_tab()
286
-    {
287
-        $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
288
-        EEH_Template::display_template($template, array());
289
-    }
290
-
291
-
292
-    public function load_scripts_styles_forms()
293
-    {
294
-        // styles
295
-        wp_enqueue_style('espresso-ui-theme');
296
-        // scripts
297
-        wp_enqueue_script('ee_admin_js');
298
-    }
299
-
300
-
301
-    protected function _set_list_table_views_default()
302
-    {
303
-        $this->_views = array(
304
-            'all' => array(
305
-                'slug'  => 'all',
306
-                'label' => esc_html__('View All Questions', 'event_espresso'),
307
-                'count' => 0,
308
-            ),
309
-        );
310
-
311
-        if (EE_Registry::instance()->CAP->current_user_can(
312
-            'ee_delete_questions',
313
-            'espresso_registration_form_trash_questions'
314
-        )
315
-        ) {
316
-            $this->_views['trash'] = array(
317
-                'slug'  => 'trash',
318
-                'label' => esc_html__('Trash', 'event_espresso'),
319
-                'count' => 0,
320
-            );
321
-        }
322
-    }
323
-
324
-    /**
325
-     * This just previews the question groups tab that comes in caffeinated.
326
-     *
327
-     * @return string html
328
-     */
329
-    protected function _questions_groups_preview()
330
-    {
331
-        $this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso');
332
-        $this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
333
-                                               . esc_attr__(
334
-                                                   'Preview Question Groups Overview List Table screenshot',
335
-                                                   'event_espresso'
336
-                                               ) . '" />';
337
-        $this->_template_args['preview_text'] = '<strong>'
338
-                                                . esc_html__(
339
-                                                    'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
340
-                                                    'event_espresso'
341
-                                                ) . '</strong>';
342
-        $this->display_admin_caf_preview_page('question_groups_tab');
343
-    }
344
-
345
-
346
-    /**
347
-     * Extracts the question field's values from the POST request to update or insert them
348
-     *
349
-     * @param \EEM_Base $model
350
-     * @return array where each key is the name of a model's field/db column, and each value is its value.
351
-     */
352
-    protected function _set_column_values_for(EEM_Base $model)
353
-    {
354
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
355
-        $set_column_values = array();
356
-
357
-        // some initial checks for proper values.
358
-        // if QST_admin_only, then no matter what QST_required is we disable.
359
-        if (! empty($this->_req_data['QST_admin_only'])) {
360
-            $this->_req_data['QST_required'] = 0;
361
-        }
362
-        // if the question shouldn't have a max length, don't let them set one
363
-        if (! isset(
364
-            $this->_req_data['QST_type'],
365
-            $this->_req_data['QST_max']
366
-        )
367
-            || ! in_array(
368
-                $this->_req_data['QST_type'],
369
-                EEM_Question::instance()->questionTypesWithMaxLength(),
370
-                true
371
-            )
372
-        ) {
373
-            // they're not allowed to set the max
374
-            $this->_req_data['QST_max'] = null;
375
-        }
376
-        foreach ($model->field_settings() as $fieldName => $settings) {
377
-            // basically if QSG_identifier is empty or not set
378
-            if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) {
379
-                $QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : '';
380
-                $set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
381
-            } //if the admin label is blank, use a slug version of the question text
382
-            elseif ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) {
383
-                $QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : '';
384
-                $set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
385
-            } elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
386
-                $set_column_values[ $fieldName ] = 0;
387
-            } elseif ($fieldName === 'QST_max') {
388
-                $qst_system = EEM_Question::instance()->get_var(
389
-                    array(
390
-                        array(
391
-                            'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0,
392
-                        ),
393
-                    ),
394
-                    'QST_system'
395
-                );
396
-                $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system);
397
-                if (empty($this->_req_data['QST_max']) ||
398
-                    $this->_req_data['QST_max'] > $max_max
399
-                ) {
400
-                    $set_column_values[ $fieldName ] = $max_max;
401
-                }
402
-            }
403
-
404
-
405
-            // only add a property to the array if it's not null (otherwise the model should just use the default value)
406
-            if (! isset($set_column_values[ $fieldName ]) &&
407
-                isset($this->_req_data[ $fieldName ])
408
-            ) {
409
-                $set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
410
-            }
411
-        }
412
-        return $set_column_values;// validation fo this data to be performed by the model before insertion.
413
-    }
414
-
415
-
416
-    /**
417
-     *_questions_overview_list_table
418
-     */
419
-    protected function _questions_overview_list_table()
420
-    {
421
-        $this->_search_btn_label = esc_html__('Questions', 'event_espresso');
422
-        $this->display_admin_list_table_page_with_sidebar();
423
-    }
424
-
425
-
426
-    /**
427
-     * _edit_question
428
-     */
429
-    protected function _edit_question()
430
-    {
431
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
432
-        $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint(
433
-            $this->_req_data['QST_ID']
434
-        ) : false;
435
-
436
-        switch ($this->_req_action) {
437
-            case 'add_question':
438
-                $this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
439
-                break;
440
-            case 'edit_question':
441
-                $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
442
-                break;
443
-            default:
444
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
445
-        }
446
-
447
-        // add PRC_ID to title if editing
448
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
449
-        if ($ID) {
450
-            $question = $this->_question_model->get_one_by_ID($ID);
451
-            $additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID));
452
-            $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
453
-        } else {
454
-            $question = EE_Question::new_instance();
455
-            $question->set_order_to_latest();
456
-            $this->_set_add_edit_form_tags('insert_question');
457
-        }
458
-        if ($question->system_ID() === EEM_Attendee::system_question_phone) {
459
-            $question_types = array_intersect_key(
460
-                EEM_Question::instance()->allowed_question_types(),
461
-                array_flip(
462
-                    array(
463
-                        EEM_Question::QST_type_text,
464
-                        EEM_Question::QST_type_us_phone,
465
-                    )
466
-                )
467
-            );
468
-        } else {
469
-            $question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category(
470
-                $question->type()
471
-            ) : $this->_question_model->allowed_question_types();
472
-        }
473
-        $this->_template_args['QST_ID'] = $ID;
474
-        $this->_template_args['question'] = $question;
475
-        $this->_template_args['question_types'] = $question_types;
476
-        $this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question(
477
-            $question->system_ID()
478
-        );
479
-        $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
480
-        $this->_set_publish_post_box_vars('id', $ID);
481
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
482
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
483
-            $this->_template_args,
484
-            true
485
-        );
486
-
487
-        // the details template wrapper
488
-        $this->display_admin_page_with_sidebar();
489
-    }
490
-
491
-
492
-    /**
493
-     * @return string
494
-     */
495
-    protected function _get_question_type_descriptions()
496
-    {
497
-        EE_Registry::instance()->load_helper('HTML');
498
-        $descriptions = '';
499
-        $question_type_descriptions = EEM_Question::instance()->question_descriptions();
500
-        foreach ($question_type_descriptions as $type => $question_type_description) {
501
-            if ($type == 'HTML_TEXTAREA') {
502
-                $html = new EE_Simple_HTML_Validation_Strategy();
503
-                $question_type_description .= sprintf(
504
-                    esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
505
-                    '<br/>',
506
-                    $html->get_list_of_allowed_tags()
507
-                );
508
-            }
509
-            $descriptions .= EEH_HTML::p(
510
-                $question_type_description,
511
-                'question_type_description-' . $type,
512
-                'question_type_description description',
513
-                'display:none;'
514
-            );
515
-        }
516
-        return $descriptions;
517
-    }
518
-
519
-
520
-    /**
521
-     * @param bool|true $new_question
522
-     * @throws \EE_Error
523
-     */
524
-    protected function _insert_or_update_question($new_question = true)
525
-    {
526
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
527
-        $set_column_values = $this->_set_column_values_for($this->_question_model);
528
-        if ($new_question) {
529
-            $question = EE_Question::new_instance($set_column_values);
530
-            $action_desc = 'added';
531
-        } else {
532
-            $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
533
-            foreach ($set_column_values as $field => $new_value) {
534
-                $question->set($field, $new_value);
535
-            }
536
-            $action_desc = 'updated';
537
-        }
538
-        $success = $question->save();
539
-        $ID = $question->ID();
540
-        if ($ID && $question->should_have_question_options()) {
541
-            // save the related options
542
-            // trash removed options, save old ones
543
-            // get list of all options
544
-            $options = $question->options();
545
-            if (! empty($options)) {
546
-                foreach ($options as $option_ID => $option) {
547
-                    $option_req_index = $this->_get_option_req_data_index($option_ID);
548
-                    if ($option_req_index !== false) {
549
-                        $option->save($this->_req_data['question_options'][ $option_req_index ]);
550
-                    } else {
551
-                        // not found, remove it
552
-                        $option->delete();
553
-                    }
554
-                }
555
-            }
556
-            // save new related options
557
-            foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
558
-                // skip $index that is from our sample
559
-                if ($index === 'xxcountxx') {
560
-                    continue;
561
-                }
562
-                // note we allow saving blank options.
563
-                if (empty($option_req_data['QSO_ID'])
564
-                ) {// no ID! save it!
565
-                    $new_option = EE_Question_Option::new_instance(
566
-                        array(
567
-                            'QSO_value' => $option_req_data['QSO_value'],
568
-                            'QSO_desc'  => $option_req_data['QSO_desc'],
569
-                            'QSO_order' => $option_req_data['QSO_order'],
570
-                            'QST_ID'    => $question->ID(),
571
-                        )
572
-                    );
573
-                    $new_option->save();
574
-                }
575
-            }
576
-        }
577
-        $query_args = array('action' => 'edit_question', 'QST_ID' => $ID);
578
-        if ($success !== false) {
579
-            $msg = $new_question
580
-                ? sprintf(
581
-                    esc_html__('The %s has been created', 'event_espresso'),
582
-                    $this->_question_model->item_name()
583
-                )
584
-                : sprintf(
585
-                    esc_html__('The %s has been updated', 'event_espresso'),
586
-                    $this->_question_model->item_name()
587
-                );
588
-            EE_Error::add_success($msg);
589
-        }
590
-
591
-        $this->_redirect_after_action(false, '', $action_desc, $query_args, true);
592
-    }
593
-
594
-
595
-    /**
596
-     * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
597
-     * by ID
598
-     * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
599
-     * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
600
-     *
601
-     * @param int $ID of the question option to find
602
-     * @return int index in question_options array if successful, FALSE if unsuccessful
603
-     */
604
-    protected function _get_option_req_data_index($ID)
605
-    {
606
-        $req_data_for_question_options = $this->_req_data['question_options'];
607
-        foreach ($req_data_for_question_options as $num => $option_data) {
608
-            if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
609
-                return $num;
610
-            }
611
-        }
612
-        return false;
613
-    }
614
-
615
-
616
-
617
-
618
-    /***********/
619
-    /* QUERIES */
620
-    /**
621
-     * For internal use in getting all the query parameters
622
-     * (because it's pretty well the same between question, question groups,
623
-     * and for both when searching for trashed and untrashed ones)
624
-     *
625
-     * @param EEM_Base $model either EEM_Question or EEM_Question_Group
626
-     * @param int      $per_page
627
-     * @param int      $current_page
628
-     * @return array model query params, @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
629
-     */
630
-    protected function get_query_params($model, $per_page = 10, $current_page = 10)
631
-    {
632
-        $query_params = array();
633
-        $offset = ($current_page - 1) * $per_page;
634
-        $query_params['limit'] = array($offset, $per_page);
635
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
636
-            : 'ASC';
637
-        $orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
638
-        $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
639
-        $query_params['order_by'] = array($field_to_order_by => $order);
640
-        $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
641
-        if (! empty($search_string)) {
642
-            if ($model instanceof EEM_Question_Group) {
643
-                $query_params[0] = array(
644
-                    'OR' => array(
645
-                        'QSG_name' => array('LIKE', "%$search_string%"),
646
-                        'QSG_desc' => array('LIKE', "%$search_string%"),
647
-                    ),
648
-                );
649
-            } else {
650
-                $query_params[0] = array(
651
-                    'QST_display_text' => array('LIKE', "%$search_string%"),
652
-                );
653
-            }
654
-        }
655
-
656
-        // capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
657
-        /*if ( $model instanceof EEM_Question_Group ) {
18
+	/**
19
+	 * _question
20
+	 * holds the specific question object for the question details screen
21
+	 *
22
+	 * @var EE_Question $_question
23
+	 */
24
+	protected $_question;
25
+
26
+	/**
27
+	 * _question_group
28
+	 * holds the specific question group object for the question group details screen
29
+	 *
30
+	 * @var EE_Question_Group $_question_group
31
+	 */
32
+	protected $_question_group;
33
+
34
+	/**
35
+	 *_question_model EEM_Question model instance (for queries)
36
+	 *
37
+	 * @var EEM_Question $_question_model ;
38
+	 */
39
+	protected $_question_model;
40
+
41
+	/**
42
+	 * _question_group_model EEM_Question_group instance (for queries)
43
+	 *
44
+	 * @var EEM_Question_Group $_question_group_model
45
+	 */
46
+	protected $_question_group_model;
47
+
48
+
49
+	/**
50
+	 * @Constructor
51
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
52
+	 * @access public
53
+	 */
54
+	public function __construct($routing = true)
55
+	{
56
+		require_once(EE_MODELS . 'EEM_Question.model.php');
57
+		require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
+		$this->_question_model = EEM_Question::instance();
59
+		$this->_question_group_model = EEM_Question_Group::instance();
60
+		parent::__construct($routing);
61
+	}
62
+
63
+
64
+	protected function _init_page_props()
65
+	{
66
+		$this->page_slug = REGISTRATION_FORM_PG_SLUG;
67
+		$this->page_label = esc_html__('Registration Form', 'event_espresso');
68
+		$this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL;
69
+		$this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
+	}
71
+
72
+
73
+	protected function _ajax_hooks()
74
+	{
75
+	}
76
+
77
+
78
+	protected function _define_page_props()
79
+	{
80
+		$this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
+		$this->_labels = array(
82
+			'buttons' => array(
83
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
+			),
85
+		);
86
+	}
87
+
88
+
89
+	/**
90
+	 *_set_page_routes
91
+	 */
92
+	protected function _set_page_routes()
93
+	{
94
+		$qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0;
95
+		$this->_page_routes = array(
96
+			'default' => array(
97
+				'func'       => '_questions_overview_list_table',
98
+				'capability' => 'ee_read_questions',
99
+			),
100
+
101
+			'edit_question' => array(
102
+				'func'       => '_edit_question',
103
+				'capability' => 'ee_edit_question',
104
+				'obj_id'     => $qst_id,
105
+				'args'       => array('edit'),
106
+			),
107
+
108
+			'question_groups' => array(
109
+				'func'       => '_questions_groups_preview',
110
+				'capability' => 'ee_read_question_groups',
111
+			),
112
+
113
+			'update_question' => array(
114
+				'func'       => '_insert_or_update_question',
115
+				'args'       => array('new_question' => false),
116
+				'capability' => 'ee_edit_question',
117
+				'obj_id'     => $qst_id,
118
+				'noheader'   => true,
119
+			),
120
+		);
121
+	}
122
+
123
+
124
+	protected function _set_page_config()
125
+	{
126
+		$this->_page_config = array(
127
+			'default' => array(
128
+				'nav'           => array(
129
+					'label' => esc_html__('Questions', 'event_espresso'),
130
+					'order' => 10,
131
+				),
132
+				'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
133
+				'metaboxes'     => $this->_default_espresso_metaboxes,
134
+				'help_tabs'     => array(
135
+					'registration_form_questions_overview_help_tab'                           => array(
136
+						'title'    => esc_html__('Questions Overview', 'event_espresso'),
137
+						'filename' => 'registration_form_questions_overview',
138
+					),
139
+					'registration_form_questions_overview_table_column_headings_help_tab'     => array(
140
+						'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
141
+						'filename' => 'registration_form_questions_overview_table_column_headings',
142
+					),
143
+					'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array(
144
+						'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
145
+						'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
146
+					),
147
+				),
148
+				'help_tour'     => array('Registration_Form_Questions_Overview_Help_Tour'),
149
+				'require_nonce' => false,
150
+				'qtips'         => array(
151
+					'EE_Registration_Form_Tips',
152
+				)/**/
153
+			),
154
+
155
+			'question_groups' => array(
156
+				'nav'           => array(
157
+					'label' => esc_html__('Question Groups', 'event_espresso'),
158
+					'order' => 20,
159
+				),
160
+				'metaboxes'     => $this->_default_espresso_metaboxes,
161
+				'help_tabs'     => array(
162
+					'registration_form_question_groups_help_tab' => array(
163
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
164
+						'filename' => 'registration_form_question_groups',
165
+					),
166
+				),
167
+				'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
168
+				'require_nonce' => false,
169
+			),
170
+
171
+			'edit_question' => array(
172
+				'nav'           => array(
173
+					'label'      => esc_html__('Edit Question', 'event_espresso'),
174
+					'order'      => 15,
175
+					'persistent' => false,
176
+					'url'        => isset($this->_req_data['question_id']) ? add_query_arg(
177
+						array('question_id' => $this->_req_data['question_id']),
178
+						$this->_current_page_view_url
179
+					) : $this->_admin_base_url,
180
+				),
181
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
182
+				'help_tabs'     => array(
183
+					'registration_form_edit_question_group_help_tab' => array(
184
+						'title'    => esc_html__('Edit Question', 'event_espresso'),
185
+						'filename' => 'registration_form_edit_question',
186
+					),
187
+				),
188
+				'help_tour'     => array('Registration_Form_Edit_Question_Help_Tour'),
189
+				'require_nonce' => false,
190
+			),
191
+		);
192
+	}
193
+
194
+
195
+	protected function _add_screen_options()
196
+	{
197
+		// todo
198
+	}
199
+
200
+	protected function _add_screen_options_default()
201
+	{
202
+		$page_title = $this->_admin_page_title;
203
+		$this->_admin_page_title = esc_html__('Questions', 'event_espresso');
204
+		$this->_per_page_screen_option();
205
+		$this->_admin_page_title = $page_title;
206
+	}
207
+
208
+	protected function _add_screen_options_question_groups()
209
+	{
210
+		$page_title = $this->_admin_page_title;
211
+		$this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
212
+		$this->_per_page_screen_option();
213
+		$this->_admin_page_title = $page_title;
214
+	}
215
+
216
+	// none of the below group are currently used for Event Categories
217
+	protected function _add_feature_pointers()
218
+	{
219
+	}
220
+
221
+	public function load_scripts_styles()
222
+	{
223
+		wp_register_style(
224
+			'espresso_registration',
225
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
226
+			array(),
227
+			EVENT_ESPRESSO_VERSION
228
+		);
229
+		wp_enqueue_style('espresso_registration');
230
+	}
231
+
232
+	public function admin_init()
233
+	{
234
+	}
235
+
236
+	public function admin_notices()
237
+	{
238
+	}
239
+
240
+	public function admin_footer_scripts()
241
+	{
242
+	}
243
+
244
+
245
+	public function load_scripts_styles_default()
246
+	{
247
+	}
248
+
249
+
250
+	public function load_scripts_styles_add_question()
251
+	{
252
+		$this->load_scripts_styles_question_details();
253
+	}
254
+
255
+	public function load_scripts_styles_edit_question()
256
+	{
257
+		$this->load_scripts_styles_question_details();
258
+	}
259
+
260
+	/**
261
+	 * Loads the JS required for adding or editing a question
262
+	 */
263
+	protected function load_scripts_styles_question_details()
264
+	{
265
+		$this->load_scripts_styles_forms();
266
+		wp_register_script(
267
+			'espresso_registration_form_single',
268
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
269
+			array('jquery-ui-sortable'),
270
+			EVENT_ESPRESSO_VERSION,
271
+			true
272
+		);
273
+		wp_enqueue_script('espresso_registration_form_single');
274
+		wp_localize_script(
275
+			'espresso_registration_form_single',
276
+			'ee_question_data',
277
+			array(
278
+				'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
279
+				'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
280
+			)
281
+		);
282
+	}
283
+
284
+
285
+	public function recaptcha_info_help_tab()
286
+	{
287
+		$template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
288
+		EEH_Template::display_template($template, array());
289
+	}
290
+
291
+
292
+	public function load_scripts_styles_forms()
293
+	{
294
+		// styles
295
+		wp_enqueue_style('espresso-ui-theme');
296
+		// scripts
297
+		wp_enqueue_script('ee_admin_js');
298
+	}
299
+
300
+
301
+	protected function _set_list_table_views_default()
302
+	{
303
+		$this->_views = array(
304
+			'all' => array(
305
+				'slug'  => 'all',
306
+				'label' => esc_html__('View All Questions', 'event_espresso'),
307
+				'count' => 0,
308
+			),
309
+		);
310
+
311
+		if (EE_Registry::instance()->CAP->current_user_can(
312
+			'ee_delete_questions',
313
+			'espresso_registration_form_trash_questions'
314
+		)
315
+		) {
316
+			$this->_views['trash'] = array(
317
+				'slug'  => 'trash',
318
+				'label' => esc_html__('Trash', 'event_espresso'),
319
+				'count' => 0,
320
+			);
321
+		}
322
+	}
323
+
324
+	/**
325
+	 * This just previews the question groups tab that comes in caffeinated.
326
+	 *
327
+	 * @return string html
328
+	 */
329
+	protected function _questions_groups_preview()
330
+	{
331
+		$this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso');
332
+		$this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
333
+											   . esc_attr__(
334
+												   'Preview Question Groups Overview List Table screenshot',
335
+												   'event_espresso'
336
+											   ) . '" />';
337
+		$this->_template_args['preview_text'] = '<strong>'
338
+												. esc_html__(
339
+													'Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
340
+													'event_espresso'
341
+												) . '</strong>';
342
+		$this->display_admin_caf_preview_page('question_groups_tab');
343
+	}
344
+
345
+
346
+	/**
347
+	 * Extracts the question field's values from the POST request to update or insert them
348
+	 *
349
+	 * @param \EEM_Base $model
350
+	 * @return array where each key is the name of a model's field/db column, and each value is its value.
351
+	 */
352
+	protected function _set_column_values_for(EEM_Base $model)
353
+	{
354
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
355
+		$set_column_values = array();
356
+
357
+		// some initial checks for proper values.
358
+		// if QST_admin_only, then no matter what QST_required is we disable.
359
+		if (! empty($this->_req_data['QST_admin_only'])) {
360
+			$this->_req_data['QST_required'] = 0;
361
+		}
362
+		// if the question shouldn't have a max length, don't let them set one
363
+		if (! isset(
364
+			$this->_req_data['QST_type'],
365
+			$this->_req_data['QST_max']
366
+		)
367
+			|| ! in_array(
368
+				$this->_req_data['QST_type'],
369
+				EEM_Question::instance()->questionTypesWithMaxLength(),
370
+				true
371
+			)
372
+		) {
373
+			// they're not allowed to set the max
374
+			$this->_req_data['QST_max'] = null;
375
+		}
376
+		foreach ($model->field_settings() as $fieldName => $settings) {
377
+			// basically if QSG_identifier is empty or not set
378
+			if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) {
379
+				$QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : '';
380
+				$set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
381
+			} //if the admin label is blank, use a slug version of the question text
382
+			elseif ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) {
383
+				$QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : '';
384
+				$set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
385
+			} elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
386
+				$set_column_values[ $fieldName ] = 0;
387
+			} elseif ($fieldName === 'QST_max') {
388
+				$qst_system = EEM_Question::instance()->get_var(
389
+					array(
390
+						array(
391
+							'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0,
392
+						),
393
+					),
394
+					'QST_system'
395
+				);
396
+				$max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system);
397
+				if (empty($this->_req_data['QST_max']) ||
398
+					$this->_req_data['QST_max'] > $max_max
399
+				) {
400
+					$set_column_values[ $fieldName ] = $max_max;
401
+				}
402
+			}
403
+
404
+
405
+			// only add a property to the array if it's not null (otherwise the model should just use the default value)
406
+			if (! isset($set_column_values[ $fieldName ]) &&
407
+				isset($this->_req_data[ $fieldName ])
408
+			) {
409
+				$set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
410
+			}
411
+		}
412
+		return $set_column_values;// validation fo this data to be performed by the model before insertion.
413
+	}
414
+
415
+
416
+	/**
417
+	 *_questions_overview_list_table
418
+	 */
419
+	protected function _questions_overview_list_table()
420
+	{
421
+		$this->_search_btn_label = esc_html__('Questions', 'event_espresso');
422
+		$this->display_admin_list_table_page_with_sidebar();
423
+	}
424
+
425
+
426
+	/**
427
+	 * _edit_question
428
+	 */
429
+	protected function _edit_question()
430
+	{
431
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
432
+		$ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint(
433
+			$this->_req_data['QST_ID']
434
+		) : false;
435
+
436
+		switch ($this->_req_action) {
437
+			case 'add_question':
438
+				$this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
439
+				break;
440
+			case 'edit_question':
441
+				$this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
442
+				break;
443
+			default:
444
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
445
+		}
446
+
447
+		// add PRC_ID to title if editing
448
+		$this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
449
+		if ($ID) {
450
+			$question = $this->_question_model->get_one_by_ID($ID);
451
+			$additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID));
452
+			$this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
453
+		} else {
454
+			$question = EE_Question::new_instance();
455
+			$question->set_order_to_latest();
456
+			$this->_set_add_edit_form_tags('insert_question');
457
+		}
458
+		if ($question->system_ID() === EEM_Attendee::system_question_phone) {
459
+			$question_types = array_intersect_key(
460
+				EEM_Question::instance()->allowed_question_types(),
461
+				array_flip(
462
+					array(
463
+						EEM_Question::QST_type_text,
464
+						EEM_Question::QST_type_us_phone,
465
+					)
466
+				)
467
+			);
468
+		} else {
469
+			$question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category(
470
+				$question->type()
471
+			) : $this->_question_model->allowed_question_types();
472
+		}
473
+		$this->_template_args['QST_ID'] = $ID;
474
+		$this->_template_args['question'] = $question;
475
+		$this->_template_args['question_types'] = $question_types;
476
+		$this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question(
477
+			$question->system_ID()
478
+		);
479
+		$this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
480
+		$this->_set_publish_post_box_vars('id', $ID);
481
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
482
+			REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
483
+			$this->_template_args,
484
+			true
485
+		);
486
+
487
+		// the details template wrapper
488
+		$this->display_admin_page_with_sidebar();
489
+	}
490
+
491
+
492
+	/**
493
+	 * @return string
494
+	 */
495
+	protected function _get_question_type_descriptions()
496
+	{
497
+		EE_Registry::instance()->load_helper('HTML');
498
+		$descriptions = '';
499
+		$question_type_descriptions = EEM_Question::instance()->question_descriptions();
500
+		foreach ($question_type_descriptions as $type => $question_type_description) {
501
+			if ($type == 'HTML_TEXTAREA') {
502
+				$html = new EE_Simple_HTML_Validation_Strategy();
503
+				$question_type_description .= sprintf(
504
+					esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
505
+					'<br/>',
506
+					$html->get_list_of_allowed_tags()
507
+				);
508
+			}
509
+			$descriptions .= EEH_HTML::p(
510
+				$question_type_description,
511
+				'question_type_description-' . $type,
512
+				'question_type_description description',
513
+				'display:none;'
514
+			);
515
+		}
516
+		return $descriptions;
517
+	}
518
+
519
+
520
+	/**
521
+	 * @param bool|true $new_question
522
+	 * @throws \EE_Error
523
+	 */
524
+	protected function _insert_or_update_question($new_question = true)
525
+	{
526
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
527
+		$set_column_values = $this->_set_column_values_for($this->_question_model);
528
+		if ($new_question) {
529
+			$question = EE_Question::new_instance($set_column_values);
530
+			$action_desc = 'added';
531
+		} else {
532
+			$question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
533
+			foreach ($set_column_values as $field => $new_value) {
534
+				$question->set($field, $new_value);
535
+			}
536
+			$action_desc = 'updated';
537
+		}
538
+		$success = $question->save();
539
+		$ID = $question->ID();
540
+		if ($ID && $question->should_have_question_options()) {
541
+			// save the related options
542
+			// trash removed options, save old ones
543
+			// get list of all options
544
+			$options = $question->options();
545
+			if (! empty($options)) {
546
+				foreach ($options as $option_ID => $option) {
547
+					$option_req_index = $this->_get_option_req_data_index($option_ID);
548
+					if ($option_req_index !== false) {
549
+						$option->save($this->_req_data['question_options'][ $option_req_index ]);
550
+					} else {
551
+						// not found, remove it
552
+						$option->delete();
553
+					}
554
+				}
555
+			}
556
+			// save new related options
557
+			foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
558
+				// skip $index that is from our sample
559
+				if ($index === 'xxcountxx') {
560
+					continue;
561
+				}
562
+				// note we allow saving blank options.
563
+				if (empty($option_req_data['QSO_ID'])
564
+				) {// no ID! save it!
565
+					$new_option = EE_Question_Option::new_instance(
566
+						array(
567
+							'QSO_value' => $option_req_data['QSO_value'],
568
+							'QSO_desc'  => $option_req_data['QSO_desc'],
569
+							'QSO_order' => $option_req_data['QSO_order'],
570
+							'QST_ID'    => $question->ID(),
571
+						)
572
+					);
573
+					$new_option->save();
574
+				}
575
+			}
576
+		}
577
+		$query_args = array('action' => 'edit_question', 'QST_ID' => $ID);
578
+		if ($success !== false) {
579
+			$msg = $new_question
580
+				? sprintf(
581
+					esc_html__('The %s has been created', 'event_espresso'),
582
+					$this->_question_model->item_name()
583
+				)
584
+				: sprintf(
585
+					esc_html__('The %s has been updated', 'event_espresso'),
586
+					$this->_question_model->item_name()
587
+				);
588
+			EE_Error::add_success($msg);
589
+		}
590
+
591
+		$this->_redirect_after_action(false, '', $action_desc, $query_args, true);
592
+	}
593
+
594
+
595
+	/**
596
+	 * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
597
+	 * by ID
598
+	 * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
599
+	 * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
600
+	 *
601
+	 * @param int $ID of the question option to find
602
+	 * @return int index in question_options array if successful, FALSE if unsuccessful
603
+	 */
604
+	protected function _get_option_req_data_index($ID)
605
+	{
606
+		$req_data_for_question_options = $this->_req_data['question_options'];
607
+		foreach ($req_data_for_question_options as $num => $option_data) {
608
+			if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
609
+				return $num;
610
+			}
611
+		}
612
+		return false;
613
+	}
614
+
615
+
616
+
617
+
618
+	/***********/
619
+	/* QUERIES */
620
+	/**
621
+	 * For internal use in getting all the query parameters
622
+	 * (because it's pretty well the same between question, question groups,
623
+	 * and for both when searching for trashed and untrashed ones)
624
+	 *
625
+	 * @param EEM_Base $model either EEM_Question or EEM_Question_Group
626
+	 * @param int      $per_page
627
+	 * @param int      $current_page
628
+	 * @return array model query params, @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
629
+	 */
630
+	protected function get_query_params($model, $per_page = 10, $current_page = 10)
631
+	{
632
+		$query_params = array();
633
+		$offset = ($current_page - 1) * $per_page;
634
+		$query_params['limit'] = array($offset, $per_page);
635
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
636
+			: 'ASC';
637
+		$orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order';
638
+		$field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby'];
639
+		$query_params['order_by'] = array($field_to_order_by => $order);
640
+		$search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null;
641
+		if (! empty($search_string)) {
642
+			if ($model instanceof EEM_Question_Group) {
643
+				$query_params[0] = array(
644
+					'OR' => array(
645
+						'QSG_name' => array('LIKE', "%$search_string%"),
646
+						'QSG_desc' => array('LIKE', "%$search_string%"),
647
+					),
648
+				);
649
+			} else {
650
+				$query_params[0] = array(
651
+					'QST_display_text' => array('LIKE', "%$search_string%"),
652
+				);
653
+			}
654
+		}
655
+
656
+		// capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
657
+		/*if ( $model instanceof EEM_Question_Group ) {
658 658
             if ( ! EE_Registry::instance()->CAP->current_user_can( 'edit_others_question_groups', 'espresso_registration_form_edit_question_group' ) ) {
659 659
                 $query_params[0] = array(
660 660
                     'AND' => array(
@@ -684,59 +684,59 @@  discard block
 block discarded – undo
684 684
             }
685 685
         }/**/
686 686
 
687
-        return $query_params;
688
-    }
689
-
690
-
691
-    /**
692
-     * @param int        $per_page
693
-     * @param int        $current_page
694
-     * @param bool|false $count
695
-     * @return \EE_Soft_Delete_Base_Class[]|int
696
-     */
697
-    public function get_questions($per_page = 10, $current_page = 1, $count = false)
698
-    {
699
-        $QST = EEM_Question::instance();
700
-        $query_params = $this->get_query_params($QST, $per_page, $current_page);
701
-        if ($count) {
702
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
703
-            $results = $QST->count($where);
704
-        } else {
705
-            $results = $QST->get_all($query_params);
706
-        }
707
-        return $results;
708
-    }
709
-
710
-
711
-    /**
712
-     * @param            $per_page
713
-     * @param int        $current_page
714
-     * @param bool|false $count
715
-     * @return \EE_Soft_Delete_Base_Class[]|int
716
-     */
717
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
718
-    {
719
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
720
-        $where = isset($query_params[0]) ? array($query_params[0]) : array();
721
-        $questions = $count ? EEM_Question::instance()->count_deleted($where)
722
-            : EEM_Question::instance()->get_all_deleted($query_params);
723
-        return $questions;
724
-    }
725
-
726
-
727
-    /**
728
-     * @param            $per_page
729
-     * @param int        $current_page
730
-     * @param bool|false $count
731
-     * @return \EE_Soft_Delete_Base_Class[]
732
-     */
733
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
734
-    {
735
-        /** @type EEM_Question_Group $questionGroupModel */
736
-        $questionGroupModel = EEM_Question_Group::instance();
737
-        // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
738
-        return $questionGroupModel->get_all(
739
-            $this->get_query_params($questionGroupModel, $per_page, $current_page)
740
-        );
741
-    }
687
+		return $query_params;
688
+	}
689
+
690
+
691
+	/**
692
+	 * @param int        $per_page
693
+	 * @param int        $current_page
694
+	 * @param bool|false $count
695
+	 * @return \EE_Soft_Delete_Base_Class[]|int
696
+	 */
697
+	public function get_questions($per_page = 10, $current_page = 1, $count = false)
698
+	{
699
+		$QST = EEM_Question::instance();
700
+		$query_params = $this->get_query_params($QST, $per_page, $current_page);
701
+		if ($count) {
702
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
703
+			$results = $QST->count($where);
704
+		} else {
705
+			$results = $QST->get_all($query_params);
706
+		}
707
+		return $results;
708
+	}
709
+
710
+
711
+	/**
712
+	 * @param            $per_page
713
+	 * @param int        $current_page
714
+	 * @param bool|false $count
715
+	 * @return \EE_Soft_Delete_Base_Class[]|int
716
+	 */
717
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
718
+	{
719
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
720
+		$where = isset($query_params[0]) ? array($query_params[0]) : array();
721
+		$questions = $count ? EEM_Question::instance()->count_deleted($where)
722
+			: EEM_Question::instance()->get_all_deleted($query_params);
723
+		return $questions;
724
+	}
725
+
726
+
727
+	/**
728
+	 * @param            $per_page
729
+	 * @param int        $current_page
730
+	 * @param bool|false $count
731
+	 * @return \EE_Soft_Delete_Base_Class[]
732
+	 */
733
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
734
+	{
735
+		/** @type EEM_Question_Group $questionGroupModel */
736
+		$questionGroupModel = EEM_Question_Group::instance();
737
+		// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
738
+		return $questionGroupModel->get_all(
739
+			$this->get_query_params($questionGroupModel, $per_page, $current_page)
740
+		);
741
+	}
742 742
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Message_Template_Group.model.php 1 patch
Indentation   +422 added lines, -422 removed lines patch added patch discarded remove patch
@@ -11,426 +11,426 @@
 block discarded – undo
11 11
 class EEM_Message_Template_Group extends EEM_Soft_Delete_Base
12 12
 {
13 13
 
14
-    // private instance of the EEM_Message_Template_Group object
15
-    protected static $_instance = null;
16
-
17
-
18
-
19
-    protected function __construct($timezone = null)
20
-    {
21
-        $this->singular_item = __('Message Template Group', 'event_espresso');
22
-        $this->plural_item = __('Message Template Groups', 'event_espresso');
23
-        $this->_tables = array(
24
-            'Message_Template_Group' => new EE_Primary_Table('esp_message_template_group', 'GRP_ID')
25
-        );
26
-        $this->_fields = array(
27
-            'Message_Template_Group' => array(
28
-                'GRP_ID' => new EE_Primary_Key_Int_Field('GRP_ID', __('Message Template Group ID', 'event_espresso')),
29
-                'MTP_name' => new EE_Plain_Text_Field('MTP_name', __('The name of the template group', 'event_espresso'), false, ''),
30
-                'MTP_description' => new EE_Simple_HTML_Field('MTP_description', __('A brief description about this template.', 'event_espresso'), false, ''),
31
-                'MTP_user_id'=> new EE_WP_User_Field('MTP_user_id', __('Template Creator ID', 'event_espresso'), false, get_current_user_id()),
32
-                'MTP_messenger'=>new EE_Plain_Text_Field('MTP_messenger', __('Messenger Used for Template', 'event_espresso'), false, 'email'),
33
-                'MTP_message_type'=>new EE_Plain_Text_Field('MTP_message_type', __('Message Type', 'event_espresso'), false, 'registration'),
34
-                'MTP_is_global'=>new EE_Boolean_Field('MTP_is_global', __('Flag indicating if Template Group is Global', 'event_espresso'), false, true),
35
-                'MTP_is_override'=>new EE_Boolean_Field('MTP_is_override', __('Flag indicating if Template Group overrides any other Templates for the messenger/messagetype combination', 'event_espresso'), false, false),
36
-                'MTP_deleted'=>new EE_Trashed_Flag_Field('MTP_deleted', __('Flag indicating whether this has been trashed', 'event_espresso'), false, false),
37
-                'MTP_is_active'=>new EE_Boolean_Field('MTP_is_active', __('Flag indicating whether template group is active', 'event_espresso'), false, true)
38
-            )
39
-        );
40
-        $this->_model_relations = array(
41
-            'Message_Template' => new EE_Has_Many_Relation(),
42
-            'Message' => new EE_Has_Many_Relation(),
43
-            'Event' => new EE_HABTM_Relation('Event_Message_Template'),
44
-            'WP_User' => new EE_Belongs_To_Relation()
45
-        );
46
-        foreach ($this->_cap_contexts_to_cap_action_map as $context => $action) {
47
-            $this->_cap_restriction_generators[ $context ] = new EE_Restriction_Generator_Global('MTP_is_global');
48
-        }
49
-        $this->_caps_slug = 'messages';
50
-
51
-        parent::__construct($timezone);
52
-    }
53
-
54
-
55
-
56
-    /**
57
-     * get_all_trashed_message_templates_by_event
58
-     *
59
-     * @access public
60
-     * @param int    $EVT_ID specific event id
61
-     * @param string $orderby
62
-     * @param string $order
63
-     * @param null   $limit
64
-     * @param bool   $count
65
-     * @return array message template objects that are attached to a specific event.
66
-     */
67
-    public function get_all_trashed_message_templates_by_event(
68
-        $EVT_ID,
69
-        $orderby = 'GRP_ID',
70
-        $order = 'ASC',
71
-        $limit = null,
72
-        $count = false
73
-    ) {
74
-        $query_params = array( array('Event.EVT_ID' => $EVT_ID), 'order_by' => array($orderby => $order), 'limit' => $limit );
75
-        return $count ? $this->count_deleted($query_params, 'GRP_ID', true) : $this->get_all_deleted($query_params);
76
-    }
77
-
78
-
79
-
80
-    /**
81
-     * get_all_message_templates_by_messenger
82
-     *
83
-     * @access public
84
-     * @param        $messenger
85
-     * @param string $orderby
86
-     * @param string $order
87
-     * @return array all (including trashed or inactive) message template group objects for the given messenger
88
-     */
89
-    public function get_all_message_templates_by_messenger($messenger, $orderby = 'GRP_ID', $order = 'ASC')
90
-    {
91
-        return $this->get_all_deleted_and_undeleted(
92
-            array( array( 'MTP_messenger' => $messenger ), 'order_by' => array( $orderby => $order ) )
93
-        );
94
-    }
95
-
96
-
97
-
98
-    /**
99
-     * This simply adds on any messenger/message type filters that may be present in the $_POST global
100
-     * @param  array  $_where any existing where conditions to append these to.
101
-     * @return array          original where conditions or original with additional filters.
102
-     */
103
-    protected function _maybe_mtp_filters($_where = array())
104
-    {
105
-        // account for messenger or message type filters
106
-        if (isset($_REQUEST['ee_messenger_filter_by'])
107
-            && $_REQUEST['ee_messenger_filter_by'] != 'none_selected'
108
-            && $_REQUEST['ee_messenger_filter_by'] != 'all'
109
-        ) {
110
-            $_where['MTP_messenger'] =  $_REQUEST['ee_messenger_filter_by'] ;
111
-        }
112
-
113
-        if (isset($_REQUEST['ee_message_type_filter_by'])
114
-            && $_REQUEST['ee_message_type_filter_by'] != 'none_selected'
115
-        ) {
116
-            $_where['MTP_message_type'] = $_REQUEST['ee_message_type_filter_by'];
117
-        }
118
-
119
-        return $_where;
120
-    }
121
-
122
-
123
-
124
-    /**
125
-     * get_all_active_message_templates groups
126
-     *
127
-     * @access public
128
-     * @param string $orderby
129
-     * @param string $order
130
-     * @param null   $limit
131
-     * @param bool   $count
132
-     * @param bool   $global
133
-     * @param bool   $user_check
134
-     * @return array all active (non_trashed, active) message template objects
135
-     */
136
-    public function get_all_active_message_templates(
137
-        $orderby = 'GRP_ID',
138
-        $order = 'ASC',
139
-        $limit = null,
140
-        $count = false,
141
-        $global = true,
142
-        $user_check = false
143
-    ) {
144
-        $_where = $global ? array('MTP_is_global' => true ) : array('MTP_is_global' => false );
145
-        $_where['MTP_is_active'] = true;
146
-        $_where = $this->_maybe_mtp_filters($_where);
147
-
148
-        if ($user_check
149
-            && ! $global
150
-            && ! EE_Registry::instance()->CAP->current_user_can(
151
-                'ee_read_others_messages',
152
-                'get_all_active_message_templates'
153
-            )
154
-        ) {
155
-            $_where['MTP_user_id'] = get_current_user_id();
156
-        }
157
-
158
-        $query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
159
-
160
-        return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
161
-    }
162
-
163
-
164
-
165
-    /**
166
-     *    retrieve ALL message_template groups from db regardless of wht
167
-     *
168
-     * @access    public
169
-     * @param string $orderby
170
-     * @param string $order
171
-     * @param null   $limit
172
-     * @param bool   $count
173
-     * @return mixed array on success, FALSE on fail
174
-     */
175
-    public function get_all_message_templates($orderby = 'GRP_ID', $order = 'ASC', $limit = null, $count = false)
176
-    {
177
-        $_where = $this->_maybe_mtp_filters();
178
-
179
-        $query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
180
-
181
-        $r_templates = $count
182
-            ? $this->count_deleted_and_undeleted($query_params, 'GRP_ID', true)
183
-            : $this->get_all_deleted_and_undeleted($query_params);
184
-
185
-        return $r_templates;
186
-    }
187
-
188
-
189
-
190
-
191
-    /**
192
-     * This gets all the custom templates attached to a specific event
193
-     * @param  int      $EVT_ID         event id
194
-     * @param  array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
195
-     * @return  EE_Message_Template_Group[]
196
-     */
197
-    public function get_all_custom_templates_by_event($EVT_ID, $query_params = array())
198
-    {
199
-        $where = array_merge($query_params, array( 'Event.EVT_ID' => $EVT_ID ));
200
-        return $this->get_all(
201
-            array( $where )
202
-        );
203
-    }
204
-
205
-
206
-
207
-    /**
208
-     * get_all_trashed_grouped_message_templates
209
-     * this returns ONLY the template groups where ALL contexts are trashed and none of the group are non-trashed
210
-     *
211
-     * @access public
212
-     * @param string $orderby
213
-     * @param string $order
214
-     * @param null   $limit
215
-     * @param bool   $count
216
-     * @param bool   $global
217
-     * @return \EE_Message_Template_Group[] message template groups.
218
-     */
219
-    public function get_all_trashed_grouped_message_templates(
220
-        $orderby = 'GRP_ID',
221
-        $order = 'ASC',
222
-        $limit = null,
223
-        $count = false,
224
-        $global = true
225
-    ) {
226
-        $_where = $global ? array('MTP_is_global' => true ) : array('MTP_is_global' => false );
227
-        $_where['MTP_is_active'] = true;
228
-        $_where = $this->_maybe_mtp_filters($_where);
229
-
230
-        $query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
231
-
232
-        return $count ? $this->count_deleted($query_params, 'GRP_ID', true) : $this->get_all_deleted($query_params);
233
-    }
234
-
235
-
236
-
237
-    /**
238
-     * this returns the message template group(s) for a given event, messenger, and message template
239
-     *
240
-     * @param  string             $messenger
241
-     * @param  string             $message_type
242
-     * @param                     $evt_id
243
-     * @param  string             $orderby pointless at this point but still included
244
-     * @param  string             $order
245
-     * @param  mixed (array|null) $limit   array($offset, $num)
246
-     * @param  bool               $count   true = just return count, false = objects
247
-     * @param  bool               $active  ignore "active" or not. (default only return active)
248
-     * @return \mixed[]) depending on $count.
249
-     */
250
-    public function get_event_message_templates_by_m_and_mt_and_evt(
251
-        $messenger,
252
-        $message_type,
253
-        $evt_id,
254
-        $orderby = 'GRP_ID',
255
-        $order = 'ASC',
256
-        $limit = null,
257
-        $count = false,
258
-        $active = true
259
-    ) {
260
-        $_where = array(
261
-            'MTP_messenger' => $messenger,
262
-            'MTP_message_type' => $message_type,
263
-            'Event.EVT_ID' => $evt_id,
264
-            'MTP_is_global' => true,
265
-            'MTP_is_active' => $active
266
-        );
267
-
268
-        $query_params = array( $_where, 'order_by' => array($orderby=>$order), 'limit' => $limit );
269
-
270
-        return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
271
-    }
272
-
273
-
274
-
275
-
276
-    /**
277
-     * get all GLOBAL message template groups for the given messenger and message type
278
-     *
279
-     * @param  string $messenger    slug for messenger
280
-     * @param  string $message_type slug for message type
281
-     * @param  string $orderby      what column to orderby
282
-     * @param  string $order        ASC or DESC
283
-     * @param  mixed (array|null) $limit array($offset, $num)
284
-     * @param  bool   $count        true = just return count, false = objects
285
-     * @param  bool   $active       ignore "active" or not. (default only return active) -
286
-     *                              'all' means return both inactive AND inactive.
287
-     * @return array               message template objects that are global (i.e. non-event)
288
-     */
289
-    public function get_global_message_template_by_m_and_mt(
290
-        $messenger,
291
-        $message_type,
292
-        $orderby = 'GRP_ID',
293
-        $order = 'ASC',
294
-        $limit = null,
295
-        $count = false,
296
-        $active = true
297
-    ) {
298
-        $_where = array(
299
-            'MTP_messenger' => $messenger,
300
-            'MTP_message_type' => $message_type,
301
-            'MTP_is_global' => true,
302
-        );
303
-
304
-        if ($active != 'all') {
305
-            $_where['MTP_is_active'] = $active;
306
-        }
307
-
308
-        $query_params = array( $_where, 'order_by' => array( $orderby => $order ), 'limit' => $limit );
309
-
310
-        return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
311
-    }
312
-
313
-
314
-
315
-
316
-    /**
317
-     * get all custom message template groups for the given messenger and message type
318
-     * @param  string $messenger    messenger
319
-     * @param  string $message_type messagetype
320
-     * @param  array  $query_params same as EEM_Base->get_all()
321
-     * @return EE_Message_Template_Group[]
322
-     */
323
-    public function get_custom_message_template_by_m_and_mt($messenger, $message_type, $query_params = array())
324
-    {
325
-        return $this->get_all(
326
-            array_merge(
327
-                $query_params,
328
-                array(
329
-                    array(
330
-                        'MTP_is_global'    => false,
331
-                        'MTP_messenger'    => $messenger,
332
-                        'MTP_message_type' => $message_type
333
-                    )
334
-                )
335
-            )
336
-        );
337
-    }
338
-
339
-
340
-
341
-    /**
342
-     * This sends things to the validator for the given messenger and message type.
343
-     *
344
-     * @param  array $fields the incoming fields to check.
345
-     *                       Note this array is in the formatted fields from the form fields setup.
346
-     *                       So we need to reformat this into an array of expected field refs by the validator.
347
-     *                       Note also that this is not only the fields for the Message Template Group
348
-     *                       but ALSO for Message Template.
349
-     * @param string $context      The context the fields were obtained from.
350
-     * @param string $messenger    The messenger we are validating
351
-     * @param string $message_type The message type we are validating.
352
-     * @return mixed If the fields all check out then we return true otherwise error messages are returned
353
-     *                       (indexed by field name);
354
-     * @throws \EE_Error
355
-     */
356
-    public function validate($fields, $context, $messenger, $message_type)
357
-    {
358
-
359
-        $assembled_fields = array();
360
-
361
-        // let's loop through all the fields and set them up in the right format
362
-        foreach ($fields as $index => $value) {
363
-            // first let's figure out if the value['content'] in the current index is an array.
364
-            //  If it is then this is special fields that are used in parsing special shortcodes (i.e. 'attendee_list').
365
-            if (is_array($value['content'])) {
366
-                $assembled_fields[ $value['name'] ] = $value['content']['main'];
367
-                // loop through the content and get the other fields.
368
-                foreach ($value['content'] as $name => $val) {
369
-                    if ($name == 'main') {
370
-                        continue;
371
-                    }
372
-                    $assembled_fields[ $name ] = $val;
373
-                }
374
-                continue;
375
-            }
376
-
377
-            // okay if we're here then this is just a straight field=>$value arrangement
378
-            $assembled_fields[ $value['name'] ] = $value['content'];
379
-        }
380
-
381
-        // now we've got the assembled_fields.
382
-        // We need to setup the string for the appropriate validator class and call that.
383
-        $m_ref = ucwords(str_replace('_', ' ', $messenger));
384
-        $m_ref = str_replace(' ', '_', $m_ref);
385
-        $mt_ref = ucwords(str_replace('_', ' ', $message_type));
386
-        $mt_ref = str_replace(' ', '_', $mt_ref);
387
-
388
-        $classname = 'EE_Messages_' . $m_ref . '_' . $mt_ref . '_Validator';
389
-
390
-        if (!class_exists($classname)) {
391
-            $msg[] = __('The Validator class was unable to load', 'event_espresso');
392
-            $msg[] = sprintf(
393
-                __(
394
-                    'The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class',
395
-                    'event_espresso'
396
-                ),
397
-                $classname
398
-            );
399
-            throw new EE_Error(implode('||', $msg));
400
-        }
401
-
402
-        $a = new ReflectionClass($classname);
403
-        $_VLD = $a->newInstance($assembled_fields, $context);
404
-        $result = $_VLD->validate();
405
-        return $result;
406
-    }
407
-
408
-
409
-
410
-    /**
411
-     * Updates all message template groups matching the incoming arguments to inactive status.
412
-     *
413
-     * @param array $messenger_names    The messenger slugs.
414
-     *                              If empty then all templates matching the message types are marked inactive.
415
-     *                              Otherwise only templates matching the messengers and message types.
416
-     * @param array $message_type_names     The message type slugs.
417
-     *                              If empty then all templates matching the messengers are marked inactive.
418
-     *                              Otherwise only templates matching the messengers and message types.
419
-     *
420
-     * @return int  count of updated records.
421
-     */
422
-    public function deactivate_message_template_groups_for($messenger_names = array(), $message_type_names = array())
423
-    {
424
-        $query_args = array();
425
-        if (empty($messenger_names) && empty($message_type_names)) {
426
-            return 0;
427
-        }
428
-        if (! empty($messenger_names)) {
429
-            $query_args[0]['MTP_messenger'] = array( 'IN', (array) $messenger_names );
430
-        }
431
-        if (! empty($message_type_names)) {
432
-            $query_args[0]['MTP_message_type'] = array( 'IN', (array) $message_type_names );
433
-        }
434
-        return $this->update(array( 'MTP_is_active' => false ), $query_args);
435
-    }
14
+	// private instance of the EEM_Message_Template_Group object
15
+	protected static $_instance = null;
16
+
17
+
18
+
19
+	protected function __construct($timezone = null)
20
+	{
21
+		$this->singular_item = __('Message Template Group', 'event_espresso');
22
+		$this->plural_item = __('Message Template Groups', 'event_espresso');
23
+		$this->_tables = array(
24
+			'Message_Template_Group' => new EE_Primary_Table('esp_message_template_group', 'GRP_ID')
25
+		);
26
+		$this->_fields = array(
27
+			'Message_Template_Group' => array(
28
+				'GRP_ID' => new EE_Primary_Key_Int_Field('GRP_ID', __('Message Template Group ID', 'event_espresso')),
29
+				'MTP_name' => new EE_Plain_Text_Field('MTP_name', __('The name of the template group', 'event_espresso'), false, ''),
30
+				'MTP_description' => new EE_Simple_HTML_Field('MTP_description', __('A brief description about this template.', 'event_espresso'), false, ''),
31
+				'MTP_user_id'=> new EE_WP_User_Field('MTP_user_id', __('Template Creator ID', 'event_espresso'), false, get_current_user_id()),
32
+				'MTP_messenger'=>new EE_Plain_Text_Field('MTP_messenger', __('Messenger Used for Template', 'event_espresso'), false, 'email'),
33
+				'MTP_message_type'=>new EE_Plain_Text_Field('MTP_message_type', __('Message Type', 'event_espresso'), false, 'registration'),
34
+				'MTP_is_global'=>new EE_Boolean_Field('MTP_is_global', __('Flag indicating if Template Group is Global', 'event_espresso'), false, true),
35
+				'MTP_is_override'=>new EE_Boolean_Field('MTP_is_override', __('Flag indicating if Template Group overrides any other Templates for the messenger/messagetype combination', 'event_espresso'), false, false),
36
+				'MTP_deleted'=>new EE_Trashed_Flag_Field('MTP_deleted', __('Flag indicating whether this has been trashed', 'event_espresso'), false, false),
37
+				'MTP_is_active'=>new EE_Boolean_Field('MTP_is_active', __('Flag indicating whether template group is active', 'event_espresso'), false, true)
38
+			)
39
+		);
40
+		$this->_model_relations = array(
41
+			'Message_Template' => new EE_Has_Many_Relation(),
42
+			'Message' => new EE_Has_Many_Relation(),
43
+			'Event' => new EE_HABTM_Relation('Event_Message_Template'),
44
+			'WP_User' => new EE_Belongs_To_Relation()
45
+		);
46
+		foreach ($this->_cap_contexts_to_cap_action_map as $context => $action) {
47
+			$this->_cap_restriction_generators[ $context ] = new EE_Restriction_Generator_Global('MTP_is_global');
48
+		}
49
+		$this->_caps_slug = 'messages';
50
+
51
+		parent::__construct($timezone);
52
+	}
53
+
54
+
55
+
56
+	/**
57
+	 * get_all_trashed_message_templates_by_event
58
+	 *
59
+	 * @access public
60
+	 * @param int    $EVT_ID specific event id
61
+	 * @param string $orderby
62
+	 * @param string $order
63
+	 * @param null   $limit
64
+	 * @param bool   $count
65
+	 * @return array message template objects that are attached to a specific event.
66
+	 */
67
+	public function get_all_trashed_message_templates_by_event(
68
+		$EVT_ID,
69
+		$orderby = 'GRP_ID',
70
+		$order = 'ASC',
71
+		$limit = null,
72
+		$count = false
73
+	) {
74
+		$query_params = array( array('Event.EVT_ID' => $EVT_ID), 'order_by' => array($orderby => $order), 'limit' => $limit );
75
+		return $count ? $this->count_deleted($query_params, 'GRP_ID', true) : $this->get_all_deleted($query_params);
76
+	}
77
+
78
+
79
+
80
+	/**
81
+	 * get_all_message_templates_by_messenger
82
+	 *
83
+	 * @access public
84
+	 * @param        $messenger
85
+	 * @param string $orderby
86
+	 * @param string $order
87
+	 * @return array all (including trashed or inactive) message template group objects for the given messenger
88
+	 */
89
+	public function get_all_message_templates_by_messenger($messenger, $orderby = 'GRP_ID', $order = 'ASC')
90
+	{
91
+		return $this->get_all_deleted_and_undeleted(
92
+			array( array( 'MTP_messenger' => $messenger ), 'order_by' => array( $orderby => $order ) )
93
+		);
94
+	}
95
+
96
+
97
+
98
+	/**
99
+	 * This simply adds on any messenger/message type filters that may be present in the $_POST global
100
+	 * @param  array  $_where any existing where conditions to append these to.
101
+	 * @return array          original where conditions or original with additional filters.
102
+	 */
103
+	protected function _maybe_mtp_filters($_where = array())
104
+	{
105
+		// account for messenger or message type filters
106
+		if (isset($_REQUEST['ee_messenger_filter_by'])
107
+			&& $_REQUEST['ee_messenger_filter_by'] != 'none_selected'
108
+			&& $_REQUEST['ee_messenger_filter_by'] != 'all'
109
+		) {
110
+			$_where['MTP_messenger'] =  $_REQUEST['ee_messenger_filter_by'] ;
111
+		}
112
+
113
+		if (isset($_REQUEST['ee_message_type_filter_by'])
114
+			&& $_REQUEST['ee_message_type_filter_by'] != 'none_selected'
115
+		) {
116
+			$_where['MTP_message_type'] = $_REQUEST['ee_message_type_filter_by'];
117
+		}
118
+
119
+		return $_where;
120
+	}
121
+
122
+
123
+
124
+	/**
125
+	 * get_all_active_message_templates groups
126
+	 *
127
+	 * @access public
128
+	 * @param string $orderby
129
+	 * @param string $order
130
+	 * @param null   $limit
131
+	 * @param bool   $count
132
+	 * @param bool   $global
133
+	 * @param bool   $user_check
134
+	 * @return array all active (non_trashed, active) message template objects
135
+	 */
136
+	public function get_all_active_message_templates(
137
+		$orderby = 'GRP_ID',
138
+		$order = 'ASC',
139
+		$limit = null,
140
+		$count = false,
141
+		$global = true,
142
+		$user_check = false
143
+	) {
144
+		$_where = $global ? array('MTP_is_global' => true ) : array('MTP_is_global' => false );
145
+		$_where['MTP_is_active'] = true;
146
+		$_where = $this->_maybe_mtp_filters($_where);
147
+
148
+		if ($user_check
149
+			&& ! $global
150
+			&& ! EE_Registry::instance()->CAP->current_user_can(
151
+				'ee_read_others_messages',
152
+				'get_all_active_message_templates'
153
+			)
154
+		) {
155
+			$_where['MTP_user_id'] = get_current_user_id();
156
+		}
157
+
158
+		$query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
159
+
160
+		return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
161
+	}
162
+
163
+
164
+
165
+	/**
166
+	 *    retrieve ALL message_template groups from db regardless of wht
167
+	 *
168
+	 * @access    public
169
+	 * @param string $orderby
170
+	 * @param string $order
171
+	 * @param null   $limit
172
+	 * @param bool   $count
173
+	 * @return mixed array on success, FALSE on fail
174
+	 */
175
+	public function get_all_message_templates($orderby = 'GRP_ID', $order = 'ASC', $limit = null, $count = false)
176
+	{
177
+		$_where = $this->_maybe_mtp_filters();
178
+
179
+		$query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
180
+
181
+		$r_templates = $count
182
+			? $this->count_deleted_and_undeleted($query_params, 'GRP_ID', true)
183
+			: $this->get_all_deleted_and_undeleted($query_params);
184
+
185
+		return $r_templates;
186
+	}
187
+
188
+
189
+
190
+
191
+	/**
192
+	 * This gets all the custom templates attached to a specific event
193
+	 * @param  int      $EVT_ID         event id
194
+	 * @param  array  $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
195
+	 * @return  EE_Message_Template_Group[]
196
+	 */
197
+	public function get_all_custom_templates_by_event($EVT_ID, $query_params = array())
198
+	{
199
+		$where = array_merge($query_params, array( 'Event.EVT_ID' => $EVT_ID ));
200
+		return $this->get_all(
201
+			array( $where )
202
+		);
203
+	}
204
+
205
+
206
+
207
+	/**
208
+	 * get_all_trashed_grouped_message_templates
209
+	 * this returns ONLY the template groups where ALL contexts are trashed and none of the group are non-trashed
210
+	 *
211
+	 * @access public
212
+	 * @param string $orderby
213
+	 * @param string $order
214
+	 * @param null   $limit
215
+	 * @param bool   $count
216
+	 * @param bool   $global
217
+	 * @return \EE_Message_Template_Group[] message template groups.
218
+	 */
219
+	public function get_all_trashed_grouped_message_templates(
220
+		$orderby = 'GRP_ID',
221
+		$order = 'ASC',
222
+		$limit = null,
223
+		$count = false,
224
+		$global = true
225
+	) {
226
+		$_where = $global ? array('MTP_is_global' => true ) : array('MTP_is_global' => false );
227
+		$_where['MTP_is_active'] = true;
228
+		$_where = $this->_maybe_mtp_filters($_where);
229
+
230
+		$query_params = array( $_where, 'order_by' => array($orderby => $order), 'limit' => $limit );
231
+
232
+		return $count ? $this->count_deleted($query_params, 'GRP_ID', true) : $this->get_all_deleted($query_params);
233
+	}
234
+
235
+
236
+
237
+	/**
238
+	 * this returns the message template group(s) for a given event, messenger, and message template
239
+	 *
240
+	 * @param  string             $messenger
241
+	 * @param  string             $message_type
242
+	 * @param                     $evt_id
243
+	 * @param  string             $orderby pointless at this point but still included
244
+	 * @param  string             $order
245
+	 * @param  mixed (array|null) $limit   array($offset, $num)
246
+	 * @param  bool               $count   true = just return count, false = objects
247
+	 * @param  bool               $active  ignore "active" or not. (default only return active)
248
+	 * @return \mixed[]) depending on $count.
249
+	 */
250
+	public function get_event_message_templates_by_m_and_mt_and_evt(
251
+		$messenger,
252
+		$message_type,
253
+		$evt_id,
254
+		$orderby = 'GRP_ID',
255
+		$order = 'ASC',
256
+		$limit = null,
257
+		$count = false,
258
+		$active = true
259
+	) {
260
+		$_where = array(
261
+			'MTP_messenger' => $messenger,
262
+			'MTP_message_type' => $message_type,
263
+			'Event.EVT_ID' => $evt_id,
264
+			'MTP_is_global' => true,
265
+			'MTP_is_active' => $active
266
+		);
267
+
268
+		$query_params = array( $_where, 'order_by' => array($orderby=>$order), 'limit' => $limit );
269
+
270
+		return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
271
+	}
272
+
273
+
274
+
275
+
276
+	/**
277
+	 * get all GLOBAL message template groups for the given messenger and message type
278
+	 *
279
+	 * @param  string $messenger    slug for messenger
280
+	 * @param  string $message_type slug for message type
281
+	 * @param  string $orderby      what column to orderby
282
+	 * @param  string $order        ASC or DESC
283
+	 * @param  mixed (array|null) $limit array($offset, $num)
284
+	 * @param  bool   $count        true = just return count, false = objects
285
+	 * @param  bool   $active       ignore "active" or not. (default only return active) -
286
+	 *                              'all' means return both inactive AND inactive.
287
+	 * @return array               message template objects that are global (i.e. non-event)
288
+	 */
289
+	public function get_global_message_template_by_m_and_mt(
290
+		$messenger,
291
+		$message_type,
292
+		$orderby = 'GRP_ID',
293
+		$order = 'ASC',
294
+		$limit = null,
295
+		$count = false,
296
+		$active = true
297
+	) {
298
+		$_where = array(
299
+			'MTP_messenger' => $messenger,
300
+			'MTP_message_type' => $message_type,
301
+			'MTP_is_global' => true,
302
+		);
303
+
304
+		if ($active != 'all') {
305
+			$_where['MTP_is_active'] = $active;
306
+		}
307
+
308
+		$query_params = array( $_where, 'order_by' => array( $orderby => $order ), 'limit' => $limit );
309
+
310
+		return $count ? $this->count($query_params, 'GRP_ID', true) : $this->get_all($query_params);
311
+	}
312
+
313
+
314
+
315
+
316
+	/**
317
+	 * get all custom message template groups for the given messenger and message type
318
+	 * @param  string $messenger    messenger
319
+	 * @param  string $message_type messagetype
320
+	 * @param  array  $query_params same as EEM_Base->get_all()
321
+	 * @return EE_Message_Template_Group[]
322
+	 */
323
+	public function get_custom_message_template_by_m_and_mt($messenger, $message_type, $query_params = array())
324
+	{
325
+		return $this->get_all(
326
+			array_merge(
327
+				$query_params,
328
+				array(
329
+					array(
330
+						'MTP_is_global'    => false,
331
+						'MTP_messenger'    => $messenger,
332
+						'MTP_message_type' => $message_type
333
+					)
334
+				)
335
+			)
336
+		);
337
+	}
338
+
339
+
340
+
341
+	/**
342
+	 * This sends things to the validator for the given messenger and message type.
343
+	 *
344
+	 * @param  array $fields the incoming fields to check.
345
+	 *                       Note this array is in the formatted fields from the form fields setup.
346
+	 *                       So we need to reformat this into an array of expected field refs by the validator.
347
+	 *                       Note also that this is not only the fields for the Message Template Group
348
+	 *                       but ALSO for Message Template.
349
+	 * @param string $context      The context the fields were obtained from.
350
+	 * @param string $messenger    The messenger we are validating
351
+	 * @param string $message_type The message type we are validating.
352
+	 * @return mixed If the fields all check out then we return true otherwise error messages are returned
353
+	 *                       (indexed by field name);
354
+	 * @throws \EE_Error
355
+	 */
356
+	public function validate($fields, $context, $messenger, $message_type)
357
+	{
358
+
359
+		$assembled_fields = array();
360
+
361
+		// let's loop through all the fields and set them up in the right format
362
+		foreach ($fields as $index => $value) {
363
+			// first let's figure out if the value['content'] in the current index is an array.
364
+			//  If it is then this is special fields that are used in parsing special shortcodes (i.e. 'attendee_list').
365
+			if (is_array($value['content'])) {
366
+				$assembled_fields[ $value['name'] ] = $value['content']['main'];
367
+				// loop through the content and get the other fields.
368
+				foreach ($value['content'] as $name => $val) {
369
+					if ($name == 'main') {
370
+						continue;
371
+					}
372
+					$assembled_fields[ $name ] = $val;
373
+				}
374
+				continue;
375
+			}
376
+
377
+			// okay if we're here then this is just a straight field=>$value arrangement
378
+			$assembled_fields[ $value['name'] ] = $value['content'];
379
+		}
380
+
381
+		// now we've got the assembled_fields.
382
+		// We need to setup the string for the appropriate validator class and call that.
383
+		$m_ref = ucwords(str_replace('_', ' ', $messenger));
384
+		$m_ref = str_replace(' ', '_', $m_ref);
385
+		$mt_ref = ucwords(str_replace('_', ' ', $message_type));
386
+		$mt_ref = str_replace(' ', '_', $mt_ref);
387
+
388
+		$classname = 'EE_Messages_' . $m_ref . '_' . $mt_ref . '_Validator';
389
+
390
+		if (!class_exists($classname)) {
391
+			$msg[] = __('The Validator class was unable to load', 'event_espresso');
392
+			$msg[] = sprintf(
393
+				__(
394
+					'The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class',
395
+					'event_espresso'
396
+				),
397
+				$classname
398
+			);
399
+			throw new EE_Error(implode('||', $msg));
400
+		}
401
+
402
+		$a = new ReflectionClass($classname);
403
+		$_VLD = $a->newInstance($assembled_fields, $context);
404
+		$result = $_VLD->validate();
405
+		return $result;
406
+	}
407
+
408
+
409
+
410
+	/**
411
+	 * Updates all message template groups matching the incoming arguments to inactive status.
412
+	 *
413
+	 * @param array $messenger_names    The messenger slugs.
414
+	 *                              If empty then all templates matching the message types are marked inactive.
415
+	 *                              Otherwise only templates matching the messengers and message types.
416
+	 * @param array $message_type_names     The message type slugs.
417
+	 *                              If empty then all templates matching the messengers are marked inactive.
418
+	 *                              Otherwise only templates matching the messengers and message types.
419
+	 *
420
+	 * @return int  count of updated records.
421
+	 */
422
+	public function deactivate_message_template_groups_for($messenger_names = array(), $message_type_names = array())
423
+	{
424
+		$query_args = array();
425
+		if (empty($messenger_names) && empty($message_type_names)) {
426
+			return 0;
427
+		}
428
+		if (! empty($messenger_names)) {
429
+			$query_args[0]['MTP_messenger'] = array( 'IN', (array) $messenger_names );
430
+		}
431
+		if (! empty($message_type_names)) {
432
+			$query_args[0]['MTP_message_type'] = array( 'IN', (array) $message_type_names );
433
+		}
434
+		return $this->update(array( 'MTP_is_active' => false ), $query_args);
435
+	}
436 436
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Change_Log.model.php 1 patch
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -11,93 +11,93 @@  discard block
 block discarded – undo
11 11
 class EEM_Change_Log extends EEM_Base
12 12
 {
13 13
 
14
-    /**
15
-     * the related object was created log type
16
-     */
17
-    const type_create = 'create';
18
-    /**
19
-     * the related object was updated (changed, or soft-deleted)
20
-     */
21
-    const type_update = 'update';
22
-    /**
23
-     * the related object was deleted permanently
24
-     */
25
-    const type_delete = 'delete';
26
-    /**
27
-     * the related item had something worth noting happen on it, but
28
-     * only for the purposes of debugging problems
29
-     */
30
-    const type_debug = 'debug';
31
-    /**
32
-     * the related item had an error occur on it
33
-     */
34
-    const type_error = 'error';
35
-    /**
36
-     * the related item is regarding some gateway interaction, like an IPN
37
-     * or request to process a payment
38
-     */
39
-    const type_gateway = 'gateway';
14
+	/**
15
+	 * the related object was created log type
16
+	 */
17
+	const type_create = 'create';
18
+	/**
19
+	 * the related object was updated (changed, or soft-deleted)
20
+	 */
21
+	const type_update = 'update';
22
+	/**
23
+	 * the related object was deleted permanently
24
+	 */
25
+	const type_delete = 'delete';
26
+	/**
27
+	 * the related item had something worth noting happen on it, but
28
+	 * only for the purposes of debugging problems
29
+	 */
30
+	const type_debug = 'debug';
31
+	/**
32
+	 * the related item had an error occur on it
33
+	 */
34
+	const type_error = 'error';
35
+	/**
36
+	 * the related item is regarding some gateway interaction, like an IPN
37
+	 * or request to process a payment
38
+	 */
39
+	const type_gateway = 'gateway';
40 40
 
41
-    /**
42
-     * private instance of the EEM_Change_Log object
43
-     *
44
-     * @access private
45
-     * @var EEM_Change_Log $_instance
46
-     */
47
-    protected static $_instance = null;
41
+	/**
42
+	 * private instance of the EEM_Change_Log object
43
+	 *
44
+	 * @access private
45
+	 * @var EEM_Change_Log $_instance
46
+	 */
47
+	protected static $_instance = null;
48 48
 
49 49
 
50
-    /**
51
-     * constructor
52
-     *
53
-     * @access protected
54
-     * @param null $timezone
55
-     * @throws EE_Error
56
-     */
57
-    protected function __construct($timezone = null)
58
-    {
59
-        global $current_user;
60
-        $this->singular_item       = esc_html__('Log', 'event_espresso');
61
-        $this->plural_item         = esc_html__('Logs', 'event_espresso');
62
-        $this->_tables             = array(
63
-            'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
64
-        );
65
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
66
-        $this->_fields             = array(
67
-            'Log' => array(
68
-                'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
69
-                'LOG_time'    => new EE_Datetime_Field(
70
-                    'LOG_time',
71
-                    esc_html__("Log Time", 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now
74
-                ),
75
-                'OBJ_ID'      => new EE_Foreign_Key_String_Field(
76
-                    'OBJ_ID',
77
-                    esc_html__("Object ID (int or string)", 'event_espresso'),
78
-                    true,
79
-                    null,
80
-                    $models_this_can_attach_to
81
-                ),
82
-                'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
83
-                    'OBJ_type',
84
-                    esc_html__("Object Type", 'event_espresso'),
85
-                    true,
86
-                    null,
87
-                    $models_this_can_attach_to
88
-                ),
89
-                'LOG_type'    => new EE_Plain_Text_Field(
90
-                    'LOG_type',
91
-                    esc_html__("Type of log entry", "event_espresso"),
92
-                    false,
93
-                    self::type_debug
94
-                ),
95
-                'LOG_message' => new EE_Maybe_Serialized_Text_Field(
96
-                    'LOG_message',
97
-                    esc_html__("Log Message (body)", 'event_espresso'),
98
-                    true
99
-                ),
100
-                /*
50
+	/**
51
+	 * constructor
52
+	 *
53
+	 * @access protected
54
+	 * @param null $timezone
55
+	 * @throws EE_Error
56
+	 */
57
+	protected function __construct($timezone = null)
58
+	{
59
+		global $current_user;
60
+		$this->singular_item       = esc_html__('Log', 'event_espresso');
61
+		$this->plural_item         = esc_html__('Logs', 'event_espresso');
62
+		$this->_tables             = array(
63
+			'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
64
+		);
65
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
66
+		$this->_fields             = array(
67
+			'Log' => array(
68
+				'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
69
+				'LOG_time'    => new EE_Datetime_Field(
70
+					'LOG_time',
71
+					esc_html__("Log Time", 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now
74
+				),
75
+				'OBJ_ID'      => new EE_Foreign_Key_String_Field(
76
+					'OBJ_ID',
77
+					esc_html__("Object ID (int or string)", 'event_espresso'),
78
+					true,
79
+					null,
80
+					$models_this_can_attach_to
81
+				),
82
+				'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
83
+					'OBJ_type',
84
+					esc_html__("Object Type", 'event_espresso'),
85
+					true,
86
+					null,
87
+					$models_this_can_attach_to
88
+				),
89
+				'LOG_type'    => new EE_Plain_Text_Field(
90
+					'LOG_type',
91
+					esc_html__("Type of log entry", "event_espresso"),
92
+					false,
93
+					self::type_debug
94
+				),
95
+				'LOG_message' => new EE_Maybe_Serialized_Text_Field(
96
+					'LOG_message',
97
+					esc_html__("Log Message (body)", 'event_espresso'),
98
+					true
99
+				),
100
+				/*
101 101
                  * Note: when querying for a change log's user, the OBJ_ID and OBJ_type fields are used,
102 102
                  * not the LOG_wp_user field. E.g.,
103 103
                  * `EEM_Change_Log::instance()->get_all(array(array('WP_User.ID'=>1)))` will actually return
@@ -106,158 +106,158 @@  discard block
 block discarded – undo
106 106
                  *  If you want the latter, you can't use the model's magic joining. E.g, you would need to do
107 107
                  * `EEM_Change_Log::instance()->get_all(array(array('LOG_wp_user' => 1)))`.
108 108
                  */
109
-                'LOG_wp_user' => new EE_WP_User_Field(
110
-                    'LOG_wp_user',
111
-                    esc_html__("User who was logged in while this occurred", 'event_espresso'),
112
-                    true
113
-                ),
114
-            ),
115
-        );
116
-        $this->_model_relations    = array();
117
-        foreach ($models_this_can_attach_to as $model) {
118
-            if ($model != 'Change_Log') {
119
-                $this->_model_relations[ $model ] = new EE_Belongs_To_Any_Relation();
120
-            }
121
-        }
122
-        // use completely custom caps for this
123
-        $this->_cap_restriction_generators = false;
124
-        // caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
125
-        foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
126
-            $this->_cap_restrictions[ $cap_context ][ EE_Restriction_Generator_Base::get_default_restrictions_cap() ]
127
-                = new EE_Return_None_Where_Conditions();
128
-        }
129
-        parent::__construct($timezone);
130
-    }
109
+				'LOG_wp_user' => new EE_WP_User_Field(
110
+					'LOG_wp_user',
111
+					esc_html__("User who was logged in while this occurred", 'event_espresso'),
112
+					true
113
+				),
114
+			),
115
+		);
116
+		$this->_model_relations    = array();
117
+		foreach ($models_this_can_attach_to as $model) {
118
+			if ($model != 'Change_Log') {
119
+				$this->_model_relations[ $model ] = new EE_Belongs_To_Any_Relation();
120
+			}
121
+		}
122
+		// use completely custom caps for this
123
+		$this->_cap_restriction_generators = false;
124
+		// caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
125
+		foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
126
+			$this->_cap_restrictions[ $cap_context ][ EE_Restriction_Generator_Base::get_default_restrictions_cap() ]
127
+				= new EE_Return_None_Where_Conditions();
128
+		}
129
+		parent::__construct($timezone);
130
+	}
131 131
 
132
-    /**
133
-     * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
134
-     * @param mixed         $message  array|string of the message you want to record
135
-     * @param EE_Base_Class $related_model_obj
136
-     * @return EE_Change_Log
137
-     * @throws EE_Error
138
-     */
139
-    public function log($log_type, $message, $related_model_obj)
140
-    {
141
-        if ($related_model_obj instanceof EE_Base_Class) {
142
-            $obj_id   = $related_model_obj->ID();
143
-            $obj_type = $related_model_obj->get_model()->get_this_model_name();
144
-        } else {
145
-            $obj_id   = null;
146
-            $obj_type = null;
147
-        }
148
-        /** @var EE_Change_Log $log */
149
-        $log = EE_Change_Log::new_instance(array(
150
-            'LOG_type'    => $log_type,
151
-            'LOG_message' => $message,
152
-            'OBJ_ID'      => $obj_id,
153
-            'OBJ_type'    => $obj_type,
154
-        ));
155
-        $log->save();
156
-        return $log;
157
-    }
132
+	/**
133
+	 * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
134
+	 * @param mixed         $message  array|string of the message you want to record
135
+	 * @param EE_Base_Class $related_model_obj
136
+	 * @return EE_Change_Log
137
+	 * @throws EE_Error
138
+	 */
139
+	public function log($log_type, $message, $related_model_obj)
140
+	{
141
+		if ($related_model_obj instanceof EE_Base_Class) {
142
+			$obj_id   = $related_model_obj->ID();
143
+			$obj_type = $related_model_obj->get_model()->get_this_model_name();
144
+		} else {
145
+			$obj_id   = null;
146
+			$obj_type = null;
147
+		}
148
+		/** @var EE_Change_Log $log */
149
+		$log = EE_Change_Log::new_instance(array(
150
+			'LOG_type'    => $log_type,
151
+			'LOG_message' => $message,
152
+			'OBJ_ID'      => $obj_id,
153
+			'OBJ_type'    => $obj_type,
154
+		));
155
+		$log->save();
156
+		return $log;
157
+	}
158 158
 
159 159
 
160
-    /**
161
-     * Adds a gateway log for the specified object, given its ID and type
162
-     *
163
-     * @param string $message
164
-     * @param mixed  $related_obj_id
165
-     * @param string $related_obj_type
166
-     * @throws EE_Error
167
-     * @return EE_Change_Log
168
-     */
169
-    public function gateway_log($message, $related_obj_id, $related_obj_type)
170
-    {
171
-        if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
172
-            throw new EE_Error(
173
-                sprintf(
174
-                    esc_html__(
175
-                        "'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
176
-                        "event_espresso"
177
-                    ),
178
-                    $related_obj_type
179
-                )
180
-            );
181
-        }
182
-        /** @var EE_Change_Log $log */
183
-        $log = EE_Change_Log::new_instance(array(
184
-            'LOG_type'    => EEM_Change_Log::type_gateway,
185
-            'LOG_message' => $message,
186
-            'OBJ_ID'      => $related_obj_id,
187
-            'OBJ_type'    => $related_obj_type,
188
-        ));
189
-        $log->save();
190
-        return $log;
191
-    }
160
+	/**
161
+	 * Adds a gateway log for the specified object, given its ID and type
162
+	 *
163
+	 * @param string $message
164
+	 * @param mixed  $related_obj_id
165
+	 * @param string $related_obj_type
166
+	 * @throws EE_Error
167
+	 * @return EE_Change_Log
168
+	 */
169
+	public function gateway_log($message, $related_obj_id, $related_obj_type)
170
+	{
171
+		if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
172
+			throw new EE_Error(
173
+				sprintf(
174
+					esc_html__(
175
+						"'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
176
+						"event_espresso"
177
+					),
178
+					$related_obj_type
179
+				)
180
+			);
181
+		}
182
+		/** @var EE_Change_Log $log */
183
+		$log = EE_Change_Log::new_instance(array(
184
+			'LOG_type'    => EEM_Change_Log::type_gateway,
185
+			'LOG_message' => $message,
186
+			'OBJ_ID'      => $related_obj_id,
187
+			'OBJ_type'    => $related_obj_type,
188
+		));
189
+		$log->save();
190
+		return $log;
191
+	}
192 192
 
193 193
 
194
-    /**
195
-     * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
196
-     *
197
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
198
-     * @return array of arrays
199
-     * @throws EE_Error
200
-     */
201
-    public function get_all_efficiently($query_params)
202
-    {
203
-        return $this->_get_all_wpdb_results($query_params);
204
-    }
194
+	/**
195
+	 * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
196
+	 *
197
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
198
+	 * @return array of arrays
199
+	 * @throws EE_Error
200
+	 */
201
+	public function get_all_efficiently($query_params)
202
+	{
203
+		return $this->_get_all_wpdb_results($query_params);
204
+	}
205 205
 
206 206
 
207
-    /**
208
-     * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
209
-     * models after this, they may be out-of-sync with the database
210
-     *
211
-     * @param DateTime $datetime
212
-     * @return false|int
213
-     * @throws EE_Error
214
-     */
215
-    public function delete_gateway_logs_older_than(DateTime $datetime)
216
-    {
217
-        global $wpdb;
218
-        return $wpdb->query(
219
-            $wpdb->prepare(
220
-                'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
221
-                EEM_Change_Log::type_gateway,
222
-                $datetime->format(EE_Datetime_Field::mysql_timestamp_format)
223
-            )
224
-        );
225
-    }
207
+	/**
208
+	 * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
209
+	 * models after this, they may be out-of-sync with the database
210
+	 *
211
+	 * @param DateTime $datetime
212
+	 * @return false|int
213
+	 * @throws EE_Error
214
+	 */
215
+	public function delete_gateway_logs_older_than(DateTime $datetime)
216
+	{
217
+		global $wpdb;
218
+		return $wpdb->query(
219
+			$wpdb->prepare(
220
+				'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
221
+				EEM_Change_Log::type_gateway,
222
+				$datetime->format(EE_Datetime_Field::mysql_timestamp_format)
223
+			)
224
+		);
225
+	}
226 226
 
227 227
 
228
-    /**
229
-     * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
230
-     * map vai the given filter.
231
-     *
232
-     * @return array
233
-     */
234
-    public static function get_pretty_label_map_for_registered_types()
235
-    {
236
-        return apply_filters(
237
-            'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
238
-            array(
239
-                self::type_create=>  esc_html__("Create", "event_espresso"),
240
-                self::type_update=>  esc_html__("Update", "event_espresso"),
241
-                self::type_delete => esc_html__("Delete", "event_espresso"),
242
-                self::type_debug=>  esc_html__("Debug", "event_espresso"),
243
-                self::type_error=>  esc_html__("Error", "event_espresso"),
244
-                self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
245
-            )
246
-        );
247
-    }
228
+	/**
229
+	 * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
230
+	 * map vai the given filter.
231
+	 *
232
+	 * @return array
233
+	 */
234
+	public static function get_pretty_label_map_for_registered_types()
235
+	{
236
+		return apply_filters(
237
+			'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
238
+			array(
239
+				self::type_create=>  esc_html__("Create", "event_espresso"),
240
+				self::type_update=>  esc_html__("Update", "event_espresso"),
241
+				self::type_delete => esc_html__("Delete", "event_espresso"),
242
+				self::type_debug=>  esc_html__("Debug", "event_espresso"),
243
+				self::type_error=>  esc_html__("Error", "event_espresso"),
244
+				self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
245
+			)
246
+		);
247
+	}
248 248
 
249 249
 
250
-    /**
251
-     * Return the pretty (localized) label for the given log type identifier.
252
-     * @param string $type_identifier
253
-     * @return string
254
-     */
255
-    public static function get_pretty_label_for_type($type_identifier)
256
-    {
257
-        $type_identifier_map = self::get_pretty_label_map_for_registered_types();
258
-        // we fallback to the incoming type identifier if there is no localized label for it.
259
-        return isset($type_identifier_map[ $type_identifier ])
260
-            ? $type_identifier_map[ $type_identifier ]
261
-            : $type_identifier;
262
-    }
250
+	/**
251
+	 * Return the pretty (localized) label for the given log type identifier.
252
+	 * @param string $type_identifier
253
+	 * @return string
254
+	 */
255
+	public static function get_pretty_label_for_type($type_identifier)
256
+	{
257
+		$type_identifier_map = self::get_pretty_label_map_for_registered_types();
258
+		// we fallback to the incoming type identifier if there is no localized label for it.
259
+		return isset($type_identifier_map[ $type_identifier ])
260
+			? $type_identifier_map[ $type_identifier ]
261
+			: $type_identifier;
262
+	}
263 263
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Currency.model.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -11,66 +11,66 @@
 block discarded – undo
11 11
  */
12 12
 class EEM_Currency extends EEM_Base
13 13
 {
14
-        // private instance of the Attendee object
15
-    protected static $_instance = null;
14
+		// private instance of the Attendee object
15
+	protected static $_instance = null;
16 16
 
17
-    protected function __construct($timezone = null)
18
-    {
19
-        $this->singular_item = __('Currency', 'event_espresso');
20
-        $this->plural_item = __('Currencies', 'event_espresso');
21
-        $this->_tables = array(
22
-            'Currency'=> new EE_Primary_Table('esp_currency', 'CUR_code')
23
-        );
24
-        $this->_fields = array(
25
-            'Currency'=>array(
26
-                'CUR_code'=> new EE_Primary_Key_String_Field('CUR_code', __('Currency Code', 'event_espresso')),
27
-                'CUR_single' => new EE_Plain_Text_Field('CUR_single', __('Currency Name Singular', 'event_espresso'), false),
28
-                'CUR_plural' => new EE_Plain_Text_Field('CUR_plural', __('Currency Name Plural', 'event_espresso'), false),
29
-                'CUR_sign' => new EE_Plain_Text_Field('CUR_sign', __('Currency Sign', 'event_espresso'), false),
30
-                'CUR_dec_plc' => new EE_Integer_Field('CUR_dec_plc', __('Currency Decimal Places', 'event_espresso'), false, 2),
31
-                'CUR_active'=>new EE_Boolean_Field('CUR_active', __('Active?', 'event_espresso'), false, true),
32
-            ));
33
-        $this->_model_relations = array(
34
-            'Payment_Method'=>new EE_HABTM_Relation('Currency_Payment_Method'),
35
-        );
36
-        // this model is generally available for reading
37
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
17
+	protected function __construct($timezone = null)
18
+	{
19
+		$this->singular_item = __('Currency', 'event_espresso');
20
+		$this->plural_item = __('Currencies', 'event_espresso');
21
+		$this->_tables = array(
22
+			'Currency'=> new EE_Primary_Table('esp_currency', 'CUR_code')
23
+		);
24
+		$this->_fields = array(
25
+			'Currency'=>array(
26
+				'CUR_code'=> new EE_Primary_Key_String_Field('CUR_code', __('Currency Code', 'event_espresso')),
27
+				'CUR_single' => new EE_Plain_Text_Field('CUR_single', __('Currency Name Singular', 'event_espresso'), false),
28
+				'CUR_plural' => new EE_Plain_Text_Field('CUR_plural', __('Currency Name Plural', 'event_espresso'), false),
29
+				'CUR_sign' => new EE_Plain_Text_Field('CUR_sign', __('Currency Sign', 'event_espresso'), false),
30
+				'CUR_dec_plc' => new EE_Integer_Field('CUR_dec_plc', __('Currency Decimal Places', 'event_espresso'), false, 2),
31
+				'CUR_active'=>new EE_Boolean_Field('CUR_active', __('Active?', 'event_espresso'), false, true),
32
+			));
33
+		$this->_model_relations = array(
34
+			'Payment_Method'=>new EE_HABTM_Relation('Currency_Payment_Method'),
35
+		);
36
+		// this model is generally available for reading
37
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
38 38
 
39
-        parent::__construct($timezone);
40
-    }
39
+		parent::__construct($timezone);
40
+	}
41 41
 
42
-    /**
43
-     * Gets all thea ctive currencies, and orders them by their singular name, and then their code
44
-     * (may be overridden)
45
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
46
-     * @return EE_Currency[]
47
-     */
48
-    public function get_all_active($query_params = array())
49
-    {
50
-        $query_params[0]['CUR_active'] = true;
51
-        if (! isset($query_params['order_by'])) {
52
-            $query_params['order_by'] = array('CUR_code'=>'ASC','CUR_single'=>'ASC');
53
-        }
54
-        return $this->get_all($query_params);
55
-    }
56
-    /**
57
-     * Gets all the currencies which can be used by that payment method type
58
-     * @param EE_PMT_Base $payment_method_type
59
-     * @return EE_Currency[]
60
-     */
61
-    public function get_all_currencies_usable_by($payment_method_type)
62
-    {
63
-        if ($payment_method_type instanceof EE_PMT_Base &&
64
-                $payment_method_type->get_gateway()) {
65
-            $currencies_supported = $payment_method_type->get_gateway()->currencies_supported();
66
-        } else {
67
-            $currencies_supported = EE_Gateway::all_currencies_supported;
68
-        }
69
-        if ($currencies_supported == EE_Gateway::all_currencies_supported || empty($currencies_supported)) {
70
-            $currencies = $this->get_all_active();
71
-        } else {
72
-            $currencies = $this->get_all_active(array(array('CUR_code'=>array('IN',$currencies_supported))));
73
-        }
74
-        return $currencies;
75
-    }
42
+	/**
43
+	 * Gets all thea ctive currencies, and orders them by their singular name, and then their code
44
+	 * (may be overridden)
45
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
46
+	 * @return EE_Currency[]
47
+	 */
48
+	public function get_all_active($query_params = array())
49
+	{
50
+		$query_params[0]['CUR_active'] = true;
51
+		if (! isset($query_params['order_by'])) {
52
+			$query_params['order_by'] = array('CUR_code'=>'ASC','CUR_single'=>'ASC');
53
+		}
54
+		return $this->get_all($query_params);
55
+	}
56
+	/**
57
+	 * Gets all the currencies which can be used by that payment method type
58
+	 * @param EE_PMT_Base $payment_method_type
59
+	 * @return EE_Currency[]
60
+	 */
61
+	public function get_all_currencies_usable_by($payment_method_type)
62
+	{
63
+		if ($payment_method_type instanceof EE_PMT_Base &&
64
+				$payment_method_type->get_gateway()) {
65
+			$currencies_supported = $payment_method_type->get_gateway()->currencies_supported();
66
+		} else {
67
+			$currencies_supported = EE_Gateway::all_currencies_supported;
68
+		}
69
+		if ($currencies_supported == EE_Gateway::all_currencies_supported || empty($currencies_supported)) {
70
+			$currencies = $this->get_all_active();
71
+		} else {
72
+			$currencies = $this->get_all_active(array(array('CUR_code'=>array('IN',$currencies_supported))));
73
+		}
74
+		return $currencies;
75
+	}
76 76
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 1 patch
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -32,443 +32,443 @@
 block discarded – undo
32 32
 class EEM_Line_Item extends EEM_Base
33 33
 {
34 34
 
35
-    /**
36
-     * Tax sub-total is just the total of all the taxes, which should be children
37
-     * of this line item. There should only ever be one tax sub-total, and it should
38
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
39
-     */
40
-    const type_tax_sub_total = 'tax-sub-total';
41
-
42
-    /**
43
-     * Tax line items indicate a tax applied to all the taxable line items.
44
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
45
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
46
-     */
47
-    const type_tax = 'tax';
48
-
49
-    /**
50
-     * Indicating individual items purchased, or discounts or surcharges.
51
-     * The sum of all the regular line items  plus the tax items should equal
52
-     * the grand total.
53
-     * Possible children are sub-line-items and cancellations.
54
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
55
-     * LIN_totals. Its LIN_percent = 0.
56
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
57
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
58
-     */
59
-    const type_line_item = 'line-item';
60
-
61
-    /**
62
-     * Line item indicating all the factors that make a single line item.
63
-     * Sub-line items should have NO children line items.
64
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
65
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
66
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
67
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
68
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
69
-     */
70
-    const type_sub_line_item = 'sub-item';
71
-
72
-    /**
73
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
74
-     * Direct children should be event subtotals.
75
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
76
-     *
77
-     */
78
-    const type_sub_total = 'sub-total';
79
-
80
-    /**
81
-     * Line item for the grand total of an order. Its direct children
82
-     * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
83
-     * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
84
-     * the entire order's mount.
85
-     */
86
-    const type_total = 'total';
87
-
88
-    /**
89
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
90
-     * should be created, indicating the quantity that were cancelled
91
-     * (because a line item could have a quantity of 1, and its cancellation item
92
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
93
-     * cancelled, and only one remains).
94
-     * When items are refunded, a cancellation line item should be made, which points
95
-     * to teh payment model object which actually refunded the payment.
96
-     * Cancellations should NOT have any children line items; the should NOT affect
97
-     * any calculations, and are only meant as a record that cancellations have occurred.
98
-     * Their LIN_percent should be 0.
99
-     */
100
-    const type_cancellation = 'cancellation';
101
-
102
-    // private instance of the EEM_Line_Item object
103
-    protected static $_instance = null;
104
-
105
-
106
-    /**
107
-     *        private constructor to prevent direct creation
108
-     * @Constructor
109
-     * @access protected
110
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
111
-     * @return \EEM_Line_Item
112
-     */
113
-    protected function __construct($timezone)
114
-    {
115
-        $this->singular_item = __('Line Item', 'event_espresso');
116
-        $this->plural_item = __('Line Items', 'event_espresso');
117
-
118
-        $this->_tables = array(
119
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
120
-        );
121
-        $line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
122
-        $this->_fields = array(
123
-            'Line_Item' => array(
124
-                'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
125
-                'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), true),
126
-                'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), true, null, 'Transaction'),
127
-                'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), false, ''),
128
-                'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), true),
129
-                'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), false, 0),
130
-                'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), false, 0),
131
-                'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), false, false),
132
-                'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), false, 1),
133
-                'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), false, 0),
134
-                'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), true, 1),
135
-                'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), true, null),
136
-                'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), false, 'line-item', array(
137
-                        self::type_line_item => __("Line Item", "event_espresso"),
138
-                        self::type_sub_line_item => __("Sub-Item", "event_espresso"),
139
-                        self::type_sub_total => __("Subtotal", "event_espresso"),
140
-                        self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
141
-                        self::type_tax => __("Tax", "event_espresso"),
142
-                        self::type_total => __("Total", "event_espresso"),
143
-                        self::type_cancellation => __('Cancellation', 'event_espresso')
144
-                    )),
145
-                'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), true, null, $line_items_can_be_for),
146
-                'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), true, null, $line_items_can_be_for),
147
-                'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
148
-            )
149
-        );
150
-        $this->_model_relations = array(
151
-            'Transaction' => new EE_Belongs_To_Relation(),
152
-            'Ticket' => new EE_Belongs_To_Any_Relation(),
153
-            'Price' => new EE_Belongs_To_Any_Relation(),
154
-            'Event' => new EE_Belongs_To_Any_Relation()
155
-        );
156
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
157
-        $this->_caps_slug = 'transactions';
158
-        parent::__construct($timezone);
159
-    }
160
-
161
-
162
-    /**
163
-     * Gets all the line items for this transaction of the given type
164
-     * @param string $line_item_type like one of EEM_Line_Item::type_*
165
-     * @param EE_Transaction|int $transaction
166
-     * @return EE_Line_Item[]
167
-     */
168
-    public function get_all_of_type_for_transaction($line_item_type, $transaction)
169
-    {
170
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
171
-        return $this->get_all(array(array(
172
-            'LIN_type' => $line_item_type,
173
-            'TXN_ID' => $transaction
174
-        )));
175
-    }
176
-
177
-
178
-    /**
179
-     * Gets all line items unrelated to tickets that are normal line items
180
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
181
-     * @param EE_Transaction|int $transaction
182
-     * @return EE_Line_Item[]
183
-     */
184
-    public function get_all_non_ticket_line_items_for_transaction($transaction)
185
-    {
186
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
-        return $this->get_all(array(array(
188
-            'LIN_type' => self::type_line_item,
189
-            'TXN_ID' => $transaction,
190
-            'OR' => array(
191
-                'OBJ_type*notticket' => array('!=', 'Ticket'),
192
-                'OBJ_type*null' => array('IS_NULL'))
193
-        )));
194
-    }
195
-
196
-    /**
197
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
198
-     * This needs to be very efficient
199
-     * because if there are spam bots afoot there will be LOTS of line items
200
-     * @return int count of how many deleted
201
-     */
202
-    public function delete_line_items_with_no_transaction()
203
-    {
204
-        /** @type WPDB $wpdb */
205
-        global $wpdb;
206
-        $time_to_leave_alone = apply_filters(
207
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
208
-            WEEK_IN_SECONDS
209
-        );
210
-        $query = $wpdb->prepare(
211
-            'DELETE li
35
+	/**
36
+	 * Tax sub-total is just the total of all the taxes, which should be children
37
+	 * of this line item. There should only ever be one tax sub-total, and it should
38
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
39
+	 */
40
+	const type_tax_sub_total = 'tax-sub-total';
41
+
42
+	/**
43
+	 * Tax line items indicate a tax applied to all the taxable line items.
44
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
45
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
46
+	 */
47
+	const type_tax = 'tax';
48
+
49
+	/**
50
+	 * Indicating individual items purchased, or discounts or surcharges.
51
+	 * The sum of all the regular line items  plus the tax items should equal
52
+	 * the grand total.
53
+	 * Possible children are sub-line-items and cancellations.
54
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
55
+	 * LIN_totals. Its LIN_percent = 0.
56
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
57
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
58
+	 */
59
+	const type_line_item = 'line-item';
60
+
61
+	/**
62
+	 * Line item indicating all the factors that make a single line item.
63
+	 * Sub-line items should have NO children line items.
64
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
65
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
66
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
67
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
68
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
69
+	 */
70
+	const type_sub_line_item = 'sub-item';
71
+
72
+	/**
73
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
74
+	 * Direct children should be event subtotals.
75
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
76
+	 *
77
+	 */
78
+	const type_sub_total = 'sub-total';
79
+
80
+	/**
81
+	 * Line item for the grand total of an order. Its direct children
82
+	 * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
83
+	 * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
84
+	 * the entire order's mount.
85
+	 */
86
+	const type_total = 'total';
87
+
88
+	/**
89
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
90
+	 * should be created, indicating the quantity that were cancelled
91
+	 * (because a line item could have a quantity of 1, and its cancellation item
92
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
93
+	 * cancelled, and only one remains).
94
+	 * When items are refunded, a cancellation line item should be made, which points
95
+	 * to teh payment model object which actually refunded the payment.
96
+	 * Cancellations should NOT have any children line items; the should NOT affect
97
+	 * any calculations, and are only meant as a record that cancellations have occurred.
98
+	 * Their LIN_percent should be 0.
99
+	 */
100
+	const type_cancellation = 'cancellation';
101
+
102
+	// private instance of the EEM_Line_Item object
103
+	protected static $_instance = null;
104
+
105
+
106
+	/**
107
+	 *        private constructor to prevent direct creation
108
+	 * @Constructor
109
+	 * @access protected
110
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
111
+	 * @return \EEM_Line_Item
112
+	 */
113
+	protected function __construct($timezone)
114
+	{
115
+		$this->singular_item = __('Line Item', 'event_espresso');
116
+		$this->plural_item = __('Line Items', 'event_espresso');
117
+
118
+		$this->_tables = array(
119
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
120
+		);
121
+		$line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
122
+		$this->_fields = array(
123
+			'Line_Item' => array(
124
+				'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
125
+				'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), true),
126
+				'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), true, null, 'Transaction'),
127
+				'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), false, ''),
128
+				'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), true),
129
+				'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), false, 0),
130
+				'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), false, 0),
131
+				'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), false, false),
132
+				'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), false, 1),
133
+				'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), false, 0),
134
+				'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), true, 1),
135
+				'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), true, null),
136
+				'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), false, 'line-item', array(
137
+						self::type_line_item => __("Line Item", "event_espresso"),
138
+						self::type_sub_line_item => __("Sub-Item", "event_espresso"),
139
+						self::type_sub_total => __("Subtotal", "event_espresso"),
140
+						self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
141
+						self::type_tax => __("Tax", "event_espresso"),
142
+						self::type_total => __("Total", "event_espresso"),
143
+						self::type_cancellation => __('Cancellation', 'event_espresso')
144
+					)),
145
+				'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), true, null, $line_items_can_be_for),
146
+				'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), true, null, $line_items_can_be_for),
147
+				'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
148
+			)
149
+		);
150
+		$this->_model_relations = array(
151
+			'Transaction' => new EE_Belongs_To_Relation(),
152
+			'Ticket' => new EE_Belongs_To_Any_Relation(),
153
+			'Price' => new EE_Belongs_To_Any_Relation(),
154
+			'Event' => new EE_Belongs_To_Any_Relation()
155
+		);
156
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
157
+		$this->_caps_slug = 'transactions';
158
+		parent::__construct($timezone);
159
+	}
160
+
161
+
162
+	/**
163
+	 * Gets all the line items for this transaction of the given type
164
+	 * @param string $line_item_type like one of EEM_Line_Item::type_*
165
+	 * @param EE_Transaction|int $transaction
166
+	 * @return EE_Line_Item[]
167
+	 */
168
+	public function get_all_of_type_for_transaction($line_item_type, $transaction)
169
+	{
170
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
171
+		return $this->get_all(array(array(
172
+			'LIN_type' => $line_item_type,
173
+			'TXN_ID' => $transaction
174
+		)));
175
+	}
176
+
177
+
178
+	/**
179
+	 * Gets all line items unrelated to tickets that are normal line items
180
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
181
+	 * @param EE_Transaction|int $transaction
182
+	 * @return EE_Line_Item[]
183
+	 */
184
+	public function get_all_non_ticket_line_items_for_transaction($transaction)
185
+	{
186
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
+		return $this->get_all(array(array(
188
+			'LIN_type' => self::type_line_item,
189
+			'TXN_ID' => $transaction,
190
+			'OR' => array(
191
+				'OBJ_type*notticket' => array('!=', 'Ticket'),
192
+				'OBJ_type*null' => array('IS_NULL'))
193
+		)));
194
+	}
195
+
196
+	/**
197
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
198
+	 * This needs to be very efficient
199
+	 * because if there are spam bots afoot there will be LOTS of line items
200
+	 * @return int count of how many deleted
201
+	 */
202
+	public function delete_line_items_with_no_transaction()
203
+	{
204
+		/** @type WPDB $wpdb */
205
+		global $wpdb;
206
+		$time_to_leave_alone = apply_filters(
207
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
208
+			WEEK_IN_SECONDS
209
+		);
210
+		$query = $wpdb->prepare(
211
+			'DELETE li
212 212
 				FROM ' . $this->table() . ' li
213 213
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
214 214
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
215
-            // use GMT time because that's what TXN_timestamps are in
216
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
217
-        );
218
-        return $wpdb->query($query);
219
-    }
220
-
221
-
222
-    /**
223
-     * get_line_item_for_transaction_object
224
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
225
-     *
226
-     * @param int $TXN_ID
227
-     * @param \EE_Base_Class $object
228
-     * @return EE_Line_Item[]
229
-     */
230
-    public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
231
-    {
232
-        return $this->get_all(array(array(
233
-            'TXN_ID' => $TXN_ID,
234
-            'OBJ_type' => str_replace('EE_', '', get_class($object)),
235
-            'OBJ_ID' => $object->ID()
236
-        )));
237
-    }
238
-
239
-
240
-    /**
241
-     * get_object_line_items_for_transaction
242
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
243
-     *
244
-     * @param int $TXN_ID
245
-     * @param string $OBJ_type
246
-     * @param array $OBJ_IDs
247
-     * @return EE_Line_Item[]
248
-     */
249
-    public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
250
-    {
251
-        $query_params = array(
252
-            'OBJ_type' => $OBJ_type,
253
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
254
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
255
-        );
256
-        if ($TXN_ID) {
257
-            $query_params['TXN_ID'] = $TXN_ID;
258
-        }
259
-        return $this->get_all(array($query_params));
260
-    }
261
-
262
-
263
-    /**
264
-     * get_all_ticket_line_items_for_transaction
265
-     *
266
-     * @param EE_Transaction $transaction
267
-     * @return EE_Line_Item[]
268
-     */
269
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
270
-    {
271
-        return $this->get_all(array(
272
-            array(
273
-                'TXN_ID' => $transaction->ID(),
274
-                'OBJ_type' => 'Ticket',
275
-            )
276
-        ));
277
-    }
278
-
279
-
280
-    /**
281
-     * get_ticket_line_item_for_transaction
282
-     *
283
-     * @param int $TXN_ID
284
-     * @param int $TKT_ID
285
-     * @return \EE_Line_Item
286
-     */
287
-    public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
288
-    {
289
-        return $this->get_one(array(
290
-            array(
291
-                'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
292
-                'OBJ_ID' => $TKT_ID,
293
-                'OBJ_type' => 'Ticket',
294
-            )
295
-        ));
296
-    }
297
-
298
-
299
-    /**
300
-     * get_existing_promotion_line_item
301
-     * searches the cart for existing line items for the specified promotion
302
-     *
303
-     * @since   1.0.0
304
-     *
305
-     * @param EE_Line_Item $parent_line_item
306
-     * @param EE_Promotion $promotion
307
-     * @return EE_Line_Item
308
-     */
309
-    public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
310
-    {
311
-        return $this->get_one(array(
312
-            array(
313
-                'TXN_ID' => $parent_line_item->TXN_ID(),
314
-                'LIN_parent' => $parent_line_item->ID(),
315
-                'OBJ_type' => 'Promotion',
316
-                'OBJ_ID' => $promotion->ID()
317
-            )
318
-        ));
319
-    }
320
-
321
-
322
-    /**
323
-     * get_all_promotion_line_items
324
-     * searches the cart for any and all existing promotion line items
325
-     *
326
-     * @since   1.0.0
327
-     *
328
-     * @param EE_Line_Item $parent_line_item
329
-     * @return EE_Line_Item[]
330
-     */
331
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
332
-    {
333
-        return $this->get_all(array(
334
-            array(
335
-                'TXN_ID' => $parent_line_item->TXN_ID(),
336
-                'LIN_parent' => $parent_line_item->ID(),
337
-                'OBJ_type' => 'Promotion'
338
-            )
339
-        ));
340
-    }
341
-
342
-    /**
343
-     * Gets the registration's corresponding line item.
344
-     * Note: basically does NOT support having multiple line items for a single ticket,
345
-     * which would happen if some of the registrations had a price modifier while others didn't.
346
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
347
-     * @param EE_Registration $registration
348
-     * @return EE_Line_ITem
349
-     */
350
-    public function get_line_item_for_registration(EE_Registration $registration)
351
-    {
352
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
353
-    }
354
-
355
-    /**
356
-     * Gets the query params used to retrieve a specific line item for the given registration
357
-     * @param EE_Registration $registration
358
-     * @param array $original_query_params any extra query params you'd like to be merged with
359
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
360
-     */
361
-    public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
362
-    {
363
-        return array_replace_recursive($original_query_params, array(
364
-            array(
365
-                'OBJ_ID' => $registration->ticket_ID(),
366
-                'OBJ_type' => 'Ticket',
367
-                'TXN_ID' => $registration->transaction_ID()
368
-            )
369
-        ));
370
-    }
371
-
372
-
373
-    /**
374
-     * @return EE_Base_Class[]|EE_Line_Item[]
375
-     * @throws InvalidInterfaceException
376
-     * @throws InvalidDataTypeException
377
-     * @throws EE_Error
378
-     * @throws InvalidArgumentException
379
-     */
380
-    public function get_total_line_items_with_no_transaction()
381
-    {
382
-        return $this->get_total_line_items_for_carts();
383
-    }
384
-
385
-
386
-    /**
387
-     * @return EE_Base_Class[]|EE_Line_Item[]
388
-     * @throws InvalidInterfaceException
389
-     * @throws InvalidDataTypeException
390
-     * @throws EE_Error
391
-     * @throws InvalidArgumentException
392
-     */
393
-    public function get_total_line_items_for_active_carts()
394
-    {
395
-        return $this->get_total_line_items_for_carts(false);
396
-    }
397
-
398
-
399
-    /**
400
-     * @return EE_Base_Class[]|EE_Line_Item[]
401
-     * @throws InvalidInterfaceException
402
-     * @throws InvalidDataTypeException
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     */
406
-    public function get_total_line_items_for_expired_carts()
407
-    {
408
-        return $this->get_total_line_items_for_carts(true);
409
-    }
410
-
411
-
412
-    /**
413
-     * Returns an array of grand total line items where the TXN_ID is 0.
414
-     * If $expired is set to true, then only line items for expired sessions will be returned.
415
-     * If $expired is set to false, then only line items for active sessions will be returned.
416
-     *
417
-     * @param null $expired
418
-     * @return EE_Base_Class[]|EE_Line_Item[]
419
-     * @throws EE_Error
420
-     * @throws InvalidArgumentException
421
-     * @throws InvalidDataTypeException
422
-     * @throws InvalidInterfaceException
423
-     */
424
-    private function get_total_line_items_for_carts($expired = null)
425
-    {
426
-        $where_params = array(
427
-            'TXN_ID' => 0,
428
-            'LIN_type' => 'total',
429
-        );
430
-        if ($expired !== null) {
431
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
432
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
433
-                'EventEspresso\core\domain\values\session\SessionLifespan'
434
-            );
435
-            $where_params['LIN_timestamp'] = array(
436
-                $expired ? '<=' : '>',
437
-                $session_lifespan->expiration(),
438
-            );
439
-        }
440
-        return $this->get_all(array($where_params));
441
-    }
442
-
443
-
444
-    /**
445
-     * Returns an array of ticket total line items where the TXN_ID is 0
446
-     * AND the timestamp is older than the session lifespan.
447
-     *
448
-     * @param int $timestamp
449
-     * @return EE_Base_Class[]|EE_Line_Item[]
450
-     * @throws EE_Error
451
-     * @throws InvalidArgumentException
452
-     * @throws InvalidDataTypeException
453
-     * @throws InvalidInterfaceException
454
-     */
455
-    public function getTicketLineItemsForExpiredCarts($timestamp = 0)
456
-    {
457
-        if (! absint($timestamp)) {
458
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
459
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
460
-                'EventEspresso\core\domain\values\session\SessionLifespan'
461
-            );
462
-            $timestamp = $session_lifespan->expiration();
463
-        }
464
-        return $this->get_all(
465
-            array(
466
-                array(
467
-                    'TXN_ID'        => 0,
468
-                    'OBJ_type'      => 'Ticket',
469
-                    'LIN_timestamp' => array('<=', $timestamp),
470
-                )
471
-            )
472
-        );
473
-    }
215
+			// use GMT time because that's what TXN_timestamps are in
216
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
217
+		);
218
+		return $wpdb->query($query);
219
+	}
220
+
221
+
222
+	/**
223
+	 * get_line_item_for_transaction_object
224
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
225
+	 *
226
+	 * @param int $TXN_ID
227
+	 * @param \EE_Base_Class $object
228
+	 * @return EE_Line_Item[]
229
+	 */
230
+	public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
231
+	{
232
+		return $this->get_all(array(array(
233
+			'TXN_ID' => $TXN_ID,
234
+			'OBJ_type' => str_replace('EE_', '', get_class($object)),
235
+			'OBJ_ID' => $object->ID()
236
+		)));
237
+	}
238
+
239
+
240
+	/**
241
+	 * get_object_line_items_for_transaction
242
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
243
+	 *
244
+	 * @param int $TXN_ID
245
+	 * @param string $OBJ_type
246
+	 * @param array $OBJ_IDs
247
+	 * @return EE_Line_Item[]
248
+	 */
249
+	public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
250
+	{
251
+		$query_params = array(
252
+			'OBJ_type' => $OBJ_type,
253
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
254
+			'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
255
+		);
256
+		if ($TXN_ID) {
257
+			$query_params['TXN_ID'] = $TXN_ID;
258
+		}
259
+		return $this->get_all(array($query_params));
260
+	}
261
+
262
+
263
+	/**
264
+	 * get_all_ticket_line_items_for_transaction
265
+	 *
266
+	 * @param EE_Transaction $transaction
267
+	 * @return EE_Line_Item[]
268
+	 */
269
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
270
+	{
271
+		return $this->get_all(array(
272
+			array(
273
+				'TXN_ID' => $transaction->ID(),
274
+				'OBJ_type' => 'Ticket',
275
+			)
276
+		));
277
+	}
278
+
279
+
280
+	/**
281
+	 * get_ticket_line_item_for_transaction
282
+	 *
283
+	 * @param int $TXN_ID
284
+	 * @param int $TKT_ID
285
+	 * @return \EE_Line_Item
286
+	 */
287
+	public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
288
+	{
289
+		return $this->get_one(array(
290
+			array(
291
+				'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
292
+				'OBJ_ID' => $TKT_ID,
293
+				'OBJ_type' => 'Ticket',
294
+			)
295
+		));
296
+	}
297
+
298
+
299
+	/**
300
+	 * get_existing_promotion_line_item
301
+	 * searches the cart for existing line items for the specified promotion
302
+	 *
303
+	 * @since   1.0.0
304
+	 *
305
+	 * @param EE_Line_Item $parent_line_item
306
+	 * @param EE_Promotion $promotion
307
+	 * @return EE_Line_Item
308
+	 */
309
+	public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
310
+	{
311
+		return $this->get_one(array(
312
+			array(
313
+				'TXN_ID' => $parent_line_item->TXN_ID(),
314
+				'LIN_parent' => $parent_line_item->ID(),
315
+				'OBJ_type' => 'Promotion',
316
+				'OBJ_ID' => $promotion->ID()
317
+			)
318
+		));
319
+	}
320
+
321
+
322
+	/**
323
+	 * get_all_promotion_line_items
324
+	 * searches the cart for any and all existing promotion line items
325
+	 *
326
+	 * @since   1.0.0
327
+	 *
328
+	 * @param EE_Line_Item $parent_line_item
329
+	 * @return EE_Line_Item[]
330
+	 */
331
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
332
+	{
333
+		return $this->get_all(array(
334
+			array(
335
+				'TXN_ID' => $parent_line_item->TXN_ID(),
336
+				'LIN_parent' => $parent_line_item->ID(),
337
+				'OBJ_type' => 'Promotion'
338
+			)
339
+		));
340
+	}
341
+
342
+	/**
343
+	 * Gets the registration's corresponding line item.
344
+	 * Note: basically does NOT support having multiple line items for a single ticket,
345
+	 * which would happen if some of the registrations had a price modifier while others didn't.
346
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
347
+	 * @param EE_Registration $registration
348
+	 * @return EE_Line_ITem
349
+	 */
350
+	public function get_line_item_for_registration(EE_Registration $registration)
351
+	{
352
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
353
+	}
354
+
355
+	/**
356
+	 * Gets the query params used to retrieve a specific line item for the given registration
357
+	 * @param EE_Registration $registration
358
+	 * @param array $original_query_params any extra query params you'd like to be merged with
359
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
360
+	 */
361
+	public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
362
+	{
363
+		return array_replace_recursive($original_query_params, array(
364
+			array(
365
+				'OBJ_ID' => $registration->ticket_ID(),
366
+				'OBJ_type' => 'Ticket',
367
+				'TXN_ID' => $registration->transaction_ID()
368
+			)
369
+		));
370
+	}
371
+
372
+
373
+	/**
374
+	 * @return EE_Base_Class[]|EE_Line_Item[]
375
+	 * @throws InvalidInterfaceException
376
+	 * @throws InvalidDataTypeException
377
+	 * @throws EE_Error
378
+	 * @throws InvalidArgumentException
379
+	 */
380
+	public function get_total_line_items_with_no_transaction()
381
+	{
382
+		return $this->get_total_line_items_for_carts();
383
+	}
384
+
385
+
386
+	/**
387
+	 * @return EE_Base_Class[]|EE_Line_Item[]
388
+	 * @throws InvalidInterfaceException
389
+	 * @throws InvalidDataTypeException
390
+	 * @throws EE_Error
391
+	 * @throws InvalidArgumentException
392
+	 */
393
+	public function get_total_line_items_for_active_carts()
394
+	{
395
+		return $this->get_total_line_items_for_carts(false);
396
+	}
397
+
398
+
399
+	/**
400
+	 * @return EE_Base_Class[]|EE_Line_Item[]
401
+	 * @throws InvalidInterfaceException
402
+	 * @throws InvalidDataTypeException
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 */
406
+	public function get_total_line_items_for_expired_carts()
407
+	{
408
+		return $this->get_total_line_items_for_carts(true);
409
+	}
410
+
411
+
412
+	/**
413
+	 * Returns an array of grand total line items where the TXN_ID is 0.
414
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
415
+	 * If $expired is set to false, then only line items for active sessions will be returned.
416
+	 *
417
+	 * @param null $expired
418
+	 * @return EE_Base_Class[]|EE_Line_Item[]
419
+	 * @throws EE_Error
420
+	 * @throws InvalidArgumentException
421
+	 * @throws InvalidDataTypeException
422
+	 * @throws InvalidInterfaceException
423
+	 */
424
+	private function get_total_line_items_for_carts($expired = null)
425
+	{
426
+		$where_params = array(
427
+			'TXN_ID' => 0,
428
+			'LIN_type' => 'total',
429
+		);
430
+		if ($expired !== null) {
431
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
432
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
433
+				'EventEspresso\core\domain\values\session\SessionLifespan'
434
+			);
435
+			$where_params['LIN_timestamp'] = array(
436
+				$expired ? '<=' : '>',
437
+				$session_lifespan->expiration(),
438
+			);
439
+		}
440
+		return $this->get_all(array($where_params));
441
+	}
442
+
443
+
444
+	/**
445
+	 * Returns an array of ticket total line items where the TXN_ID is 0
446
+	 * AND the timestamp is older than the session lifespan.
447
+	 *
448
+	 * @param int $timestamp
449
+	 * @return EE_Base_Class[]|EE_Line_Item[]
450
+	 * @throws EE_Error
451
+	 * @throws InvalidArgumentException
452
+	 * @throws InvalidDataTypeException
453
+	 * @throws InvalidInterfaceException
454
+	 */
455
+	public function getTicketLineItemsForExpiredCarts($timestamp = 0)
456
+	{
457
+		if (! absint($timestamp)) {
458
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
459
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
460
+				'EventEspresso\core\domain\values\session\SessionLifespan'
461
+			);
462
+			$timestamp = $session_lifespan->expiration();
463
+		}
464
+		return $this->get_all(
465
+			array(
466
+				array(
467
+					'TXN_ID'        => 0,
468
+					'OBJ_type'      => 'Ticket',
469
+					'LIN_timestamp' => array('<=', $timestamp),
470
+				)
471
+			)
472
+		);
473
+	}
474 474
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Belongs_To_Relation.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -12,137 +12,137 @@
 block discarded – undo
12 12
 class EE_Belongs_To_Relation extends EE_Model_Relation_Base
13 13
 {
14 14
 
15
-    /**
16
-     * Object representing the relationship between two models. Belongs_To means that THIS model has the foreign key
17
-     * to the other model. This knows how to join the models,
18
-     * get related models across the relation, and add-and-remove the relationships.
19
-     *
20
-     * @param boolean $block_deletes                                For Belongs_To relations, this is set to FALSE by
21
-     *                                                              default. if there are related models across this
22
-     *                                                              relation, block (prevent and add an error) the
23
-     *                                                              deletion of this model
24
-     * @param string  $related_model_objects_deletion_error_message a customized error message on blocking deletes
25
-     *                                                              instead of the default
26
-     */
27
-    public function __construct($block_deletes = false, $related_model_objects_deletion_error_message = null)
28
-    {
29
-        parent::__construct($block_deletes, $related_model_objects_deletion_error_message);
30
-    }
15
+	/**
16
+	 * Object representing the relationship between two models. Belongs_To means that THIS model has the foreign key
17
+	 * to the other model. This knows how to join the models,
18
+	 * get related models across the relation, and add-and-remove the relationships.
19
+	 *
20
+	 * @param boolean $block_deletes                                For Belongs_To relations, this is set to FALSE by
21
+	 *                                                              default. if there are related models across this
22
+	 *                                                              relation, block (prevent and add an error) the
23
+	 *                                                              deletion of this model
24
+	 * @param string  $related_model_objects_deletion_error_message a customized error message on blocking deletes
25
+	 *                                                              instead of the default
26
+	 */
27
+	public function __construct($block_deletes = false, $related_model_objects_deletion_error_message = null)
28
+	{
29
+		parent::__construct($block_deletes, $related_model_objects_deletion_error_message);
30
+	}
31 31
 
32 32
 
33
-    /**
34
-     * get_join_statement
35
-     *
36
-     * @param string $model_relation_chain
37
-     * @return string
38
-     * @throws \EE_Error
39
-     */
40
-    public function get_join_statement($model_relation_chain)
41
-    {
42
-        // create the sql string like
43
-        $this_table_fk_field  = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
44
-        $other_table_pk_field = $this->get_other_model()->get_primary_key_field();
45
-        $this_table_alias     = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
46
-            $model_relation_chain,
47
-            $this->get_this_model()->get_this_model_name()
48
-        ) . $this_table_fk_field->get_table_alias();
49
-        $other_table_alias    = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
50
-            $model_relation_chain,
51
-            $this->get_other_model()->get_this_model_name()
52
-        ) . $other_table_pk_field->get_table_alias();
53
-        $other_table          = $this->get_other_model()->get_table_for_alias($other_table_alias);
54
-        return $this->_left_join(
55
-            $other_table,
56
-            $other_table_alias,
57
-            $other_table_pk_field->get_table_column(),
58
-            $this_table_alias,
59
-            $this_table_fk_field->get_table_column()
60
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
61
-    }
33
+	/**
34
+	 * get_join_statement
35
+	 *
36
+	 * @param string $model_relation_chain
37
+	 * @return string
38
+	 * @throws \EE_Error
39
+	 */
40
+	public function get_join_statement($model_relation_chain)
41
+	{
42
+		// create the sql string like
43
+		$this_table_fk_field  = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
44
+		$other_table_pk_field = $this->get_other_model()->get_primary_key_field();
45
+		$this_table_alias     = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
46
+			$model_relation_chain,
47
+			$this->get_this_model()->get_this_model_name()
48
+		) . $this_table_fk_field->get_table_alias();
49
+		$other_table_alias    = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
50
+			$model_relation_chain,
51
+			$this->get_other_model()->get_this_model_name()
52
+		) . $other_table_pk_field->get_table_alias();
53
+		$other_table          = $this->get_other_model()->get_table_for_alias($other_table_alias);
54
+		return $this->_left_join(
55
+			$other_table,
56
+			$other_table_alias,
57
+			$other_table_pk_field->get_table_column(),
58
+			$this_table_alias,
59
+			$this_table_fk_field->get_table_column()
60
+		) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
61
+	}
62 62
 
63 63
 
64
-    /**
65
-     * Sets this model object's foreign key to the other model object's primary key. Feel free to do this manually if
66
-     * you like.
67
-     *
68
-     * @param EE_Base_Class|int $this_obj_or_id
69
-     * @param EE_Base_Class|int $other_obj_or_id
70
-     * @param array             $extra_join_model_fields_n_values
71
-     * @return \EE_Base_Class
72
-     * @throws \EE_Error
73
-     */
74
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
-    {
76
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
78
-        // find the field on the other model which is a foreign key to this model
79
-        $fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
80
-        if ($this_model_obj->get($fk_on_this_model->get_name()) != $other_model_obj->ID()) {
81
-            // set that field on the other model to this model's ID
82
-            $this_model_obj->set($fk_on_this_model->get_name(), $other_model_obj->ID());
83
-            $this_model_obj->save();
84
-        }
85
-        return $other_model_obj;
86
-    }
64
+	/**
65
+	 * Sets this model object's foreign key to the other model object's primary key. Feel free to do this manually if
66
+	 * you like.
67
+	 *
68
+	 * @param EE_Base_Class|int $this_obj_or_id
69
+	 * @param EE_Base_Class|int $other_obj_or_id
70
+	 * @param array             $extra_join_model_fields_n_values
71
+	 * @return \EE_Base_Class
72
+	 * @throws \EE_Error
73
+	 */
74
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
+	{
76
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
78
+		// find the field on the other model which is a foreign key to this model
79
+		$fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
80
+		if ($this_model_obj->get($fk_on_this_model->get_name()) != $other_model_obj->ID()) {
81
+			// set that field on the other model to this model's ID
82
+			$this_model_obj->set($fk_on_this_model->get_name(), $other_model_obj->ID());
83
+			$this_model_obj->save();
84
+		}
85
+		return $other_model_obj;
86
+	}
87 87
 
88 88
 
89
-    /**
90
-     * Sets the this model object's foreign key to its default, instead of pointing to the other model object
91
-     *
92
-     * @param EE_Base_Class|int $this_obj_or_id
93
-     * @param EE_Base_Class|int $other_obj_or_id
94
-     * @param array             $where_query
95
-     * @return \EE_Base_Class
96
-     * @throws \EE_Error
97
-     */
98
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
99
-    {
100
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
101
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
102
-        // find the field on the other model which is a foreign key to this model
103
-        $fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
104
-        // set that field on the other model to this model's ID
105
-        $this_model_obj->set($fk_on_this_model->get_name(), null, true);
106
-        $this_model_obj->save();
107
-        return $other_model_obj;
108
-    }
89
+	/**
90
+	 * Sets the this model object's foreign key to its default, instead of pointing to the other model object
91
+	 *
92
+	 * @param EE_Base_Class|int $this_obj_or_id
93
+	 * @param EE_Base_Class|int $other_obj_or_id
94
+	 * @param array             $where_query
95
+	 * @return \EE_Base_Class
96
+	 * @throws \EE_Error
97
+	 */
98
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
99
+	{
100
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
101
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
102
+		// find the field on the other model which is a foreign key to this model
103
+		$fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
104
+		// set that field on the other model to this model's ID
105
+		$this_model_obj->set($fk_on_this_model->get_name(), null, true);
106
+		$this_model_obj->save();
107
+		return $other_model_obj;
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * Overrides parent so that we don't NEED to save the $model_object before getting the related objects.
113
-     *
114
-     * @param EE_Base_Class $model_obj_or_id
115
-     * @param array         $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
116
-     * @param boolean       $values_already_prepared_by_model_object @deprecated since 4.8.1
117
-     * @return EE_Base_Class[]
118
-     * @throws \EE_Error
119
-     */
120
-    public function get_all_related(
121
-        $model_obj_or_id,
122
-        $query_params = array(),
123
-        $values_already_prepared_by_model_object = false
124
-    ) {
125
-        if ($values_already_prepared_by_model_object !== false) {
126
-            EE_Error::doing_it_wrong(
127
-                'EE_Model_Relation_Base::get_all_related',
128
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
129
-                '4.8.1'
130
-            );
131
-        }
132
-        // get column on this model object which is a foreign key to the other model
133
-        $fk_field_obj = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
134
-        // get its value
135
-        if ($model_obj_or_id instanceof EE_Base_Class) {
136
-            $model_obj = $model_obj_or_id;
137
-        } else {
138
-            $model_obj = $this->get_this_model()->ensure_is_obj($model_obj_or_id);
139
-        }
140
-        $ID_value_on_other_model = $model_obj->get($fk_field_obj->get_name());
141
-        // get all where their PK matches that value
142
-        $query_params[0][ $this->get_other_model()->get_primary_key_field()->get_name() ] = $ID_value_on_other_model;
143
-        $query_params                                                                   = $this->_disable_default_where_conditions_on_query_param($query_params);
111
+	/**
112
+	 * Overrides parent so that we don't NEED to save the $model_object before getting the related objects.
113
+	 *
114
+	 * @param EE_Base_Class $model_obj_or_id
115
+	 * @param array         $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
116
+	 * @param boolean       $values_already_prepared_by_model_object @deprecated since 4.8.1
117
+	 * @return EE_Base_Class[]
118
+	 * @throws \EE_Error
119
+	 */
120
+	public function get_all_related(
121
+		$model_obj_or_id,
122
+		$query_params = array(),
123
+		$values_already_prepared_by_model_object = false
124
+	) {
125
+		if ($values_already_prepared_by_model_object !== false) {
126
+			EE_Error::doing_it_wrong(
127
+				'EE_Model_Relation_Base::get_all_related',
128
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
129
+				'4.8.1'
130
+			);
131
+		}
132
+		// get column on this model object which is a foreign key to the other model
133
+		$fk_field_obj = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
134
+		// get its value
135
+		if ($model_obj_or_id instanceof EE_Base_Class) {
136
+			$model_obj = $model_obj_or_id;
137
+		} else {
138
+			$model_obj = $this->get_this_model()->ensure_is_obj($model_obj_or_id);
139
+		}
140
+		$ID_value_on_other_model = $model_obj->get($fk_field_obj->get_name());
141
+		// get all where their PK matches that value
142
+		$query_params[0][ $this->get_other_model()->get_primary_key_field()->get_name() ] = $ID_value_on_other_model;
143
+		$query_params                                                                   = $this->_disable_default_where_conditions_on_query_param($query_params);
144 144
 //      echo '$query_params';
145 145
 //      var_dump($query_params);
146
-        return $this->get_other_model()->get_all($query_params);
147
-    }
146
+		return $this->get_other_model()->get_all($query_params);
147
+	}
148 148
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Has_Many_Revision_Relation.php 1 patch
Indentation   +296 added lines, -296 removed lines patch added patch discarded remove patch
@@ -12,303 +12,303 @@
 block discarded – undo
12 12
 {
13 13
 
14 14
 
15
-    /**
16
-     * The Foreign key on the model that acts as the PRIMARY KEY used in special autosave handling where we query for
17
-     * autosaves (or the Foreign key on other models in relations pointing to this models primary key which is this
18
-     * value).  The _primary_cpt_field is what is equivalent to the post_id field on a cpt join.
19
-     *
20
-     * @var string
21
-     */
22
-    private $_primary_cpt_field;
23
-
24
-
25
-    /**
26
-     * This is what field serves as the "parent" column that is linked with whatever the main model's calling this
27
-     * relation has as a primary key.  In other words EEM_Event has 'Datetime' => new
28
-     * EE_Has_Many_Revision_Relation('EVT_ID', 'DTT_parent').  That means that in the EEM_Datetime model the
29
-     * 'DTT_Parent' field is related to the 'DTT_ID' primary key field (in the same model) because 'DTT_ID' is the
30
-     * primary key in the other model (EEM_Datetime).
31
-     *
32
-     * @var string
33
-     */
34
-    private $_parent_pk_relation_field;
35
-
36
-
37
-    /**
38
-     * Object representing the relationship between two models. Has_Many_Relations are where the OTHER model has the
39
-     * foreign key this model. IE, there can be many other model objects related to one of this model's objects (but
40
-     * NOT through a JOIN table, which is the case for EE_HABTM_Relations). This knows how to join the models, get
41
-     * related models across the relation, and add-and-remove the relationships.
42
-     *
43
-     * @param string  $primary_cpt_field             See property description for details
44
-     * @param string  $parent_pk_relation_field      This is the field that is "connected" to the $primary_cpt_field.
45
-     *                                               See property desc for details.
46
-     * @param boolean $block_deletes                 For this type of relation, we block by default. If there are
47
-     *                                               related models across this relation, block (prevent and add an
48
-     *                                               error) the deletion of this model
49
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
50
-     *                                               default
51
-     */
52
-    public function __construct(
53
-        $primary_cpt_field,
54
-        $parent_pk_relation_field,
55
-        $block_deletes = true,
56
-        $blocking_delete_error_message = null
57
-    ) {
58
-        $this->_primary_cpt_field        = $primary_cpt_field;
59
-        $this->_parent_pk_relation_field = $parent_pk_relation_field;
60
-        parent::__construct($block_deletes, $blocking_delete_error_message);
61
-    }
62
-
63
-
64
-    /**
65
-     * Sets the other model object's foreign key to this model object's primary key. Feel free to do this manually if
66
-     * you like.
67
-     *
68
-     * @param EE_Base_Class|int $this_obj_or_id
69
-     * @param EE_Base_Class|int $other_obj_or_id
70
-     * @param array             $extra_join_model_fields_n_values
71
-     * @return \EE_Base_Class
72
-     * @throws \EE_Error
73
-     */
74
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
-    {
76
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
78
-
79
-        // handle possible revisions
80
-        $other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj);
81
-
82
-        // if is array, then we've already done the add_relation so let's get out
83
-        if (is_array($other_model_obj)) {
84
-            return $other_model_obj[0];
85
-        }
86
-        // find the field on the other model which is a foreign key to this model
87
-        $fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
88
-        // set that field on the other model to this model's ID
89
-        $other_model_obj->set($fk_field_on_other_model->get_name(), $this_model_obj->ID());
90
-        $other_model_obj->save();
91
-        return $other_model_obj;
92
-    }
93
-
94
-
95
-    /**
96
-     * Sets the other model object's foreign key to its default, instead of pointing to this model object
97
-     *
98
-     * @param EE_Base_Class|int $this_obj_or_id
99
-     * @param EE_Base_Class|int $other_obj_or_id
100
-     * @param array             $where_query
101
-     * @return \EE_Base_Class
102
-     * @throws \EE_Error
103
-     */
104
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
105
-    {
106
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id);
107
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
108
-        // handle possible revisions
109
-        $other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj, true);
110
-
111
-
112
-        // if is array, then we've already done the add_relation so let's get out
113
-        if (is_array($other_model_obj)) {
114
-            return $other_model_obj[0];
115
-        }
116
-
117
-        // find the field on the other model which is a foreign key to this model
118
-        $fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
119
-
120
-
121
-        // set that field on the other model to this model's ID
122
-        if ($this->_blocking_delete) {
123
-            $other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
124
-            $other_model_obj->save();
125
-        } else {
126
-            $other_model_obj->delete();
127
-            $other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
128
-            return $other_model_obj;
129
-        }
130
-        return $other_model_obj;
131
-    }
132
-
133
-
134
-    /**
135
-     * This is identical to EE_Model_Relation->get_all_related() except we're going handle special autosave conditions
136
-     * in here.
137
-     *
138
-     * @param  EE_Base_Class|int $model_object_or_id
139
-     * @param  array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
140
-     * @param  boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
141
-     * @return EE_Base_Class[]
142
-     * @throws \EE_Error
143
-     */
144
-    public function get_all_related(
145
-        $model_object_or_id,
146
-        $query_params = array(),
147
-        $values_already_prepared_by_model_object = false
148
-    ) {
149
-        if ($values_already_prepared_by_model_object !== false) {
150
-            EE_Error::doing_it_wrong(
151
-                'EE_Model_Relation_Base::get_all_related',
152
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
153
-                '4.8.1'
154
-            );
155
-        }
156
-
157
-        // if this is an autosave then we're going to get things differently
158
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
159
-            return $this->_do_autosave_get_all($model_object_or_id, $query_params);
160
-        }
161
-
162
-        return parent::get_all_related($model_object_or_id, $query_params);
163
-    }
164
-
165
-
166
-    /**
167
-     * If we're in the midst of an autosave then we're going to do things a bit differently than the usual
168
-     * get_all_related (commenting within).  For description of params see the get_all_related() comments
169
-     *
170
-     * @access protected
171
-     * @param      $model_object_or_id
172
-     * @param      $query_params
173
-     * @param bool $deprecated
174
-     * @return \EE_Base_Class[]
175
-     * @throws \EE_Error
176
-     */
177
-    protected function _do_autosave_get_all($model_object_or_id, $query_params, $deprecated = false)
178
-    {
179
-
180
-        // first we check if the post_id for the incoming query is for an autosave.  If it isn't that's what we want!
181
-        $model_object_id = $this->_get_model_object_id($model_object_or_id);
182
-
183
-        $autosave  = wp_get_post_autosave($model_object_id);
184
-        $id_to_use = $autosave ? $autosave->ID : $model_object_id;
185
-
186
-        $autosave_relations = parent::get_all_related($id_to_use, $query_params);
187
-        $parent_ids         = $parents = array();
188
-        $return_objs        = array();
189
-
190
-        // k this is where things differ because NOW what we're going to do is get the PARENTS for the get all related (and we'll also start setting up the return_objs array containing related that DON'T have parent ids, for those that DON'T have parents to merge with our returned objects);
191
-        foreach ($autosave_relations as $a_r) {
192
-            $pid = $a_r->parent();
193
-            if (! empty($pid)) {
194
-                $parent_ids[] = $pid;
195
-            } else {
196
-                $return_objs[] = $a_r;
197
-            }
198
-        }
199
-
200
-        // we have to make sure we also include the ORIGINAL values
201
-        $originals = parent::get_all_related($model_object_or_id, $query_params);
202
-
203
-        // merge $originals with $return_objs
204
-        if ($originals) {
205
-            $return_objs = array_merge($originals, $return_objs);
206
-        }
207
-
208
-        // now we setup the query to get all the parents
209
-        if (! empty($parent_ids)) {
210
-            $query_param_where_this_model_pk                  = $this->get_this_model()->get_this_model_name() . "." . $this->get_this_model()->get_primary_key_field()->get_name();
211
-            $query_param[0][ $query_param_where_this_model_pk ] = array('IN', $parent_ids);
212
-            $parents                                          = $this->get_other_model()->get_all($query_params);
213
-        }
214
-
215
-        // var_dump($parents);
216
-
217
-
218
-        // now merge parents with our current $return_objs and send back
219
-        return array_merge($parents, $return_objs);
220
-    }
221
-
222
-
223
-    /**
224
-     * Basically this method gets called to verify if the incoming object needs to be manipulated somewhat because it
225
-     * is a revision save.  If so, then we change things before sending back.  We also do verifications when this IS
226
-     * NOT an revision because we always need to make sure that the autosave/revision has parent recorded (which is
227
-     * sometime delayed if the object is created/saved first by the autosave)
228
-     *
229
-     * @param  EE_Base_Class $this_obj
230
-     * @param  EE_Base_Class $other_obj
231
-     * @param  boolean       $remove_relation Indicates whether we're doing a remove_relation or add_relation.
232
-     * @return EE_Base_Class. ($other_obj);
233
-     * @throws \EE_Error
234
-     */
235
-    protected function _check_for_revision($this_obj, $other_obj, $remove_relation = false)
236
-    {
237
-        $pk_on_related_model = $this->get_other_model()->get_primary_key_field()->get_name();
238
-        // now we need to determine if we're in a WP revision save cause if we are we need to do some special handling
239
-        if ($this_obj->post_type() === 'revision') {
240
-            // first if $other_obj fk = this_obj pk then we know that this is a pk object, let's make sure there is a matching set for the autosave if there is then we save over it, if there isn't then we need to create a new one.
241
-            $parent_evt_id = $this_obj->parent();
242
-            /*var_dump($parent_evt_id);
15
+	/**
16
+	 * The Foreign key on the model that acts as the PRIMARY KEY used in special autosave handling where we query for
17
+	 * autosaves (or the Foreign key on other models in relations pointing to this models primary key which is this
18
+	 * value).  The _primary_cpt_field is what is equivalent to the post_id field on a cpt join.
19
+	 *
20
+	 * @var string
21
+	 */
22
+	private $_primary_cpt_field;
23
+
24
+
25
+	/**
26
+	 * This is what field serves as the "parent" column that is linked with whatever the main model's calling this
27
+	 * relation has as a primary key.  In other words EEM_Event has 'Datetime' => new
28
+	 * EE_Has_Many_Revision_Relation('EVT_ID', 'DTT_parent').  That means that in the EEM_Datetime model the
29
+	 * 'DTT_Parent' field is related to the 'DTT_ID' primary key field (in the same model) because 'DTT_ID' is the
30
+	 * primary key in the other model (EEM_Datetime).
31
+	 *
32
+	 * @var string
33
+	 */
34
+	private $_parent_pk_relation_field;
35
+
36
+
37
+	/**
38
+	 * Object representing the relationship between two models. Has_Many_Relations are where the OTHER model has the
39
+	 * foreign key this model. IE, there can be many other model objects related to one of this model's objects (but
40
+	 * NOT through a JOIN table, which is the case for EE_HABTM_Relations). This knows how to join the models, get
41
+	 * related models across the relation, and add-and-remove the relationships.
42
+	 *
43
+	 * @param string  $primary_cpt_field             See property description for details
44
+	 * @param string  $parent_pk_relation_field      This is the field that is "connected" to the $primary_cpt_field.
45
+	 *                                               See property desc for details.
46
+	 * @param boolean $block_deletes                 For this type of relation, we block by default. If there are
47
+	 *                                               related models across this relation, block (prevent and add an
48
+	 *                                               error) the deletion of this model
49
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
50
+	 *                                               default
51
+	 */
52
+	public function __construct(
53
+		$primary_cpt_field,
54
+		$parent_pk_relation_field,
55
+		$block_deletes = true,
56
+		$blocking_delete_error_message = null
57
+	) {
58
+		$this->_primary_cpt_field        = $primary_cpt_field;
59
+		$this->_parent_pk_relation_field = $parent_pk_relation_field;
60
+		parent::__construct($block_deletes, $blocking_delete_error_message);
61
+	}
62
+
63
+
64
+	/**
65
+	 * Sets the other model object's foreign key to this model object's primary key. Feel free to do this manually if
66
+	 * you like.
67
+	 *
68
+	 * @param EE_Base_Class|int $this_obj_or_id
69
+	 * @param EE_Base_Class|int $other_obj_or_id
70
+	 * @param array             $extra_join_model_fields_n_values
71
+	 * @return \EE_Base_Class
72
+	 * @throws \EE_Error
73
+	 */
74
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
+	{
76
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
78
+
79
+		// handle possible revisions
80
+		$other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj);
81
+
82
+		// if is array, then we've already done the add_relation so let's get out
83
+		if (is_array($other_model_obj)) {
84
+			return $other_model_obj[0];
85
+		}
86
+		// find the field on the other model which is a foreign key to this model
87
+		$fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
88
+		// set that field on the other model to this model's ID
89
+		$other_model_obj->set($fk_field_on_other_model->get_name(), $this_model_obj->ID());
90
+		$other_model_obj->save();
91
+		return $other_model_obj;
92
+	}
93
+
94
+
95
+	/**
96
+	 * Sets the other model object's foreign key to its default, instead of pointing to this model object
97
+	 *
98
+	 * @param EE_Base_Class|int $this_obj_or_id
99
+	 * @param EE_Base_Class|int $other_obj_or_id
100
+	 * @param array             $where_query
101
+	 * @return \EE_Base_Class
102
+	 * @throws \EE_Error
103
+	 */
104
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
105
+	{
106
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id);
107
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
108
+		// handle possible revisions
109
+		$other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj, true);
110
+
111
+
112
+		// if is array, then we've already done the add_relation so let's get out
113
+		if (is_array($other_model_obj)) {
114
+			return $other_model_obj[0];
115
+		}
116
+
117
+		// find the field on the other model which is a foreign key to this model
118
+		$fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
119
+
120
+
121
+		// set that field on the other model to this model's ID
122
+		if ($this->_blocking_delete) {
123
+			$other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
124
+			$other_model_obj->save();
125
+		} else {
126
+			$other_model_obj->delete();
127
+			$other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
128
+			return $other_model_obj;
129
+		}
130
+		return $other_model_obj;
131
+	}
132
+
133
+
134
+	/**
135
+	 * This is identical to EE_Model_Relation->get_all_related() except we're going handle special autosave conditions
136
+	 * in here.
137
+	 *
138
+	 * @param  EE_Base_Class|int $model_object_or_id
139
+	 * @param  array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
140
+	 * @param  boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
141
+	 * @return EE_Base_Class[]
142
+	 * @throws \EE_Error
143
+	 */
144
+	public function get_all_related(
145
+		$model_object_or_id,
146
+		$query_params = array(),
147
+		$values_already_prepared_by_model_object = false
148
+	) {
149
+		if ($values_already_prepared_by_model_object !== false) {
150
+			EE_Error::doing_it_wrong(
151
+				'EE_Model_Relation_Base::get_all_related',
152
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
153
+				'4.8.1'
154
+			);
155
+		}
156
+
157
+		// if this is an autosave then we're going to get things differently
158
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
159
+			return $this->_do_autosave_get_all($model_object_or_id, $query_params);
160
+		}
161
+
162
+		return parent::get_all_related($model_object_or_id, $query_params);
163
+	}
164
+
165
+
166
+	/**
167
+	 * If we're in the midst of an autosave then we're going to do things a bit differently than the usual
168
+	 * get_all_related (commenting within).  For description of params see the get_all_related() comments
169
+	 *
170
+	 * @access protected
171
+	 * @param      $model_object_or_id
172
+	 * @param      $query_params
173
+	 * @param bool $deprecated
174
+	 * @return \EE_Base_Class[]
175
+	 * @throws \EE_Error
176
+	 */
177
+	protected function _do_autosave_get_all($model_object_or_id, $query_params, $deprecated = false)
178
+	{
179
+
180
+		// first we check if the post_id for the incoming query is for an autosave.  If it isn't that's what we want!
181
+		$model_object_id = $this->_get_model_object_id($model_object_or_id);
182
+
183
+		$autosave  = wp_get_post_autosave($model_object_id);
184
+		$id_to_use = $autosave ? $autosave->ID : $model_object_id;
185
+
186
+		$autosave_relations = parent::get_all_related($id_to_use, $query_params);
187
+		$parent_ids         = $parents = array();
188
+		$return_objs        = array();
189
+
190
+		// k this is where things differ because NOW what we're going to do is get the PARENTS for the get all related (and we'll also start setting up the return_objs array containing related that DON'T have parent ids, for those that DON'T have parents to merge with our returned objects);
191
+		foreach ($autosave_relations as $a_r) {
192
+			$pid = $a_r->parent();
193
+			if (! empty($pid)) {
194
+				$parent_ids[] = $pid;
195
+			} else {
196
+				$return_objs[] = $a_r;
197
+			}
198
+		}
199
+
200
+		// we have to make sure we also include the ORIGINAL values
201
+		$originals = parent::get_all_related($model_object_or_id, $query_params);
202
+
203
+		// merge $originals with $return_objs
204
+		if ($originals) {
205
+			$return_objs = array_merge($originals, $return_objs);
206
+		}
207
+
208
+		// now we setup the query to get all the parents
209
+		if (! empty($parent_ids)) {
210
+			$query_param_where_this_model_pk                  = $this->get_this_model()->get_this_model_name() . "." . $this->get_this_model()->get_primary_key_field()->get_name();
211
+			$query_param[0][ $query_param_where_this_model_pk ] = array('IN', $parent_ids);
212
+			$parents                                          = $this->get_other_model()->get_all($query_params);
213
+		}
214
+
215
+		// var_dump($parents);
216
+
217
+
218
+		// now merge parents with our current $return_objs and send back
219
+		return array_merge($parents, $return_objs);
220
+	}
221
+
222
+
223
+	/**
224
+	 * Basically this method gets called to verify if the incoming object needs to be manipulated somewhat because it
225
+	 * is a revision save.  If so, then we change things before sending back.  We also do verifications when this IS
226
+	 * NOT an revision because we always need to make sure that the autosave/revision has parent recorded (which is
227
+	 * sometime delayed if the object is created/saved first by the autosave)
228
+	 *
229
+	 * @param  EE_Base_Class $this_obj
230
+	 * @param  EE_Base_Class $other_obj
231
+	 * @param  boolean       $remove_relation Indicates whether we're doing a remove_relation or add_relation.
232
+	 * @return EE_Base_Class. ($other_obj);
233
+	 * @throws \EE_Error
234
+	 */
235
+	protected function _check_for_revision($this_obj, $other_obj, $remove_relation = false)
236
+	{
237
+		$pk_on_related_model = $this->get_other_model()->get_primary_key_field()->get_name();
238
+		// now we need to determine if we're in a WP revision save cause if we are we need to do some special handling
239
+		if ($this_obj->post_type() === 'revision') {
240
+			// first if $other_obj fk = this_obj pk then we know that this is a pk object, let's make sure there is a matching set for the autosave if there is then we save over it, if there isn't then we need to create a new one.
241
+			$parent_evt_id = $this_obj->parent();
242
+			/*var_dump($parent_evt_id);
243 243
             var_dump($this_obj);
244 244
             var_dump($other_obj);/**/
245 245
 
246
-            if (! empty($parent_evt_id) && $parent_evt_id == $other_obj->get($this->_primary_cpt_field)) {
247
-                // let's do query on this objects model to see if the incoming pk value on the obj matches any parents in this objects table.
248
-                $has_parent_obj = $this->get_other_model()->get_one(array(
249
-                    array(
250
-                        $this->_parent_pk_relation_field => $other_obj->ID(),
251
-                        $this->_primary_cpt_field        => $this_obj->ID(),
252
-                    ),
253
-                ));
254
-
255
-                if ($has_parent_obj) {
256
-                    // this makes sure the update on the current obj happens to the revision's row NOT the parent row.
257
-
258
-                    $other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
259
-                    $other_obj->set($pk_on_related_model, $has_parent_obj->ID());
260
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
261
-
262
-                    if (! $remove_relation) {
263
-                        $other_obj->save();
264
-                        return array($other_obj);
265
-                    } elseif ($remove_relation && ! $this->_blocking_delete) {
266
-                        $other_obj->delete();
267
-                        $other_obj->set($this->_parent_pk_relation_field, null, true);
268
-                        return array($other_obj);
269
-                    }
270
-                } else {
271
-                    $other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
272
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
273
-                    $other_obj->set(
274
-                        $pk_on_related_model,
275
-                        null,
276
-                        true
277
-                    ); // ensure we create a new row for the autosave with parent id the same as the incoming ID.
278
-                    $other_obj->save(); // make sure we insert.
279
-                    return array($other_obj);
280
-                }
281
-            }
282
-
283
-            // var_dump('what makes it here');
284
-            // var_dump($other_obj);
285
-            // the next possible condition is that the incoming other_model obj has a NULL pk which means it just gets saved (which in turn creates it)
286
-
287
-            // the last possible condition on a revision is that the incoming other_model object has a fk that == $this_obj pk which means we just return the $other obj and let it save as normal so we see the return at the bottom of this method.
288
-        } else {
289
-            // we only need to do the below IF this is not a remove relation
290
-            if (! $remove_relation) {
291
-                // okay this is is a normal update/save/remove so, let's make sure the other object is not a revision of the current object.
292
-                // the other object will likely NOT have the correct fk on it (which is the primary_cpt_field_mame) so we must retrieve from the db to get that first.
293
-                $existing_other_obj    = $this->get_other_model()->get_one_by_ID($other_obj->ID());
294
-                $potential_revision_id = is_object($existing_other_obj) ? $existing_other_obj->get($this->_primary_cpt_field) : null;
295
-
296
-                if ($parent_this_obj_id = wp_is_post_revision($potential_revision_id)) {
297
-                    // yes the OTHER object is linked to the revision of the parent, not the parent itself. That means we need to make the other_object an attachment of this_obj and then duplicate other_obj for the revision.
298
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
299
-                    $other_obj->save();
300
-
301
-                    // now create a new other_obj and fill with details from existing object
302
-                    $new_obj = $other_obj;
303
-                    $new_obj->set($this->_primary_cpt_field, $potential_revision_id);
304
-                    $new_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
305
-                    $new_obj->set($pk_on_related_model, null);
306
-                    $new_obj->save();
307
-                    return array($new_obj);
308
-                }
309
-            }
310
-        }
311
-
312
-        return $other_obj;
313
-    }
246
+			if (! empty($parent_evt_id) && $parent_evt_id == $other_obj->get($this->_primary_cpt_field)) {
247
+				// let's do query on this objects model to see if the incoming pk value on the obj matches any parents in this objects table.
248
+				$has_parent_obj = $this->get_other_model()->get_one(array(
249
+					array(
250
+						$this->_parent_pk_relation_field => $other_obj->ID(),
251
+						$this->_primary_cpt_field        => $this_obj->ID(),
252
+					),
253
+				));
254
+
255
+				if ($has_parent_obj) {
256
+					// this makes sure the update on the current obj happens to the revision's row NOT the parent row.
257
+
258
+					$other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
259
+					$other_obj->set($pk_on_related_model, $has_parent_obj->ID());
260
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
261
+
262
+					if (! $remove_relation) {
263
+						$other_obj->save();
264
+						return array($other_obj);
265
+					} elseif ($remove_relation && ! $this->_blocking_delete) {
266
+						$other_obj->delete();
267
+						$other_obj->set($this->_parent_pk_relation_field, null, true);
268
+						return array($other_obj);
269
+					}
270
+				} else {
271
+					$other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
272
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
273
+					$other_obj->set(
274
+						$pk_on_related_model,
275
+						null,
276
+						true
277
+					); // ensure we create a new row for the autosave with parent id the same as the incoming ID.
278
+					$other_obj->save(); // make sure we insert.
279
+					return array($other_obj);
280
+				}
281
+			}
282
+
283
+			// var_dump('what makes it here');
284
+			// var_dump($other_obj);
285
+			// the next possible condition is that the incoming other_model obj has a NULL pk which means it just gets saved (which in turn creates it)
286
+
287
+			// the last possible condition on a revision is that the incoming other_model object has a fk that == $this_obj pk which means we just return the $other obj and let it save as normal so we see the return at the bottom of this method.
288
+		} else {
289
+			// we only need to do the below IF this is not a remove relation
290
+			if (! $remove_relation) {
291
+				// okay this is is a normal update/save/remove so, let's make sure the other object is not a revision of the current object.
292
+				// the other object will likely NOT have the correct fk on it (which is the primary_cpt_field_mame) so we must retrieve from the db to get that first.
293
+				$existing_other_obj    = $this->get_other_model()->get_one_by_ID($other_obj->ID());
294
+				$potential_revision_id = is_object($existing_other_obj) ? $existing_other_obj->get($this->_primary_cpt_field) : null;
295
+
296
+				if ($parent_this_obj_id = wp_is_post_revision($potential_revision_id)) {
297
+					// yes the OTHER object is linked to the revision of the parent, not the parent itself. That means we need to make the other_object an attachment of this_obj and then duplicate other_obj for the revision.
298
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
299
+					$other_obj->save();
300
+
301
+					// now create a new other_obj and fill with details from existing object
302
+					$new_obj = $other_obj;
303
+					$new_obj->set($this->_primary_cpt_field, $potential_revision_id);
304
+					$new_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
305
+					$new_obj->set($pk_on_related_model, null);
306
+					$new_obj->save();
307
+					return array($new_obj);
308
+				}
309
+			}
310
+		}
311
+
312
+		return $other_obj;
313
+	}
314 314
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Model_Relation_Base.php 1 patch
Indentation   +497 added lines, -497 removed lines patch added patch discarded remove patch
@@ -15,502 +15,502 @@
 block discarded – undo
15 15
  */
16 16
 abstract class EE_Model_Relation_Base implements HasSchemaInterface
17 17
 {
18
-    /**
19
-     * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
-     *
21
-     * @var string eg Event, Question_Group, Registration
22
-     */
23
-    private $_this_model_name;
24
-    /**
25
-     * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
-     *
27
-     * @var string eg Event, Question_Group, Registration
28
-     */
29
-    private $_other_model_name;
30
-
31
-    /**
32
-     * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
-     * initiating model.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $_timezone;
38
-
39
-    /**
40
-     * If you try to delete "this_model", and there are related "other_models",
41
-     * and this isn't null, then abandon the deletion and add this warning.
42
-     * This effectively makes it impossible to delete "this_model" while there are
43
-     * related "other_models" along this relation.
44
-     *
45
-     * @var string (internationalized)
46
-     */
47
-    protected $_blocking_delete_error_message;
48
-
49
-    protected $_blocking_delete = false;
50
-
51
-    /**
52
-     * Object representing the relationship between two models. This knows how to join the models,
53
-     * get related models across the relation, and add-and-remove the relationships.
54
-     *
55
-     * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
-     *                                               and add an error) the deletion of this model
57
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
-     *                                               default
59
-     */
60
-    public function __construct($block_deletes, $blocking_delete_error_message)
61
-    {
62
-        $this->_blocking_delete               = $block_deletes;
63
-        $this->_blocking_delete_error_message = $blocking_delete_error_message;
64
-    }
65
-
66
-
67
-    /**
68
-     * @param $this_model_name
69
-     * @param $other_model_name
70
-     * @throws EE_Error
71
-     */
72
-    public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
-    {
74
-        $this->_this_model_name  = $this_model_name;
75
-        $this->_other_model_name = $other_model_name;
76
-        if (is_string($this->_blocking_delete)) {
77
-            throw new EE_Error(sprintf(
78
-                __(
79
-                    "When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
-                    "event_espresso"
81
-                ),
82
-                get_class($this),
83
-                $this_model_name,
84
-                $other_model_name,
85
-                $this->_blocking_delete
86
-            ));
87
-        }
88
-    }
89
-
90
-
91
-    /**
92
-     * Gets the model where this relation is defined.
93
-     *
94
-     * @return EEM_Base
95
-     */
96
-    public function get_this_model()
97
-    {
98
-        return $this->_get_model($this->_this_model_name);
99
-    }
100
-
101
-
102
-    /**
103
-     * Gets the model which this relation establishes the relation TO (ie,
104
-     * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
-     *
106
-     * @return EEM_Base
107
-     */
108
-    public function get_other_model()
109
-    {
110
-        return $this->_get_model($this->_other_model_name);
111
-    }
112
-
113
-
114
-    /**
115
-     * Internally used by get_this_model() and get_other_model()
116
-     *
117
-     * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
-     * @return EEM_Base
119
-     */
120
-    protected function _get_model($model_name)
121
-    {
122
-        $modelInstance = EE_Registry::instance()->load_model($model_name);
123
-        $modelInstance->set_timezone($this->_timezone);
124
-        return $modelInstance;
125
-    }
126
-
127
-
128
-    /**
129
-     * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
-     * timezone set correctly.
131
-     *
132
-     * @param string $timezone timezone to set.
133
-     */
134
-    public function set_timezone($timezone)
135
-    {
136
-        if ($timezone !== null) {
137
-            $this->_timezone = $timezone;
138
-        }
139
-    }
140
-
141
-
142
-    /**
143
-     * @param        $other_table
144
-     * @param        $other_table_alias
145
-     * @param        $other_table_column
146
-     * @param        $this_table_alias
147
-     * @param        $this_table_join_column
148
-     * @param string $extra_join_sql
149
-     * @return string
150
-     */
151
-    protected function _left_join(
152
-        $other_table,
153
-        $other_table_alias,
154
-        $other_table_column,
155
-        $this_table_alias,
156
-        $this_table_join_column,
157
-        $extra_join_sql = ''
158
-    ) {
159
-        return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
-    }
161
-
162
-
163
-    /**
164
-     * Gets all the model objects of type of other model related to $model_object,
165
-     * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
-     * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
-     * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
-     * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
-     *
170
-     * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
-     * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
-     * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
-     * @return EE_Base_Class[]
174
-     * @throws \EE_Error
175
-     */
176
-    public function get_all_related(
177
-        $model_object_or_id,
178
-        $query_params = array(),
179
-        $values_already_prepared_by_model_object = false
180
-    ) {
181
-        if ($values_already_prepared_by_model_object !== false) {
182
-            EE_Error::doing_it_wrong(
183
-                'EE_Model_Relation_Base::get_all_related',
184
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
-                '4.8.1'
186
-            );
187
-        }
188
-        $query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
-        $query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
-                                                             . "."
191
-                                                             . $this->get_this_model()->get_primary_key_field()->get_name();
192
-        $model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
-        $query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
-        return $this->get_other_model()->get_all($query_params);
195
-    }
196
-
197
-
198
-    /**
199
-     * Alters the $query_params to disable default where conditions, unless otherwise specified
200
-     *
201
-     * @param string $query_params
202
-     * @return array
203
-     */
204
-    protected function _disable_default_where_conditions_on_query_param($query_params)
205
-    {
206
-        if (! isset($query_params['default_where_conditions'])) {
207
-            $query_params['default_where_conditions'] = 'none';
208
-        }
209
-        return $query_params;
210
-    }
211
-
212
-
213
-    /**
214
-     * Deletes the related model objects which meet the query parameters. If no
215
-     * parameters are specified, then all related model objects will be deleted.
216
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
-     * model objects will only be soft-deleted.
218
-     *
219
-     * @param EE_Base_Class|int|string $model_object_or_id
220
-     * @param array                    $query_params
221
-     * @return int of how many related models got deleted
222
-     * @throws \EE_Error
223
-     */
224
-    public function delete_all_related($model_object_or_id, $query_params = array())
225
-    {
226
-        // for each thing we would delete,
227
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
-        // determine if it's blocked by anything else before it can be deleted
229
-        $deleted_count = 0;
230
-        foreach ($related_model_objects as $related_model_object) {
231
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
-                $related_model_object,
233
-                $model_object_or_id
234
-            );
235
-            /* @var $model_object_or_id EE_Base_Class */
236
-            if (! $delete_is_blocked) {
237
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
238
-                $related_model_object->delete();
239
-                $deleted_count++;
240
-            }
241
-        }
242
-        return $deleted_count;
243
-    }
244
-
245
-
246
-    /**
247
-     * Deletes the related model objects which meet the query parameters. If no
248
-     * parameters are specified, then all related model objects will be deleted.
249
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
-     * model objects will only be soft-deleted.
251
-     *
252
-     * @param EE_Base_Class|int|string $model_object_or_id
253
-     * @param array                    $query_params
254
-     * @return int of how many related models got deleted
255
-     * @throws \EE_Error
256
-     */
257
-    public function delete_related_permanently($model_object_or_id, $query_params = array())
258
-    {
259
-        // for each thing we would delete,
260
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
-        // determine if it's blocked by anything else before it can be deleted
262
-        $deleted_count = 0;
263
-        foreach ($related_model_objects as $related_model_object) {
264
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
-                $related_model_object,
266
-                $model_object_or_id
267
-            );
268
-            /* @var $model_object_or_id EE_Base_Class */
269
-            if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
271
-                $deleted_count++;
272
-                if (! $delete_is_blocked) {
273
-                    $related_model_object->delete_permanently();
274
-                } else {
275
-                    // delete is blocked
276
-                    // brent and darren, in this case, wanted to just soft delete it then
277
-                    $related_model_object->delete();
278
-                }
279
-            } else {
280
-                // its not a soft-deletable thing anyways. do the normal logic.
281
-                if (! $delete_is_blocked) {
282
-                    $this->remove_relation_to($model_object_or_id, $related_model_object);
283
-                    $related_model_object->delete();
284
-                    $deleted_count++;
285
-                }
286
-            }
287
-        }
288
-        return $deleted_count;
289
-    }
290
-
291
-
292
-    /**
293
-     * this just returns a model_object_id for incoming item that could be an object or id.
294
-     *
295
-     * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
-     * @throws EE_Error
297
-     * @return int
298
-     */
299
-    protected function _get_model_object_id($model_object_or_id)
300
-    {
301
-        $model_object_id = $model_object_or_id;
302
-        if ($model_object_or_id instanceof EE_Base_Class) {
303
-            $model_object_id = $model_object_or_id->ID();
304
-        }
305
-        if (! $model_object_id) {
306
-            throw new EE_Error(sprintf(
307
-                __(
308
-                    "Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
-                    "event_espresso"
310
-                ),
311
-                $this->get_other_model()->get_this_model_name(),
312
-                $this->get_this_model()->get_this_model_name()
313
-            ));
314
-        }
315
-        return $model_object_id;
316
-    }
317
-
318
-
319
-    /**
320
-     * Gets the SQL string for performing the join between this model and the other model.
321
-     *
322
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
-     * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
-     *                other_model_primary_table.fk" etc
325
-     */
326
-    abstract public function get_join_statement($model_relation_chain);
327
-
328
-
329
-    /**
330
-     * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
-     * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
-     * relationship only allows this model to be related to a single other model of this type)
333
-     *
334
-     * @param       $this_obj_or_id
335
-     * @param       $other_obj_or_id
336
-     * @param array $extra_join_model_fields_n_values
337
-     * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
-     *                        $other_obj_or_id)
339
-     */
340
-    abstract public function add_relation_to(
341
-        $this_obj_or_id,
342
-        $other_obj_or_id,
343
-        $extra_join_model_fields_n_values = array()
344
-    );
345
-
346
-
347
-    /**
348
-     * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
-     * model objects
350
-     *
351
-     * @param       $this_obj_or_id
352
-     * @param       $other_obj_or_id
353
-     * @param array $where_query
354
-     * @return bool
355
-     */
356
-    abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
-
358
-
359
-    /**
360
-     * Removes ALL relation instances for this relation obj
361
-     *
362
-     * @param EE_Base_Class|int $this_obj_or_id
363
-     * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
-     * @return EE_Base_Class[]
365
-     * @throws \EE_Error
366
-     */
367
-    public function remove_relations($this_obj_or_id, $where_query_param = array())
368
-    {
369
-        $related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
-        $objs_removed   = array();
371
-        foreach ($related_things as $related_thing) {
372
-            $objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
-        }
374
-        return $objs_removed;
375
-    }
376
-
377
-
378
-    /**
379
-     * If you aren't allowed to delete this model when there are related models across this
380
-     * relation object, return true. Otherwise, if you can delete this model even though
381
-     * related objects exist, returns false.
382
-     *
383
-     * @return boolean
384
-     */
385
-    public function block_delete_if_related_models_exist()
386
-    {
387
-        return $this->_blocking_delete;
388
-    }
389
-
390
-
391
-    /**
392
-     * Gets the error message to show
393
-     *
394
-     * @return string
395
-     */
396
-    public function get_deletion_error_message()
397
-    {
398
-        if ($this->_blocking_delete_error_message) {
399
-            return $this->_blocking_delete_error_message;
400
-        } else {
18
+	/**
19
+	 * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
+	 *
21
+	 * @var string eg Event, Question_Group, Registration
22
+	 */
23
+	private $_this_model_name;
24
+	/**
25
+	 * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
+	 *
27
+	 * @var string eg Event, Question_Group, Registration
28
+	 */
29
+	private $_other_model_name;
30
+
31
+	/**
32
+	 * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
+	 * initiating model.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $_timezone;
38
+
39
+	/**
40
+	 * If you try to delete "this_model", and there are related "other_models",
41
+	 * and this isn't null, then abandon the deletion and add this warning.
42
+	 * This effectively makes it impossible to delete "this_model" while there are
43
+	 * related "other_models" along this relation.
44
+	 *
45
+	 * @var string (internationalized)
46
+	 */
47
+	protected $_blocking_delete_error_message;
48
+
49
+	protected $_blocking_delete = false;
50
+
51
+	/**
52
+	 * Object representing the relationship between two models. This knows how to join the models,
53
+	 * get related models across the relation, and add-and-remove the relationships.
54
+	 *
55
+	 * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
+	 *                                               and add an error) the deletion of this model
57
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
+	 *                                               default
59
+	 */
60
+	public function __construct($block_deletes, $blocking_delete_error_message)
61
+	{
62
+		$this->_blocking_delete               = $block_deletes;
63
+		$this->_blocking_delete_error_message = $blocking_delete_error_message;
64
+	}
65
+
66
+
67
+	/**
68
+	 * @param $this_model_name
69
+	 * @param $other_model_name
70
+	 * @throws EE_Error
71
+	 */
72
+	public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
+	{
74
+		$this->_this_model_name  = $this_model_name;
75
+		$this->_other_model_name = $other_model_name;
76
+		if (is_string($this->_blocking_delete)) {
77
+			throw new EE_Error(sprintf(
78
+				__(
79
+					"When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
+					"event_espresso"
81
+				),
82
+				get_class($this),
83
+				$this_model_name,
84
+				$other_model_name,
85
+				$this->_blocking_delete
86
+			));
87
+		}
88
+	}
89
+
90
+
91
+	/**
92
+	 * Gets the model where this relation is defined.
93
+	 *
94
+	 * @return EEM_Base
95
+	 */
96
+	public function get_this_model()
97
+	{
98
+		return $this->_get_model($this->_this_model_name);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Gets the model which this relation establishes the relation TO (ie,
104
+	 * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
+	 *
106
+	 * @return EEM_Base
107
+	 */
108
+	public function get_other_model()
109
+	{
110
+		return $this->_get_model($this->_other_model_name);
111
+	}
112
+
113
+
114
+	/**
115
+	 * Internally used by get_this_model() and get_other_model()
116
+	 *
117
+	 * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
+	 * @return EEM_Base
119
+	 */
120
+	protected function _get_model($model_name)
121
+	{
122
+		$modelInstance = EE_Registry::instance()->load_model($model_name);
123
+		$modelInstance->set_timezone($this->_timezone);
124
+		return $modelInstance;
125
+	}
126
+
127
+
128
+	/**
129
+	 * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
+	 * timezone set correctly.
131
+	 *
132
+	 * @param string $timezone timezone to set.
133
+	 */
134
+	public function set_timezone($timezone)
135
+	{
136
+		if ($timezone !== null) {
137
+			$this->_timezone = $timezone;
138
+		}
139
+	}
140
+
141
+
142
+	/**
143
+	 * @param        $other_table
144
+	 * @param        $other_table_alias
145
+	 * @param        $other_table_column
146
+	 * @param        $this_table_alias
147
+	 * @param        $this_table_join_column
148
+	 * @param string $extra_join_sql
149
+	 * @return string
150
+	 */
151
+	protected function _left_join(
152
+		$other_table,
153
+		$other_table_alias,
154
+		$other_table_column,
155
+		$this_table_alias,
156
+		$this_table_join_column,
157
+		$extra_join_sql = ''
158
+	) {
159
+		return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
+	}
161
+
162
+
163
+	/**
164
+	 * Gets all the model objects of type of other model related to $model_object,
165
+	 * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
+	 * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
+	 * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
+	 * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
+	 *
170
+	 * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
+	 * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
+	 * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
+	 * @return EE_Base_Class[]
174
+	 * @throws \EE_Error
175
+	 */
176
+	public function get_all_related(
177
+		$model_object_or_id,
178
+		$query_params = array(),
179
+		$values_already_prepared_by_model_object = false
180
+	) {
181
+		if ($values_already_prepared_by_model_object !== false) {
182
+			EE_Error::doing_it_wrong(
183
+				'EE_Model_Relation_Base::get_all_related',
184
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
+				'4.8.1'
186
+			);
187
+		}
188
+		$query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
+		$query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
+															 . "."
191
+															 . $this->get_this_model()->get_primary_key_field()->get_name();
192
+		$model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
+		$query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
+		return $this->get_other_model()->get_all($query_params);
195
+	}
196
+
197
+
198
+	/**
199
+	 * Alters the $query_params to disable default where conditions, unless otherwise specified
200
+	 *
201
+	 * @param string $query_params
202
+	 * @return array
203
+	 */
204
+	protected function _disable_default_where_conditions_on_query_param($query_params)
205
+	{
206
+		if (! isset($query_params['default_where_conditions'])) {
207
+			$query_params['default_where_conditions'] = 'none';
208
+		}
209
+		return $query_params;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Deletes the related model objects which meet the query parameters. If no
215
+	 * parameters are specified, then all related model objects will be deleted.
216
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
+	 * model objects will only be soft-deleted.
218
+	 *
219
+	 * @param EE_Base_Class|int|string $model_object_or_id
220
+	 * @param array                    $query_params
221
+	 * @return int of how many related models got deleted
222
+	 * @throws \EE_Error
223
+	 */
224
+	public function delete_all_related($model_object_or_id, $query_params = array())
225
+	{
226
+		// for each thing we would delete,
227
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
+		// determine if it's blocked by anything else before it can be deleted
229
+		$deleted_count = 0;
230
+		foreach ($related_model_objects as $related_model_object) {
231
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
+				$related_model_object,
233
+				$model_object_or_id
234
+			);
235
+			/* @var $model_object_or_id EE_Base_Class */
236
+			if (! $delete_is_blocked) {
237
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
238
+				$related_model_object->delete();
239
+				$deleted_count++;
240
+			}
241
+		}
242
+		return $deleted_count;
243
+	}
244
+
245
+
246
+	/**
247
+	 * Deletes the related model objects which meet the query parameters. If no
248
+	 * parameters are specified, then all related model objects will be deleted.
249
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
+	 * model objects will only be soft-deleted.
251
+	 *
252
+	 * @param EE_Base_Class|int|string $model_object_or_id
253
+	 * @param array                    $query_params
254
+	 * @return int of how many related models got deleted
255
+	 * @throws \EE_Error
256
+	 */
257
+	public function delete_related_permanently($model_object_or_id, $query_params = array())
258
+	{
259
+		// for each thing we would delete,
260
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
+		// determine if it's blocked by anything else before it can be deleted
262
+		$deleted_count = 0;
263
+		foreach ($related_model_objects as $related_model_object) {
264
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
+				$related_model_object,
266
+				$model_object_or_id
267
+			);
268
+			/* @var $model_object_or_id EE_Base_Class */
269
+			if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
271
+				$deleted_count++;
272
+				if (! $delete_is_blocked) {
273
+					$related_model_object->delete_permanently();
274
+				} else {
275
+					// delete is blocked
276
+					// brent and darren, in this case, wanted to just soft delete it then
277
+					$related_model_object->delete();
278
+				}
279
+			} else {
280
+				// its not a soft-deletable thing anyways. do the normal logic.
281
+				if (! $delete_is_blocked) {
282
+					$this->remove_relation_to($model_object_or_id, $related_model_object);
283
+					$related_model_object->delete();
284
+					$deleted_count++;
285
+				}
286
+			}
287
+		}
288
+		return $deleted_count;
289
+	}
290
+
291
+
292
+	/**
293
+	 * this just returns a model_object_id for incoming item that could be an object or id.
294
+	 *
295
+	 * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
+	 * @throws EE_Error
297
+	 * @return int
298
+	 */
299
+	protected function _get_model_object_id($model_object_or_id)
300
+	{
301
+		$model_object_id = $model_object_or_id;
302
+		if ($model_object_or_id instanceof EE_Base_Class) {
303
+			$model_object_id = $model_object_or_id->ID();
304
+		}
305
+		if (! $model_object_id) {
306
+			throw new EE_Error(sprintf(
307
+				__(
308
+					"Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
+					"event_espresso"
310
+				),
311
+				$this->get_other_model()->get_this_model_name(),
312
+				$this->get_this_model()->get_this_model_name()
313
+			));
314
+		}
315
+		return $model_object_id;
316
+	}
317
+
318
+
319
+	/**
320
+	 * Gets the SQL string for performing the join between this model and the other model.
321
+	 *
322
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
+	 * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
+	 *                other_model_primary_table.fk" etc
325
+	 */
326
+	abstract public function get_join_statement($model_relation_chain);
327
+
328
+
329
+	/**
330
+	 * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
+	 * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
+	 * relationship only allows this model to be related to a single other model of this type)
333
+	 *
334
+	 * @param       $this_obj_or_id
335
+	 * @param       $other_obj_or_id
336
+	 * @param array $extra_join_model_fields_n_values
337
+	 * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
+	 *                        $other_obj_or_id)
339
+	 */
340
+	abstract public function add_relation_to(
341
+		$this_obj_or_id,
342
+		$other_obj_or_id,
343
+		$extra_join_model_fields_n_values = array()
344
+	);
345
+
346
+
347
+	/**
348
+	 * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
+	 * model objects
350
+	 *
351
+	 * @param       $this_obj_or_id
352
+	 * @param       $other_obj_or_id
353
+	 * @param array $where_query
354
+	 * @return bool
355
+	 */
356
+	abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
+
358
+
359
+	/**
360
+	 * Removes ALL relation instances for this relation obj
361
+	 *
362
+	 * @param EE_Base_Class|int $this_obj_or_id
363
+	 * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
+	 * @return EE_Base_Class[]
365
+	 * @throws \EE_Error
366
+	 */
367
+	public function remove_relations($this_obj_or_id, $where_query_param = array())
368
+	{
369
+		$related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
+		$objs_removed   = array();
371
+		foreach ($related_things as $related_thing) {
372
+			$objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
+		}
374
+		return $objs_removed;
375
+	}
376
+
377
+
378
+	/**
379
+	 * If you aren't allowed to delete this model when there are related models across this
380
+	 * relation object, return true. Otherwise, if you can delete this model even though
381
+	 * related objects exist, returns false.
382
+	 *
383
+	 * @return boolean
384
+	 */
385
+	public function block_delete_if_related_models_exist()
386
+	{
387
+		return $this->_blocking_delete;
388
+	}
389
+
390
+
391
+	/**
392
+	 * Gets the error message to show
393
+	 *
394
+	 * @return string
395
+	 */
396
+	public function get_deletion_error_message()
397
+	{
398
+		if ($this->_blocking_delete_error_message) {
399
+			return $this->_blocking_delete_error_message;
400
+		} else {
401 401
 //          return sprintf(__('Cannot delete %1$s when there are related %2$s', "event_espresso"),$this->get_this_model()->item_name(2),$this->get_other_model()->item_name(2));
402
-            return sprintf(
403
-                __(
404
-                    'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
-                    "event_espresso"
406
-                ),
407
-                $this->get_this_model()->item_name(1),
408
-                $this->get_other_model()->item_name(1),
409
-                $this->get_other_model()->item_name(2)
410
-            );
411
-        }
412
-    }
413
-
414
-    /**
415
-     * Returns whatever is set as the nicename for the object.
416
-     *
417
-     * @return string
418
-     */
419
-    public function getSchemaDescription()
420
-    {
421
-        $description = $this instanceof EE_Belongs_To_Relation
422
-            ? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
-            : esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
-        return sprintf(
425
-            $description,
426
-            $this->get_other_model()->get_this_model_name(),
427
-            $this->get_this_model()->get_this_model_name()
428
-        );
429
-    }
430
-
431
-    /**
432
-     * Returns whatever is set as the $_schema_type property for the object.
433
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
-     *
435
-     * @return string|array
436
-     */
437
-    public function getSchemaType()
438
-    {
439
-        return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
-    }
441
-
442
-    /**
443
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
-     * this method and return the properties for the schema.
445
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
446
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
-     *
448
-     * @return array
449
-     */
450
-    public function getSchemaProperties()
451
-    {
452
-        return array();
453
-    }
454
-
455
-    /**
456
-     * If a child class has enum values, they should override this method and provide a simple array
457
-     * of the enum values.
458
-     * The reason this is not a property on the class is because there may be filterable enum values that
459
-     * are set on the instantiated object that could be filtered after construct.
460
-     *
461
-     * @return array
462
-     */
463
-    public function getSchemaEnum()
464
-    {
465
-        return array();
466
-    }
467
-
468
-    /**
469
-     * This returns the value of the $_schema_format property on the object.
470
-     *
471
-     * @return string
472
-     */
473
-    public function getSchemaFormat()
474
-    {
475
-        return array();
476
-    }
477
-
478
-    /**
479
-     * This returns the value of the $_schema_readonly property on the object.
480
-     *
481
-     * @return bool
482
-     */
483
-    public function getSchemaReadonly()
484
-    {
485
-        return true;
486
-    }
487
-
488
-    /**
489
-     * This returns elements used to represent this field in the json schema.
490
-     *
491
-     * @link http://json-schema.org/
492
-     * @return array
493
-     */
494
-    public function getSchema()
495
-    {
496
-        $schema = array(
497
-            'description' => $this->getSchemaDescription(),
498
-            'type' => $this->getSchemaType(),
499
-            'relation' => true,
500
-            'relation_type' => get_class($this),
501
-            'readonly' => $this->getSchemaReadonly()
502
-        );
503
-
504
-        if ($this instanceof EE_HABTM_Relation) {
505
-            $schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
-        }
507
-
508
-        if ($this->getSchemaType() === 'array') {
509
-            $schema['items'] = array(
510
-                'type' => 'object'
511
-            );
512
-        }
513
-
514
-        return $schema;
515
-    }
402
+			return sprintf(
403
+				__(
404
+					'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
+					"event_espresso"
406
+				),
407
+				$this->get_this_model()->item_name(1),
408
+				$this->get_other_model()->item_name(1),
409
+				$this->get_other_model()->item_name(2)
410
+			);
411
+		}
412
+	}
413
+
414
+	/**
415
+	 * Returns whatever is set as the nicename for the object.
416
+	 *
417
+	 * @return string
418
+	 */
419
+	public function getSchemaDescription()
420
+	{
421
+		$description = $this instanceof EE_Belongs_To_Relation
422
+			? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
+			: esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
+		return sprintf(
425
+			$description,
426
+			$this->get_other_model()->get_this_model_name(),
427
+			$this->get_this_model()->get_this_model_name()
428
+		);
429
+	}
430
+
431
+	/**
432
+	 * Returns whatever is set as the $_schema_type property for the object.
433
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
+	 *
435
+	 * @return string|array
436
+	 */
437
+	public function getSchemaType()
438
+	{
439
+		return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
+	}
441
+
442
+	/**
443
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
+	 * this method and return the properties for the schema.
445
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
446
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
+	 *
448
+	 * @return array
449
+	 */
450
+	public function getSchemaProperties()
451
+	{
452
+		return array();
453
+	}
454
+
455
+	/**
456
+	 * If a child class has enum values, they should override this method and provide a simple array
457
+	 * of the enum values.
458
+	 * The reason this is not a property on the class is because there may be filterable enum values that
459
+	 * are set on the instantiated object that could be filtered after construct.
460
+	 *
461
+	 * @return array
462
+	 */
463
+	public function getSchemaEnum()
464
+	{
465
+		return array();
466
+	}
467
+
468
+	/**
469
+	 * This returns the value of the $_schema_format property on the object.
470
+	 *
471
+	 * @return string
472
+	 */
473
+	public function getSchemaFormat()
474
+	{
475
+		return array();
476
+	}
477
+
478
+	/**
479
+	 * This returns the value of the $_schema_readonly property on the object.
480
+	 *
481
+	 * @return bool
482
+	 */
483
+	public function getSchemaReadonly()
484
+	{
485
+		return true;
486
+	}
487
+
488
+	/**
489
+	 * This returns elements used to represent this field in the json schema.
490
+	 *
491
+	 * @link http://json-schema.org/
492
+	 * @return array
493
+	 */
494
+	public function getSchema()
495
+	{
496
+		$schema = array(
497
+			'description' => $this->getSchemaDescription(),
498
+			'type' => $this->getSchemaType(),
499
+			'relation' => true,
500
+			'relation_type' => get_class($this),
501
+			'readonly' => $this->getSchemaReadonly()
502
+		);
503
+
504
+		if ($this instanceof EE_HABTM_Relation) {
505
+			$schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
+		}
507
+
508
+		if ($this->getSchemaType() === 'array') {
509
+			$schema['items'] = array(
510
+				'type' => 'object'
511
+			);
512
+		}
513
+
514
+		return $schema;
515
+	}
516 516
 }
Please login to merge, or discard this patch.