Completed
Branch Gutenberg/create-ee_core-data-... (409285)
by
unknown
106:15 queued 93:05
created
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -781,7 +781,7 @@  discard block
 block discarded – undo
781 781
      * _get_transaction_and_cart_for_previous_visit
782 782
      *
783 783
      * @access private
784
-     * @return mixed EE_Transaction|NULL
784
+     * @return EE_Transaction|null EE_Transaction|NULL
785 785
      */
786 786
     private function _get_transaction_and_cart_for_previous_visit()
787 787
     {
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
      *    generates a new EE_Transaction object and adds it to the $_transaction property.
864 864
      *
865 865
      * @access private
866
-     * @return mixed EE_Transaction|NULL
866
+     * @return EE_Transaction|null EE_Transaction|NULL
867 867
      */
868 868
     private function _initialize_transaction()
869 869
     {
Please login to merge, or discard this patch.
Indentation   +1793 added lines, -1793 removed lines patch added patch discarded remove patch
@@ -15,1797 +15,1797 @@
 block discarded – undo
15 15
 class EED_Single_Page_Checkout extends EED_Module
16 16
 {
17 17
 
18
-    /**
19
-     * $_initialized - has the SPCO controller already been initialized ?
20
-     *
21
-     * @access private
22
-     * @var bool $_initialized
23
-     */
24
-    private static $_initialized = false;
25
-
26
-
27
-    /**
28
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
29
-     *
30
-     * @access private
31
-     * @var bool $_valid_checkout
32
-     */
33
-    private static $_checkout_verified = true;
34
-
35
-    /**
36
-     *    $_reg_steps_array - holds initial array of reg steps
37
-     *
38
-     * @access private
39
-     * @var array $_reg_steps_array
40
-     */
41
-    private static $_reg_steps_array = array();
42
-
43
-    /**
44
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
45
-     *
46
-     * @access public
47
-     * @var EE_Checkout $checkout
48
-     */
49
-    public $checkout;
50
-
51
-
52
-    /**
53
-     * @return EED_Module|EED_Single_Page_Checkout
54
-     */
55
-    public static function instance()
56
-    {
57
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
-        return parent::get_instance(__CLASS__);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return EE_CART
64
-     */
65
-    public function cart()
66
-    {
67
-        return $this->checkout->cart;
68
-    }
69
-
70
-
71
-    /**
72
-     * @return EE_Transaction
73
-     */
74
-    public function transaction()
75
-    {
76
-        return $this->checkout->transaction;
77
-    }
78
-
79
-
80
-    /**
81
-     *    set_hooks - for hooking into EE Core, other modules, etc
82
-     *
83
-     * @access    public
84
-     * @return    void
85
-     * @throws EE_Error
86
-     */
87
-    public static function set_hooks()
88
-    {
89
-        EED_Single_Page_Checkout::set_definitions();
90
-    }
91
-
92
-
93
-    /**
94
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
95
-     *
96
-     * @access    public
97
-     * @return    void
98
-     * @throws EE_Error
99
-     */
100
-    public static function set_hooks_admin()
101
-    {
102
-        EED_Single_Page_Checkout::set_definitions();
103
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
104
-            return;
105
-        }
106
-        // going to start an output buffer in case anything gets accidentally output
107
-        // that might disrupt our JSON response
108
-        ob_start();
109
-        EED_Single_Page_Checkout::load_request_handler();
110
-        EED_Single_Page_Checkout::load_reg_steps();
111
-        // set ajax hooks
112
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
113
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
114
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
115
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
116
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
117
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
118
-    }
119
-
120
-
121
-    /**
122
-     *    process ajax request
123
-     *
124
-     * @param string $ajax_action
125
-     * @throws EE_Error
126
-     */
127
-    public static function process_ajax_request($ajax_action)
128
-    {
129
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
130
-        EED_Single_Page_Checkout::instance()->_initialize();
131
-    }
132
-
133
-
134
-    /**
135
-     *    ajax display registration step
136
-     *
137
-     * @throws EE_Error
138
-     */
139
-    public static function display_reg_step()
140
-    {
141
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
142
-    }
143
-
144
-
145
-    /**
146
-     *    ajax process registration step
147
-     *
148
-     * @throws EE_Error
149
-     */
150
-    public static function process_reg_step()
151
-    {
152
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
153
-    }
154
-
155
-
156
-    /**
157
-     *    ajax process registration step
158
-     *
159
-     * @throws EE_Error
160
-     */
161
-    public static function update_reg_step()
162
-    {
163
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
164
-    }
165
-
166
-
167
-    /**
168
-     *   update_checkout
169
-     *
170
-     * @access public
171
-     * @return void
172
-     * @throws EE_Error
173
-     */
174
-    public static function update_checkout()
175
-    {
176
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
177
-    }
178
-
179
-
180
-    /**
181
-     *    load_request_handler
182
-     *
183
-     * @access    public
184
-     * @return    void
185
-     */
186
-    public static function load_request_handler()
187
-    {
188
-        // load core Request_Handler class
189
-        if (EE_Registry::instance()->REQ !== null) {
190
-            EE_Registry::instance()->load_core('Request_Handler');
191
-        }
192
-    }
193
-
194
-
195
-    /**
196
-     *    set_definitions
197
-     *
198
-     * @access    public
199
-     * @return    void
200
-     * @throws EE_Error
201
-     */
202
-    public static function set_definitions()
203
-    {
204
-        if (defined('SPCO_BASE_PATH')) {
205
-            return;
206
-        }
207
-        define(
208
-            'SPCO_BASE_PATH',
209
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
210
-        );
211
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
212
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
213
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
214
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
215
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
216
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
217
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
218
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
219
-        );
220
-    }
221
-
222
-
223
-    /**
224
-     * load_reg_steps
225
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
226
-     *
227
-     * @access    private
228
-     * @throws EE_Error
229
-     */
230
-    public static function load_reg_steps()
231
-    {
232
-        static $reg_steps_loaded = false;
233
-        if ($reg_steps_loaded) {
234
-            return;
235
-        }
236
-        // filter list of reg_steps
237
-        $reg_steps_to_load = (array) apply_filters(
238
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
239
-            EED_Single_Page_Checkout::get_reg_steps()
240
-        );
241
-        // sort by key (order)
242
-        ksort($reg_steps_to_load);
243
-        // loop through folders
244
-        foreach ($reg_steps_to_load as $order => $reg_step) {
245
-            // we need a
246
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
247
-                // copy over to the reg_steps_array
248
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
249
-                // register custom key route for each reg step
250
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
251
-                EE_Config::register_route(
252
-                    $reg_step['slug'],
253
-                    'EED_Single_Page_Checkout',
254
-                    'run',
255
-                    'step'
256
-                );
257
-                // add AJAX or other hooks
258
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
259
-                    // setup autoloaders if necessary
260
-                    if (! class_exists($reg_step['class_name'])) {
261
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
262
-                            $reg_step['file_path'],
263
-                            true
264
-                        );
265
-                    }
266
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
267
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
268
-                    }
269
-                }
270
-            }
271
-        }
272
-        $reg_steps_loaded = true;
273
-    }
274
-
275
-
276
-    /**
277
-     *    get_reg_steps
278
-     *
279
-     * @access    public
280
-     * @return    array
281
-     */
282
-    public static function get_reg_steps()
283
-    {
284
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
285
-        if (empty($reg_steps)) {
286
-            $reg_steps = array(
287
-                10  => array(
288
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
289
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
290
-                    'slug'       => 'attendee_information',
291
-                    'has_hooks'  => false,
292
-                ),
293
-                30  => array(
294
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
295
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
296
-                    'slug'       => 'payment_options',
297
-                    'has_hooks'  => true,
298
-                ),
299
-                999 => array(
300
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
301
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
302
-                    'slug'       => 'finalize_registration',
303
-                    'has_hooks'  => false,
304
-                ),
305
-            );
306
-        }
307
-        return $reg_steps;
308
-    }
309
-
310
-
311
-    /**
312
-     *    registration_checkout_for_admin
313
-     *
314
-     * @access    public
315
-     * @return    string
316
-     * @throws EE_Error
317
-     */
318
-    public static function registration_checkout_for_admin()
319
-    {
320
-        EED_Single_Page_Checkout::load_request_handler();
321
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
322
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
323
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
324
-        EED_Single_Page_Checkout::instance()->_initialize();
325
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
326
-        return EE_Registry::instance()->REQ->get_output();
327
-    }
328
-
329
-
330
-    /**
331
-     * process_registration_from_admin
332
-     *
333
-     * @access public
334
-     * @return \EE_Transaction
335
-     * @throws EE_Error
336
-     */
337
-    public static function process_registration_from_admin()
338
-    {
339
-        EED_Single_Page_Checkout::load_request_handler();
340
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
341
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
342
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
343
-        EED_Single_Page_Checkout::instance()->_initialize();
344
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
345
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
346
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
347
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
348
-                if ($final_reg_step->process_reg_step()) {
349
-                    $final_reg_step->set_completed();
350
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
351
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
352
-                }
353
-            }
354
-        }
355
-        return null;
356
-    }
357
-
358
-
359
-    /**
360
-     *    run
361
-     *
362
-     * @access    public
363
-     * @param WP_Query $WP_Query
364
-     * @return    void
365
-     * @throws EE_Error
366
-     */
367
-    public function run($WP_Query)
368
-    {
369
-        if ($WP_Query instanceof WP_Query
370
-            && $WP_Query->is_main_query()
371
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
372
-            && $this->_is_reg_checkout()
373
-        ) {
374
-            $this->_initialize();
375
-        }
376
-    }
377
-
378
-
379
-    /**
380
-     * determines whether current url matches reg page url
381
-     *
382
-     * @return bool
383
-     */
384
-    protected function _is_reg_checkout()
385
-    {
386
-        // get current permalink for reg page without any extra query args
387
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
388
-        // get request URI for current request, but without the scheme or host
389
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
390
-        $current_request_uri = html_entity_decode($current_request_uri);
391
-        // get array of query args from the current request URI
392
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
393
-        // grab page id if it is set
394
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
395
-        // and remove the page id from the query args (we will re-add it later)
396
-        unset($query_args['page_id']);
397
-        // now strip all query args from current request URI
398
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
399
-        // and re-add the page id if it was set
400
-        if ($page_id) {
401
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
402
-        }
403
-        // remove slashes and ?
404
-        $current_request_uri = trim($current_request_uri, '?/');
405
-        // is current request URI part of the known full reg page URL ?
406
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
407
-    }
408
-
409
-
410
-    /**
411
-     * @param WP_Query $wp_query
412
-     * @return    void
413
-     * @throws EE_Error
414
-     */
415
-    public static function init($wp_query)
416
-    {
417
-        EED_Single_Page_Checkout::instance()->run($wp_query);
418
-    }
419
-
420
-
421
-    /**
422
-     *    _initialize - initial module setup
423
-     *
424
-     * @access    private
425
-     * @throws EE_Error
426
-     * @return    void
427
-     */
428
-    private function _initialize()
429
-    {
430
-        // ensure SPCO doesn't run twice
431
-        if (EED_Single_Page_Checkout::$_initialized) {
432
-            return;
433
-        }
434
-        try {
435
-            EED_Single_Page_Checkout::load_reg_steps();
436
-            $this->_verify_session();
437
-            // setup the EE_Checkout object
438
-            $this->checkout = $this->_initialize_checkout();
439
-            // filter checkout
440
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
441
-            // get the $_GET
442
-            $this->_get_request_vars();
443
-            if ($this->_block_bots()) {
444
-                return;
445
-            }
446
-            // filter continue_reg
447
-            $this->checkout->continue_reg = apply_filters(
448
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
449
-                true,
450
-                $this->checkout
451
-            );
452
-            // load the reg steps array
453
-            if (! $this->_load_and_instantiate_reg_steps()) {
454
-                EED_Single_Page_Checkout::$_initialized = true;
455
-                return;
456
-            }
457
-            // set the current step
458
-            $this->checkout->set_current_step($this->checkout->step);
459
-            // and the next step
460
-            $this->checkout->set_next_step();
461
-            // verify that everything has been setup correctly
462
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
463
-                EED_Single_Page_Checkout::$_initialized = true;
464
-                return;
465
-            }
466
-            // lock the transaction
467
-            $this->checkout->transaction->lock();
468
-            // make sure all of our cached objects are added to their respective model entity mappers
469
-            $this->checkout->refresh_all_entities();
470
-            // set amount owing
471
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
472
-            // initialize each reg step, which gives them the chance to potentially alter the process
473
-            $this->_initialize_reg_steps();
474
-            // DEBUG LOG
475
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
476
-            // get reg form
477
-            if (! $this->_check_form_submission()) {
478
-                EED_Single_Page_Checkout::$_initialized = true;
479
-                return;
480
-            }
481
-            // checkout the action!!!
482
-            $this->_process_form_action();
483
-            // add some style and make it dance
484
-            $this->add_styles_and_scripts();
485
-            // kk... SPCO has successfully run
486
-            EED_Single_Page_Checkout::$_initialized = true;
487
-            // set no cache headers and constants
488
-            EE_System::do_not_cache();
489
-            // add anchor
490
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
491
-            // remove transaction lock
492
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
493
-        } catch (Exception $e) {
494
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
495
-        }
496
-    }
497
-
498
-
499
-    /**
500
-     *    _verify_session
501
-     * checks that the session is valid and not expired
502
-     *
503
-     * @access    private
504
-     * @throws EE_Error
505
-     */
506
-    private function _verify_session()
507
-    {
508
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
509
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
510
-        }
511
-        $clear_session_requested = filter_var(
512
-            EE_Registry::instance()->REQ->get('clear_session', false),
513
-            FILTER_VALIDATE_BOOLEAN
514
-        );
515
-        // is session still valid ?
516
-        if ($clear_session_requested
517
-            || (EE_Registry::instance()->SSN->expired()
518
-                && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
519
-            )
520
-        ) {
521
-            $this->checkout = new EE_Checkout();
522
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
523
-            // EE_Registry::instance()->SSN->reset_cart();
524
-            // EE_Registry::instance()->SSN->reset_checkout();
525
-            // EE_Registry::instance()->SSN->reset_transaction();
526
-            if (! $clear_session_requested) {
527
-                EE_Error::add_attention(
528
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
529
-                    __FILE__,
530
-                    __FUNCTION__,
531
-                    __LINE__
532
-                );
533
-            }
534
-            // EE_Registry::instance()->SSN->reset_expired();
535
-        }
536
-    }
537
-
538
-
539
-    /**
540
-     *    _initialize_checkout
541
-     * loads and instantiates EE_Checkout
542
-     *
543
-     * @access    private
544
-     * @throws EE_Error
545
-     * @return EE_Checkout
546
-     */
547
-    private function _initialize_checkout()
548
-    {
549
-        // look in session for existing checkout
550
-        /** @type EE_Checkout $checkout */
551
-        $checkout = EE_Registry::instance()->SSN->checkout();
552
-        // verify
553
-        if (! $checkout instanceof EE_Checkout) {
554
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
555
-            $checkout = EE_Registry::instance()->load_file(
556
-                SPCO_INC_PATH,
557
-                'EE_Checkout',
558
-                'class',
559
-                array(),
560
-                false
561
-            );
562
-        } else {
563
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
564
-                $this->unlock_transaction();
565
-                wp_safe_redirect($checkout->redirect_url);
566
-                exit();
567
-            }
568
-        }
569
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
570
-        // verify again
571
-        if (! $checkout instanceof EE_Checkout) {
572
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
573
-        }
574
-        // reset anything that needs a clean slate for each request
575
-        $checkout->reset_for_current_request();
576
-        return $checkout;
577
-    }
578
-
579
-
580
-    /**
581
-     *    _get_request_vars
582
-     *
583
-     * @access    private
584
-     * @return    void
585
-     * @throws EE_Error
586
-     */
587
-    private function _get_request_vars()
588
-    {
589
-        // load classes
590
-        EED_Single_Page_Checkout::load_request_handler();
591
-        // make sure this request is marked as belonging to EE
592
-        EE_Registry::instance()->REQ->set_espresso_page(true);
593
-        // which step is being requested ?
594
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
595
-        // which step is being edited ?
596
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
597
-        // and what we're doing on the current step
598
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
599
-        // timestamp
600
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
601
-        // returning to edit ?
602
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
603
-        // add reg url link to registration query params
604
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
605
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
606
-        }
607
-        // or some other kind of revisit ?
608
-        $this->checkout->revisit = filter_var(
609
-            EE_Registry::instance()->REQ->get('revisit', false),
610
-            FILTER_VALIDATE_BOOLEAN
611
-        );
612
-        // and whether or not to generate a reg form for this request
613
-        $this->checkout->generate_reg_form = filter_var(
614
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
615
-            FILTER_VALIDATE_BOOLEAN
616
-        );
617
-        // and whether or not to process a reg form submission for this request
618
-        $this->checkout->process_form_submission = filter_var(
619
-            EE_Registry::instance()->REQ->get(
620
-                'process_form_submission',
621
-                $this->checkout->action === 'process_reg_step'
622
-            ),
623
-            FILTER_VALIDATE_BOOLEAN
624
-        );
625
-        $this->checkout->process_form_submission = filter_var(
626
-            $this->checkout->action !== 'display_spco_reg_step'
627
-                ? $this->checkout->process_form_submission
628
-                : false,
629
-            FILTER_VALIDATE_BOOLEAN
630
-        );
631
-        // $this->_display_request_vars();
632
-    }
633
-
634
-
635
-    /**
636
-     *  _display_request_vars
637
-     *
638
-     * @access    protected
639
-     * @return    void
640
-     */
641
-    protected function _display_request_vars()
642
-    {
643
-        if (! WP_DEBUG) {
644
-            return;
645
-        }
646
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
647
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
648
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
649
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
650
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
651
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
652
-        EEH_Debug_Tools::printr(
653
-            $this->checkout->generate_reg_form,
654
-            '$this->checkout->generate_reg_form',
655
-            __FILE__,
656
-            __LINE__
657
-        );
658
-        EEH_Debug_Tools::printr(
659
-            $this->checkout->process_form_submission,
660
-            '$this->checkout->process_form_submission',
661
-            __FILE__,
662
-            __LINE__
663
-        );
664
-    }
665
-
666
-
667
-    /**
668
-     * _block_bots
669
-     * checks that the incoming request has either of the following set:
670
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
671
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
672
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
673
-     * then where you coming from man?
674
-     *
675
-     * @return boolean
676
-     */
677
-    private function _block_bots()
678
-    {
679
-        $invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
680
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
681
-            return true;
682
-        }
683
-        return false;
684
-    }
685
-
686
-
687
-    /**
688
-     *    _get_first_step
689
-     *  gets slug for first step in $_reg_steps_array
690
-     *
691
-     * @access    private
692
-     * @throws EE_Error
693
-     * @return    string
694
-     */
695
-    private function _get_first_step()
696
-    {
697
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
698
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
699
-    }
700
-
701
-
702
-    /**
703
-     * instantiates each reg step based on the loaded reg_steps array
704
-     *
705
-     * @return    bool
706
-     * @throws EE_Error
707
-     * @throws InvalidArgumentException
708
-     * @throws InvalidDataTypeException
709
-     * @throws InvalidInterfaceException
710
-     */
711
-    private function _load_and_instantiate_reg_steps()
712
-    {
713
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
714
-        // have reg_steps already been instantiated ?
715
-        if (empty($this->checkout->reg_steps)
716
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
717
-        ) {
718
-            // if not, then loop through raw reg steps array
719
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
720
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
721
-                    return false;
722
-                }
723
-            }
724
-            if (isset($this->checkout->reg_steps['registration_confirmation'])) {
725
-                // skip the registration_confirmation page ?
726
-                if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
727
-                    // just remove it from the reg steps array
728
-                    $this->checkout->remove_reg_step('registration_confirmation', false);
729
-                } elseif (EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
-                ) {
731
-                    // set the order to something big like 100
732
-                    $this->checkout->set_reg_step_order('registration_confirmation', 100);
733
-                }
734
-            }
735
-            // filter the array for good luck
736
-            $this->checkout->reg_steps = apply_filters(
737
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
738
-                $this->checkout->reg_steps
739
-            );
740
-            // finally re-sort based on the reg step class order properties
741
-            $this->checkout->sort_reg_steps();
742
-        } else {
743
-            foreach ($this->checkout->reg_steps as $reg_step) {
744
-                // set all current step stati to FALSE
745
-                $reg_step->set_is_current_step(false);
746
-            }
747
-        }
748
-        if (empty($this->checkout->reg_steps)) {
749
-            EE_Error::add_error(
750
-                __('No Reg Steps were loaded..', 'event_espresso'),
751
-                __FILE__,
752
-                __FUNCTION__,
753
-                __LINE__
754
-            );
755
-            return false;
756
-        }
757
-        // make reg step details available to JS
758
-        $this->checkout->set_reg_step_JSON_info();
759
-        return true;
760
-    }
761
-
762
-
763
-    /**
764
-     *     _load_and_instantiate_reg_step
765
-     *
766
-     * @access    private
767
-     * @param array $reg_step
768
-     * @param int   $order
769
-     * @return bool
770
-     */
771
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
772
-    {
773
-        // we need a file_path, class_name, and slug to add a reg step
774
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
775
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
776
-            if ($this->checkout->reg_url_link
777
-                && $this->checkout->step !== $reg_step['slug']
778
-                && $reg_step['slug'] !== 'finalize_registration'
779
-                // normally at this point we would NOT load the reg step, but this filter can change that
780
-                && apply_filters(
781
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
782
-                    true,
783
-                    $reg_step,
784
-                    $this->checkout
785
-                )
786
-            ) {
787
-                return true;
788
-            }
789
-            // instantiate step class using file path and class name
790
-            $reg_step_obj = EE_Registry::instance()->load_file(
791
-                $reg_step['file_path'],
792
-                $reg_step['class_name'],
793
-                'class',
794
-                $this->checkout,
795
-                false
796
-            );
797
-            // did we gets the goods ?
798
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
799
-                // set reg step order based on config
800
-                $reg_step_obj->set_order($order);
801
-                // add instantiated reg step object to the master reg steps array
802
-                $this->checkout->add_reg_step($reg_step_obj);
803
-            } else {
804
-                EE_Error::add_error(
805
-                    __('The current step could not be set.', 'event_espresso'),
806
-                    __FILE__,
807
-                    __FUNCTION__,
808
-                    __LINE__
809
-                );
810
-                return false;
811
-            }
812
-        } else {
813
-            if (WP_DEBUG) {
814
-                EE_Error::add_error(
815
-                    sprintf(
816
-                        __(
817
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
818
-                            'event_espresso'
819
-                        ),
820
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
821
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
822
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
823
-                        '<ul>',
824
-                        '<li>',
825
-                        '</li>',
826
-                        '</ul>'
827
-                    ),
828
-                    __FILE__,
829
-                    __FUNCTION__,
830
-                    __LINE__
831
-                );
832
-            }
833
-            return false;
834
-        }
835
-        return true;
836
-    }
837
-
838
-
839
-    /**
840
-     * _verify_transaction_and_get_registrations
841
-     *
842
-     * @access private
843
-     * @return bool
844
-     * @throws InvalidDataTypeException
845
-     * @throws InvalidEntityException
846
-     * @throws EE_Error
847
-     */
848
-    private function _verify_transaction_and_get_registrations()
849
-    {
850
-        // was there already a valid transaction in the checkout from the session ?
851
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
852
-            // get transaction from db or session
853
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
854
-                ? $this->_get_transaction_and_cart_for_previous_visit()
855
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
856
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
857
-                EE_Error::add_error(
858
-                    __(
859
-                        'Your Registration and Transaction information could not be retrieved from the db.',
860
-                        'event_espresso'
861
-                    ),
862
-                    __FILE__,
863
-                    __FUNCTION__,
864
-                    __LINE__
865
-                );
866
-                $this->checkout->transaction = EE_Transaction::new_instance();
867
-                // add some style and make it dance
868
-                $this->add_styles_and_scripts();
869
-                EED_Single_Page_Checkout::$_initialized = true;
870
-                return false;
871
-            }
872
-            // and the registrations for the transaction
873
-            $this->_get_registrations($this->checkout->transaction);
874
-        }
875
-        return true;
876
-    }
877
-
878
-
879
-    /**
880
-     * _get_transaction_and_cart_for_previous_visit
881
-     *
882
-     * @access private
883
-     * @return mixed EE_Transaction|NULL
884
-     */
885
-    private function _get_transaction_and_cart_for_previous_visit()
886
-    {
887
-        /** @var $TXN_model EEM_Transaction */
888
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
889
-        // because the reg_url_link is present in the request,
890
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
891
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
892
-        // verify transaction
893
-        if ($transaction instanceof EE_Transaction) {
894
-            // and get the cart that was used for that transaction
895
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
896
-            return $transaction;
897
-        }
898
-        EE_Error::add_error(
899
-            __('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
900
-            __FILE__,
901
-            __FUNCTION__,
902
-            __LINE__
903
-        );
904
-        return null;
905
-    }
906
-
907
-
908
-    /**
909
-     * _get_cart_for_transaction
910
-     *
911
-     * @access private
912
-     * @param EE_Transaction $transaction
913
-     * @return EE_Cart
914
-     */
915
-    private function _get_cart_for_transaction($transaction)
916
-    {
917
-        return $this->checkout->get_cart_for_transaction($transaction);
918
-    }
919
-
920
-
921
-    /**
922
-     * get_cart_for_transaction
923
-     *
924
-     * @access public
925
-     * @param EE_Transaction $transaction
926
-     * @return EE_Cart
927
-     */
928
-    public function get_cart_for_transaction(EE_Transaction $transaction)
929
-    {
930
-        return $this->checkout->get_cart_for_transaction($transaction);
931
-    }
932
-
933
-
934
-    /**
935
-     * _get_transaction_and_cart_for_current_session
936
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
937
-     *
938
-     * @access private
939
-     * @return EE_Transaction
940
-     * @throws EE_Error
941
-     */
942
-    private function _get_cart_for_current_session_and_setup_new_transaction()
943
-    {
944
-        //  if there's no transaction, then this is the FIRST visit to SPCO
945
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
946
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
947
-        // and then create a new transaction
948
-        $transaction = $this->_initialize_transaction();
949
-        // verify transaction
950
-        if ($transaction instanceof EE_Transaction) {
951
-            // save it so that we have an ID for other objects to use
952
-            $transaction->save();
953
-            // and save TXN data to the cart
954
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
955
-        } else {
956
-            EE_Error::add_error(
957
-                __('A Valid Transaction could not be initialized.', 'event_espresso'),
958
-                __FILE__,
959
-                __FUNCTION__,
960
-                __LINE__
961
-            );
962
-        }
963
-        return $transaction;
964
-    }
965
-
966
-
967
-    /**
968
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
969
-     *
970
-     * @access private
971
-     * @return mixed EE_Transaction|NULL
972
-     */
973
-    private function _initialize_transaction()
974
-    {
975
-        try {
976
-            // ensure cart totals have been calculated
977
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
978
-            // grab the cart grand total
979
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
980
-            // create new TXN
981
-            $transaction = EE_Transaction::new_instance(
982
-                array(
983
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
984
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
985
-                    'TXN_paid'      => 0,
986
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
987
-                )
988
-            );
989
-            // save it so that we have an ID for other objects to use
990
-            $transaction->save();
991
-            // set cron job for following up on TXNs after their session has expired
992
-            EE_Cron_Tasks::schedule_expired_transaction_check(
993
-                EE_Registry::instance()->SSN->expiration() + 1,
994
-                $transaction->ID()
995
-            );
996
-            return $transaction;
997
-        } catch (Exception $e) {
998
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
999
-        }
1000
-        return null;
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * _get_registrations
1006
-     *
1007
-     * @access private
1008
-     * @param EE_Transaction $transaction
1009
-     * @return void
1010
-     * @throws InvalidDataTypeException
1011
-     * @throws InvalidEntityException
1012
-     * @throws EE_Error
1013
-     */
1014
-    private function _get_registrations(EE_Transaction $transaction)
1015
-    {
1016
-        // first step: grab the registrants  { : o
1017
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1018
-        $this->checkout->total_ticket_count = count($registrations);
1019
-        // verify registrations have been set
1020
-        if (empty($registrations)) {
1021
-            // if no cached registrations, then check the db
1022
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1023
-            // still nothing ? well as long as this isn't a revisit
1024
-            if (empty($registrations) && ! $this->checkout->revisit) {
1025
-                // generate new registrations from scratch
1026
-                $registrations = $this->_initialize_registrations($transaction);
1027
-            }
1028
-        }
1029
-        // sort by their original registration order
1030
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1031
-        // then loop thru the array
1032
-        foreach ($registrations as $registration) {
1033
-            // verify each registration
1034
-            if ($registration instanceof EE_Registration) {
1035
-                // we display all attendee info for the primary registrant
1036
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1037
-                    && $registration->is_primary_registrant()
1038
-                ) {
1039
-                    $this->checkout->primary_revisit = true;
1040
-                    break;
1041
-                }
1042
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1043
-                    // but hide info if it doesn't belong to you
1044
-                    $transaction->clear_cache('Registration', $registration->ID());
1045
-                    $this->checkout->total_ticket_count--;
1046
-                }
1047
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1048
-            }
1049
-        }
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1055
-     *
1056
-     * @access private
1057
-     * @param EE_Transaction $transaction
1058
-     * @return    array
1059
-     * @throws InvalidDataTypeException
1060
-     * @throws InvalidEntityException
1061
-     * @throws EE_Error
1062
-     */
1063
-    private function _initialize_registrations(EE_Transaction $transaction)
1064
-    {
1065
-        $att_nmbr = 0;
1066
-        $registrations = array();
1067
-        if ($transaction instanceof EE_Transaction) {
1068
-            /** @type EE_Registration_Processor $registration_processor */
1069
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1070
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1071
-            // now let's add the cart items to the $transaction
1072
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1073
-                // do the following for each ticket of this type they selected
1074
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1075
-                    $att_nmbr++;
1076
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1077
-                    $CreateRegistrationCommand = EE_Registry::instance()->create(
1078
-                        'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1079
-                        array(
1080
-                            $transaction,
1081
-                            $line_item,
1082
-                            $att_nmbr,
1083
-                            $this->checkout->total_ticket_count,
1084
-                        )
1085
-                    );
1086
-                    // override capabilities for frontend registrations
1087
-                    if (! is_admin()) {
1088
-                        $CreateRegistrationCommand->setCapCheck(
1089
-                            new PublicCapabilities('', 'create_new_registration')
1090
-                        );
1091
-                    }
1092
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1093
-                    if (! $registration instanceof EE_Registration) {
1094
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1095
-                    }
1096
-                    $registrations[ $registration->ID() ] = $registration;
1097
-                }
1098
-            }
1099
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1100
-        }
1101
-        return $registrations;
1102
-    }
1103
-
1104
-
1105
-    /**
1106
-     * sorts registrations by REG_count
1107
-     *
1108
-     * @access public
1109
-     * @param EE_Registration $reg_A
1110
-     * @param EE_Registration $reg_B
1111
-     * @return int
1112
-     */
1113
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1114
-    {
1115
-        // this shouldn't ever happen within the same TXN, but oh well
1116
-        if ($reg_A->count() === $reg_B->count()) {
1117
-            return 0;
1118
-        }
1119
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     *    _final_verifications
1125
-     * just makes sure that everything is set up correctly before proceeding
1126
-     *
1127
-     * @access    private
1128
-     * @return    bool
1129
-     * @throws EE_Error
1130
-     */
1131
-    private function _final_verifications()
1132
-    {
1133
-        // filter checkout
1134
-        $this->checkout = apply_filters(
1135
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1136
-            $this->checkout
1137
-        );
1138
-        // verify that current step is still set correctly
1139
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1140
-            EE_Error::add_error(
1141
-                __(
1142
-                    'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1143
-                    'event_espresso'
1144
-                ),
1145
-                __FILE__,
1146
-                __FUNCTION__,
1147
-                __LINE__
1148
-            );
1149
-            return false;
1150
-        }
1151
-        // if returning to SPCO, then verify that primary registrant is set
1152
-        if (! empty($this->checkout->reg_url_link)) {
1153
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1154
-            if (! $valid_registrant instanceof EE_Registration) {
1155
-                EE_Error::add_error(
1156
-                    __(
1157
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1158
-                        'event_espresso'
1159
-                    ),
1160
-                    __FILE__,
1161
-                    __FUNCTION__,
1162
-                    __LINE__
1163
-                );
1164
-                return false;
1165
-            }
1166
-            $valid_registrant = null;
1167
-            foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1168
-                if ($registration instanceof EE_Registration
1169
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1170
-                ) {
1171
-                    $valid_registrant = $registration;
1172
-                }
1173
-            }
1174
-            if (! $valid_registrant instanceof EE_Registration) {
1175
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1176
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1177
-                    // clear the session, mark the checkout as unverified, and try again
1178
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1179
-                    EED_Single_Page_Checkout::$_initialized = false;
1180
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1181
-                    $this->_initialize();
1182
-                    EE_Error::reset_notices();
1183
-                    return false;
1184
-                }
1185
-                EE_Error::add_error(
1186
-                    __(
1187
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1188
-                        'event_espresso'
1189
-                    ),
1190
-                    __FILE__,
1191
-                    __FUNCTION__,
1192
-                    __LINE__
1193
-                );
1194
-                return false;
1195
-            }
1196
-        }
1197
-        // now that things have been kinda sufficiently verified,
1198
-        // let's add the checkout to the session so that it's available to other systems
1199
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1200
-        return true;
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     *    _initialize_reg_steps
1206
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1207
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1208
-     *
1209
-     * @access    private
1210
-     * @param bool $reinitializing
1211
-     * @throws EE_Error
1212
-     */
1213
-    private function _initialize_reg_steps($reinitializing = false)
1214
-    {
1215
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1216
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1217
-        foreach ($this->checkout->reg_steps as $reg_step) {
1218
-            if (! $reg_step->initialize_reg_step()) {
1219
-                // if not initialized then maybe this step is being removed...
1220
-                if (! $reinitializing && $reg_step->is_current_step()) {
1221
-                    // if it was the current step, then we need to start over here
1222
-                    $this->_initialize_reg_steps(true);
1223
-                    return;
1224
-                }
1225
-                continue;
1226
-            }
1227
-            // add css and JS for current step
1228
-            $reg_step->enqueue_styles_and_scripts();
1229
-            // i18n
1230
-            $reg_step->translate_js_strings();
1231
-            if ($reg_step->is_current_step()) {
1232
-                // the text that appears on the reg step form submit button
1233
-                $reg_step->set_submit_button_text();
1234
-            }
1235
-        }
1236
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1237
-        do_action(
1238
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1239
-            $this->checkout->current_step
1240
-        );
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * _check_form_submission
1246
-     *
1247
-     * @access private
1248
-     * @return boolean
1249
-     */
1250
-    private function _check_form_submission()
1251
-    {
1252
-        // does this request require the reg form to be generated ?
1253
-        if ($this->checkout->generate_reg_form) {
1254
-            // ever heard that song by Blue Rodeo ?
1255
-            try {
1256
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1257
-                // if not displaying a form, then check for form submission
1258
-                if ($this->checkout->process_form_submission
1259
-                    && $this->checkout->current_step->reg_form->was_submitted()
1260
-                ) {
1261
-                    // clear out any old data in case this step is being run again
1262
-                    $this->checkout->current_step->set_valid_data(array());
1263
-                    // capture submitted form data
1264
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1265
-                        apply_filters(
1266
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1267
-                            EE_Registry::instance()->REQ->params(),
1268
-                            $this->checkout
1269
-                        )
1270
-                    );
1271
-                    // validate submitted form data
1272
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1273
-                        // thou shall not pass !!!
1274
-                        $this->checkout->continue_reg = false;
1275
-                        // any form validation errors?
1276
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1277
-                            EE_Error::add_error(
1278
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1279
-                                __FILE__,
1280
-                                __FUNCTION__,
1281
-                                __LINE__
1282
-                            );
1283
-                        }
1284
-                        // well not really... what will happen is
1285
-                        // we'll just get redirected back to redo the current step
1286
-                        $this->go_to_next_step();
1287
-                        return false;
1288
-                    }
1289
-                }
1290
-            } catch (EE_Error $e) {
1291
-                $e->get_error();
1292
-            }
1293
-        }
1294
-        return true;
1295
-    }
1296
-
1297
-
1298
-    /**
1299
-     * _process_action
1300
-     *
1301
-     * @access private
1302
-     * @return void
1303
-     * @throws EE_Error
1304
-     */
1305
-    private function _process_form_action()
1306
-    {
1307
-        // what cha wanna do?
1308
-        switch ($this->checkout->action) {
1309
-            // AJAX next step reg form
1310
-            case 'display_spco_reg_step':
1311
-                $this->checkout->redirect = false;
1312
-                if (EE_Registry::instance()->REQ->ajax) {
1313
-                    $this->checkout->json_response->set_reg_step_html(
1314
-                        $this->checkout->current_step->display_reg_form()
1315
-                    );
1316
-                }
1317
-                break;
1318
-            default:
1319
-                // meh... do one of those other steps first
1320
-                if (! empty($this->checkout->action)
1321
-                    && is_callable(array($this->checkout->current_step, $this->checkout->action))
1322
-                ) {
1323
-                    // dynamically creates hook point like:
1324
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1325
-                    do_action(
1326
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1327
-                        $this->checkout->current_step
1328
-                    );
1329
-                    // call action on current step
1330
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1331
-                        // good registrant, you get to proceed
1332
-                        if ($this->checkout->current_step->success_message() !== ''
1333
-                            && apply_filters(
1334
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1335
-                                false
1336
-                            )
1337
-                        ) {
1338
-                            EE_Error::add_success(
1339
-                                $this->checkout->current_step->success_message()
1340
-                                . '<br />' . $this->checkout->next_step->_instructions()
1341
-                            );
1342
-                        }
1343
-                        // pack it up, pack it in...
1344
-                        $this->_setup_redirect();
1345
-                    }
1346
-                    // dynamically creates hook point like:
1347
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1348
-                    do_action(
1349
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1350
-                        $this->checkout->current_step
1351
-                    );
1352
-                } else {
1353
-                    EE_Error::add_error(
1354
-                        sprintf(
1355
-                            __(
1356
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1357
-                                'event_espresso'
1358
-                            ),
1359
-                            $this->checkout->action,
1360
-                            $this->checkout->current_step->name()
1361
-                        ),
1362
-                        __FILE__,
1363
-                        __FUNCTION__,
1364
-                        __LINE__
1365
-                    );
1366
-                }
1367
-            // end default
1368
-        }
1369
-        // store our progress so far
1370
-        $this->checkout->stash_transaction_and_checkout();
1371
-        // advance to the next step! If you pass GO, collect $200
1372
-        $this->go_to_next_step();
1373
-    }
1374
-
1375
-
1376
-    /**
1377
-     *        add_styles_and_scripts
1378
-     *
1379
-     * @access        public
1380
-     * @return        void
1381
-     */
1382
-    public function add_styles_and_scripts()
1383
-    {
1384
-        // i18n
1385
-        $this->translate_js_strings();
1386
-        if ($this->checkout->admin_request) {
1387
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1388
-        } else {
1389
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1390
-        }
1391
-    }
1392
-
1393
-
1394
-    /**
1395
-     *        translate_js_strings
1396
-     *
1397
-     * @access        public
1398
-     * @return        void
1399
-     */
1400
-    public function translate_js_strings()
1401
-    {
1402
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1403
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1404
-        EE_Registry::$i18n_js_strings['server_error'] = __(
1405
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1406
-            'event_espresso'
1407
-        );
1408
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1409
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1410
-            'event_espresso'
1411
-        );
1412
-        EE_Registry::$i18n_js_strings['validation_error'] = __(
1413
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1414
-            'event_espresso'
1415
-        );
1416
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1417
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1418
-            'event_espresso'
1419
-        );
1420
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1421
-            'This registration step could not be completed. Please refresh the page and try again.',
1422
-            'event_espresso'
1423
-        );
1424
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1425
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1426
-            'event_espresso'
1427
-        );
1428
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1429
-            __(
1430
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1431
-                'event_espresso'
1432
-            ),
1433
-            '<br/>',
1434
-            '<br/>'
1435
-        );
1436
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1437
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1438
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1439
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1440
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1441
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1442
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1443
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1444
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1445
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1446
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1447
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1448
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1449
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1450
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1451
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1452
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1453
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1454
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
1455
-        );
1456
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1457
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1458
-            true
1459
-        );
1460
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1461
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1462
-        );
1463
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1464
-            'M d, Y H:i:s',
1465
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1466
-        );
1467
-    }
1468
-
1469
-
1470
-    /**
1471
-     *    enqueue_styles_and_scripts
1472
-     *
1473
-     * @access        public
1474
-     * @return        void
1475
-     * @throws EE_Error
1476
-     */
1477
-    public function enqueue_styles_and_scripts()
1478
-    {
1479
-        // load css
1480
-        wp_register_style(
1481
-            'single_page_checkout',
1482
-            SPCO_CSS_URL . 'single_page_checkout.css',
1483
-            array('espresso_default'),
1484
-            EVENT_ESPRESSO_VERSION
1485
-        );
1486
-        wp_enqueue_style('single_page_checkout');
1487
-        // load JS
1488
-        wp_register_script(
1489
-            'jquery_plugin',
1490
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1491
-            array('jquery'),
1492
-            '1.0.1',
1493
-            true
1494
-        );
1495
-        wp_register_script(
1496
-            'jquery_countdown',
1497
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1498
-            array('jquery_plugin'),
1499
-            '2.0.2',
1500
-            true
1501
-        );
1502
-        wp_register_script(
1503
-            'single_page_checkout',
1504
-            SPCO_JS_URL . 'single_page_checkout.js',
1505
-            array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1506
-            EVENT_ESPRESSO_VERSION,
1507
-            true
1508
-        );
1509
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1510
-            $this->checkout->registration_form->enqueue_js();
1511
-        }
1512
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1513
-            $this->checkout->current_step->reg_form->enqueue_js();
1514
-        }
1515
-        wp_enqueue_script('single_page_checkout');
1516
-        /**
1517
-         * global action hook for enqueueing styles and scripts with
1518
-         * spco calls.
1519
-         */
1520
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1521
-        /**
1522
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1523
-         * The hook will end up being something like:
1524
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1525
-         */
1526
-        do_action(
1527
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1528
-            $this
1529
-        );
1530
-    }
1531
-
1532
-
1533
-    /**
1534
-     *    display the Registration Single Page Checkout Form
1535
-     *
1536
-     * @access    private
1537
-     * @return    void
1538
-     * @throws EE_Error
1539
-     */
1540
-    private function _display_spco_reg_form()
1541
-    {
1542
-        // if registering via the admin, just display the reg form for the current step
1543
-        if ($this->checkout->admin_request) {
1544
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1545
-        } else {
1546
-            // add powered by EE msg
1547
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1548
-            $empty_cart = count($this->checkout->transaction
1549
-                                    ->registrations($this->checkout->reg_cache_where_params)) < 1;
1550
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1551
-            $cookies_not_set_msg = '';
1552
-            if ($empty_cart) {
1553
-                $cookies_not_set_msg = apply_filters(
1554
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1555
-                    sprintf(
1556
-                        __(
1557
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1558
-                            'event_espresso'
1559
-                        ),
1560
-                        '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1561
-                        '</div>',
1562
-                        '<h6 class="important-notice">',
1563
-                        '</h6>',
1564
-                        '<p>',
1565
-                        '</p>',
1566
-                        '<br />',
1567
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1568
-                        '</a>'
1569
-                    )
1570
-                );
1571
-            }
1572
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1573
-                array(
1574
-                    'name'            => 'single-page-checkout',
1575
-                    'html_id'         => 'ee-single-page-checkout-dv',
1576
-                    'layout_strategy' =>
1577
-                        new EE_Template_Layout(
1578
-                            array(
1579
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1580
-                                'template_args'        => array(
1581
-                                    'empty_cart'              => $empty_cart,
1582
-                                    'revisit'                 => $this->checkout->revisit,
1583
-                                    'reg_steps'               => $this->checkout->reg_steps,
1584
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1585
-                                        ? $this->checkout->next_step->slug()
1586
-                                        : '',
1587
-                                    'empty_msg'               => apply_filters(
1588
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1589
-                                        sprintf(
1590
-                                            __(
1591
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1592
-                                                'event_espresso'
1593
-                                            ),
1594
-                                            '<a href="'
1595
-                                            . get_post_type_archive_link('espresso_events')
1596
-                                            . '" title="',
1597
-                                            '">',
1598
-                                            '</a>'
1599
-                                        )
1600
-                                    ),
1601
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1602
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1603
-                                    'session_expiration'      => gmdate(
1604
-                                        'M d, Y H:i:s',
1605
-                                        EE_Registry::instance()->SSN->expiration()
1606
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1607
-                                    ),
1608
-                                ),
1609
-                            )
1610
-                        ),
1611
-                )
1612
-            );
1613
-            // load template and add to output sent that gets filtered into the_content()
1614
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1615
-        }
1616
-    }
1617
-
1618
-
1619
-    /**
1620
-     *    add_extra_finalize_registration_inputs
1621
-     *
1622
-     * @access    public
1623
-     * @param $next_step
1624
-     * @internal  param string $label
1625
-     * @return void
1626
-     */
1627
-    public function add_extra_finalize_registration_inputs($next_step)
1628
-    {
1629
-        if ($next_step === 'finalize_registration') {
1630
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1631
-        }
1632
-    }
1633
-
1634
-
1635
-    /**
1636
-     *    display_registration_footer
1637
-     *
1638
-     * @access    public
1639
-     * @return    string
1640
-     */
1641
-    public static function display_registration_footer()
1642
-    {
1643
-        if (apply_filters(
1644
-            'FHEE__EE_Front__Controller__show_reg_footer',
1645
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1646
-        )) {
1647
-            add_filter(
1648
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1649
-                function ($url) {
1650
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1651
-                }
1652
-            );
1653
-            echo apply_filters(
1654
-                'FHEE__EE_Front_Controller__display_registration_footer',
1655
-                \EEH_Template::powered_by_event_espresso(
1656
-                    '',
1657
-                    'espresso-registration-footer-dv',
1658
-                    array('utm_content' => 'registration_checkout')
1659
-                )
1660
-            );
1661
-        }
1662
-        return '';
1663
-    }
1664
-
1665
-
1666
-    /**
1667
-     *    unlock_transaction
1668
-     *
1669
-     * @access    public
1670
-     * @return    void
1671
-     * @throws EE_Error
1672
-     */
1673
-    public function unlock_transaction()
1674
-    {
1675
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1676
-            $this->checkout->transaction->unlock();
1677
-        }
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     *        _setup_redirect
1683
-     *
1684
-     * @access    private
1685
-     * @return void
1686
-     */
1687
-    private function _setup_redirect()
1688
-    {
1689
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1690
-            $this->checkout->redirect = true;
1691
-            if (empty($this->checkout->redirect_url)) {
1692
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1693
-            }
1694
-            $this->checkout->redirect_url = apply_filters(
1695
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1696
-                $this->checkout->redirect_url,
1697
-                $this->checkout
1698
-            );
1699
-        }
1700
-    }
1701
-
1702
-
1703
-    /**
1704
-     *   handle ajax message responses and redirects
1705
-     *
1706
-     * @access public
1707
-     * @return void
1708
-     * @throws EE_Error
1709
-     */
1710
-    public function go_to_next_step()
1711
-    {
1712
-        if (EE_Registry::instance()->REQ->ajax) {
1713
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1714
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1715
-        }
1716
-        $this->unlock_transaction();
1717
-        // just return for these conditions
1718
-        if ($this->checkout->admin_request
1719
-            || $this->checkout->action === 'redirect_form'
1720
-            || $this->checkout->action === 'update_checkout'
1721
-        ) {
1722
-            return;
1723
-        }
1724
-        // AJAX response
1725
-        $this->_handle_json_response();
1726
-        // redirect to next step or the Thank You page
1727
-        $this->_handle_html_redirects();
1728
-        // hmmm... must be something wrong, so let's just display the form again !
1729
-        $this->_display_spco_reg_form();
1730
-    }
1731
-
1732
-
1733
-    /**
1734
-     *   _handle_json_response
1735
-     *
1736
-     * @access protected
1737
-     * @return void
1738
-     */
1739
-    protected function _handle_json_response()
1740
-    {
1741
-        // if this is an ajax request
1742
-        if (EE_Registry::instance()->REQ->ajax) {
1743
-            $this->checkout->json_response->set_registration_time_limit(
1744
-                $this->checkout->get_registration_time_limit()
1745
-            );
1746
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1747
-            // just send the ajax (
1748
-            $json_response = apply_filters(
1749
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1750
-                $this->checkout->json_response
1751
-            );
1752
-            echo $json_response;
1753
-            exit();
1754
-        }
1755
-    }
1756
-
1757
-
1758
-    /**
1759
-     *   _handle_redirects
1760
-     *
1761
-     * @access protected
1762
-     * @return void
1763
-     */
1764
-    protected function _handle_html_redirects()
1765
-    {
1766
-        // going somewhere ?
1767
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1768
-            // store notices in a transient
1769
-            EE_Error::get_notices(false, true, true);
1770
-            wp_safe_redirect($this->checkout->redirect_url);
1771
-            exit();
1772
-        }
1773
-    }
1774
-
1775
-
1776
-    /**
1777
-     *   set_checkout_anchor
1778
-     *
1779
-     * @access public
1780
-     * @return void
1781
-     */
1782
-    public function set_checkout_anchor()
1783
-    {
1784
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1785
-    }
1786
-
1787
-    /**
1788
-     *    getRegistrationExpirationNotice
1789
-     *
1790
-     * @since     4.9.59.p
1791
-     * @access    public
1792
-     * @return    string
1793
-     */
1794
-    public static function getRegistrationExpirationNotice()
1795
-    {
1796
-        return sprintf(
1797
-            __(
1798
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1799
-                'event_espresso'
1800
-            ),
1801
-            '<h4 class="important-notice">',
1802
-            '</h4>',
1803
-            '<br />',
1804
-            '<p>',
1805
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1806
-            '">',
1807
-            '</a>',
1808
-            '</p>'
1809
-        );
1810
-    }
18
+	/**
19
+	 * $_initialized - has the SPCO controller already been initialized ?
20
+	 *
21
+	 * @access private
22
+	 * @var bool $_initialized
23
+	 */
24
+	private static $_initialized = false;
25
+
26
+
27
+	/**
28
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
29
+	 *
30
+	 * @access private
31
+	 * @var bool $_valid_checkout
32
+	 */
33
+	private static $_checkout_verified = true;
34
+
35
+	/**
36
+	 *    $_reg_steps_array - holds initial array of reg steps
37
+	 *
38
+	 * @access private
39
+	 * @var array $_reg_steps_array
40
+	 */
41
+	private static $_reg_steps_array = array();
42
+
43
+	/**
44
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
45
+	 *
46
+	 * @access public
47
+	 * @var EE_Checkout $checkout
48
+	 */
49
+	public $checkout;
50
+
51
+
52
+	/**
53
+	 * @return EED_Module|EED_Single_Page_Checkout
54
+	 */
55
+	public static function instance()
56
+	{
57
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
+		return parent::get_instance(__CLASS__);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return EE_CART
64
+	 */
65
+	public function cart()
66
+	{
67
+		return $this->checkout->cart;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @return EE_Transaction
73
+	 */
74
+	public function transaction()
75
+	{
76
+		return $this->checkout->transaction;
77
+	}
78
+
79
+
80
+	/**
81
+	 *    set_hooks - for hooking into EE Core, other modules, etc
82
+	 *
83
+	 * @access    public
84
+	 * @return    void
85
+	 * @throws EE_Error
86
+	 */
87
+	public static function set_hooks()
88
+	{
89
+		EED_Single_Page_Checkout::set_definitions();
90
+	}
91
+
92
+
93
+	/**
94
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
95
+	 *
96
+	 * @access    public
97
+	 * @return    void
98
+	 * @throws EE_Error
99
+	 */
100
+	public static function set_hooks_admin()
101
+	{
102
+		EED_Single_Page_Checkout::set_definitions();
103
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
104
+			return;
105
+		}
106
+		// going to start an output buffer in case anything gets accidentally output
107
+		// that might disrupt our JSON response
108
+		ob_start();
109
+		EED_Single_Page_Checkout::load_request_handler();
110
+		EED_Single_Page_Checkout::load_reg_steps();
111
+		// set ajax hooks
112
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
113
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
114
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
115
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
116
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
117
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
118
+	}
119
+
120
+
121
+	/**
122
+	 *    process ajax request
123
+	 *
124
+	 * @param string $ajax_action
125
+	 * @throws EE_Error
126
+	 */
127
+	public static function process_ajax_request($ajax_action)
128
+	{
129
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
130
+		EED_Single_Page_Checkout::instance()->_initialize();
131
+	}
132
+
133
+
134
+	/**
135
+	 *    ajax display registration step
136
+	 *
137
+	 * @throws EE_Error
138
+	 */
139
+	public static function display_reg_step()
140
+	{
141
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
142
+	}
143
+
144
+
145
+	/**
146
+	 *    ajax process registration step
147
+	 *
148
+	 * @throws EE_Error
149
+	 */
150
+	public static function process_reg_step()
151
+	{
152
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
153
+	}
154
+
155
+
156
+	/**
157
+	 *    ajax process registration step
158
+	 *
159
+	 * @throws EE_Error
160
+	 */
161
+	public static function update_reg_step()
162
+	{
163
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
164
+	}
165
+
166
+
167
+	/**
168
+	 *   update_checkout
169
+	 *
170
+	 * @access public
171
+	 * @return void
172
+	 * @throws EE_Error
173
+	 */
174
+	public static function update_checkout()
175
+	{
176
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
177
+	}
178
+
179
+
180
+	/**
181
+	 *    load_request_handler
182
+	 *
183
+	 * @access    public
184
+	 * @return    void
185
+	 */
186
+	public static function load_request_handler()
187
+	{
188
+		// load core Request_Handler class
189
+		if (EE_Registry::instance()->REQ !== null) {
190
+			EE_Registry::instance()->load_core('Request_Handler');
191
+		}
192
+	}
193
+
194
+
195
+	/**
196
+	 *    set_definitions
197
+	 *
198
+	 * @access    public
199
+	 * @return    void
200
+	 * @throws EE_Error
201
+	 */
202
+	public static function set_definitions()
203
+	{
204
+		if (defined('SPCO_BASE_PATH')) {
205
+			return;
206
+		}
207
+		define(
208
+			'SPCO_BASE_PATH',
209
+			rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
210
+		);
211
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
212
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
213
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
214
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
215
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
216
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
217
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
218
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
219
+		);
220
+	}
221
+
222
+
223
+	/**
224
+	 * load_reg_steps
225
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
226
+	 *
227
+	 * @access    private
228
+	 * @throws EE_Error
229
+	 */
230
+	public static function load_reg_steps()
231
+	{
232
+		static $reg_steps_loaded = false;
233
+		if ($reg_steps_loaded) {
234
+			return;
235
+		}
236
+		// filter list of reg_steps
237
+		$reg_steps_to_load = (array) apply_filters(
238
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
239
+			EED_Single_Page_Checkout::get_reg_steps()
240
+		);
241
+		// sort by key (order)
242
+		ksort($reg_steps_to_load);
243
+		// loop through folders
244
+		foreach ($reg_steps_to_load as $order => $reg_step) {
245
+			// we need a
246
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
247
+				// copy over to the reg_steps_array
248
+				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
249
+				// register custom key route for each reg step
250
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
251
+				EE_Config::register_route(
252
+					$reg_step['slug'],
253
+					'EED_Single_Page_Checkout',
254
+					'run',
255
+					'step'
256
+				);
257
+				// add AJAX or other hooks
258
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
259
+					// setup autoloaders if necessary
260
+					if (! class_exists($reg_step['class_name'])) {
261
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
262
+							$reg_step['file_path'],
263
+							true
264
+						);
265
+					}
266
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
267
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
268
+					}
269
+				}
270
+			}
271
+		}
272
+		$reg_steps_loaded = true;
273
+	}
274
+
275
+
276
+	/**
277
+	 *    get_reg_steps
278
+	 *
279
+	 * @access    public
280
+	 * @return    array
281
+	 */
282
+	public static function get_reg_steps()
283
+	{
284
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
285
+		if (empty($reg_steps)) {
286
+			$reg_steps = array(
287
+				10  => array(
288
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
289
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
290
+					'slug'       => 'attendee_information',
291
+					'has_hooks'  => false,
292
+				),
293
+				30  => array(
294
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
295
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
296
+					'slug'       => 'payment_options',
297
+					'has_hooks'  => true,
298
+				),
299
+				999 => array(
300
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
301
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
302
+					'slug'       => 'finalize_registration',
303
+					'has_hooks'  => false,
304
+				),
305
+			);
306
+		}
307
+		return $reg_steps;
308
+	}
309
+
310
+
311
+	/**
312
+	 *    registration_checkout_for_admin
313
+	 *
314
+	 * @access    public
315
+	 * @return    string
316
+	 * @throws EE_Error
317
+	 */
318
+	public static function registration_checkout_for_admin()
319
+	{
320
+		EED_Single_Page_Checkout::load_request_handler();
321
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
322
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
323
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
324
+		EED_Single_Page_Checkout::instance()->_initialize();
325
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
326
+		return EE_Registry::instance()->REQ->get_output();
327
+	}
328
+
329
+
330
+	/**
331
+	 * process_registration_from_admin
332
+	 *
333
+	 * @access public
334
+	 * @return \EE_Transaction
335
+	 * @throws EE_Error
336
+	 */
337
+	public static function process_registration_from_admin()
338
+	{
339
+		EED_Single_Page_Checkout::load_request_handler();
340
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
341
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
342
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
343
+		EED_Single_Page_Checkout::instance()->_initialize();
344
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
345
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
346
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
347
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
348
+				if ($final_reg_step->process_reg_step()) {
349
+					$final_reg_step->set_completed();
350
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
351
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
352
+				}
353
+			}
354
+		}
355
+		return null;
356
+	}
357
+
358
+
359
+	/**
360
+	 *    run
361
+	 *
362
+	 * @access    public
363
+	 * @param WP_Query $WP_Query
364
+	 * @return    void
365
+	 * @throws EE_Error
366
+	 */
367
+	public function run($WP_Query)
368
+	{
369
+		if ($WP_Query instanceof WP_Query
370
+			&& $WP_Query->is_main_query()
371
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
372
+			&& $this->_is_reg_checkout()
373
+		) {
374
+			$this->_initialize();
375
+		}
376
+	}
377
+
378
+
379
+	/**
380
+	 * determines whether current url matches reg page url
381
+	 *
382
+	 * @return bool
383
+	 */
384
+	protected function _is_reg_checkout()
385
+	{
386
+		// get current permalink for reg page without any extra query args
387
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
388
+		// get request URI for current request, but without the scheme or host
389
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
390
+		$current_request_uri = html_entity_decode($current_request_uri);
391
+		// get array of query args from the current request URI
392
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
393
+		// grab page id if it is set
394
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
395
+		// and remove the page id from the query args (we will re-add it later)
396
+		unset($query_args['page_id']);
397
+		// now strip all query args from current request URI
398
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
399
+		// and re-add the page id if it was set
400
+		if ($page_id) {
401
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
402
+		}
403
+		// remove slashes and ?
404
+		$current_request_uri = trim($current_request_uri, '?/');
405
+		// is current request URI part of the known full reg page URL ?
406
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
407
+	}
408
+
409
+
410
+	/**
411
+	 * @param WP_Query $wp_query
412
+	 * @return    void
413
+	 * @throws EE_Error
414
+	 */
415
+	public static function init($wp_query)
416
+	{
417
+		EED_Single_Page_Checkout::instance()->run($wp_query);
418
+	}
419
+
420
+
421
+	/**
422
+	 *    _initialize - initial module setup
423
+	 *
424
+	 * @access    private
425
+	 * @throws EE_Error
426
+	 * @return    void
427
+	 */
428
+	private function _initialize()
429
+	{
430
+		// ensure SPCO doesn't run twice
431
+		if (EED_Single_Page_Checkout::$_initialized) {
432
+			return;
433
+		}
434
+		try {
435
+			EED_Single_Page_Checkout::load_reg_steps();
436
+			$this->_verify_session();
437
+			// setup the EE_Checkout object
438
+			$this->checkout = $this->_initialize_checkout();
439
+			// filter checkout
440
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
441
+			// get the $_GET
442
+			$this->_get_request_vars();
443
+			if ($this->_block_bots()) {
444
+				return;
445
+			}
446
+			// filter continue_reg
447
+			$this->checkout->continue_reg = apply_filters(
448
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
449
+				true,
450
+				$this->checkout
451
+			);
452
+			// load the reg steps array
453
+			if (! $this->_load_and_instantiate_reg_steps()) {
454
+				EED_Single_Page_Checkout::$_initialized = true;
455
+				return;
456
+			}
457
+			// set the current step
458
+			$this->checkout->set_current_step($this->checkout->step);
459
+			// and the next step
460
+			$this->checkout->set_next_step();
461
+			// verify that everything has been setup correctly
462
+			if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
463
+				EED_Single_Page_Checkout::$_initialized = true;
464
+				return;
465
+			}
466
+			// lock the transaction
467
+			$this->checkout->transaction->lock();
468
+			// make sure all of our cached objects are added to their respective model entity mappers
469
+			$this->checkout->refresh_all_entities();
470
+			// set amount owing
471
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
472
+			// initialize each reg step, which gives them the chance to potentially alter the process
473
+			$this->_initialize_reg_steps();
474
+			// DEBUG LOG
475
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
476
+			// get reg form
477
+			if (! $this->_check_form_submission()) {
478
+				EED_Single_Page_Checkout::$_initialized = true;
479
+				return;
480
+			}
481
+			// checkout the action!!!
482
+			$this->_process_form_action();
483
+			// add some style and make it dance
484
+			$this->add_styles_and_scripts();
485
+			// kk... SPCO has successfully run
486
+			EED_Single_Page_Checkout::$_initialized = true;
487
+			// set no cache headers and constants
488
+			EE_System::do_not_cache();
489
+			// add anchor
490
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
491
+			// remove transaction lock
492
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
493
+		} catch (Exception $e) {
494
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
495
+		}
496
+	}
497
+
498
+
499
+	/**
500
+	 *    _verify_session
501
+	 * checks that the session is valid and not expired
502
+	 *
503
+	 * @access    private
504
+	 * @throws EE_Error
505
+	 */
506
+	private function _verify_session()
507
+	{
508
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
509
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
510
+		}
511
+		$clear_session_requested = filter_var(
512
+			EE_Registry::instance()->REQ->get('clear_session', false),
513
+			FILTER_VALIDATE_BOOLEAN
514
+		);
515
+		// is session still valid ?
516
+		if ($clear_session_requested
517
+			|| (EE_Registry::instance()->SSN->expired()
518
+				&& EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
519
+			)
520
+		) {
521
+			$this->checkout = new EE_Checkout();
522
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
523
+			// EE_Registry::instance()->SSN->reset_cart();
524
+			// EE_Registry::instance()->SSN->reset_checkout();
525
+			// EE_Registry::instance()->SSN->reset_transaction();
526
+			if (! $clear_session_requested) {
527
+				EE_Error::add_attention(
528
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
529
+					__FILE__,
530
+					__FUNCTION__,
531
+					__LINE__
532
+				);
533
+			}
534
+			// EE_Registry::instance()->SSN->reset_expired();
535
+		}
536
+	}
537
+
538
+
539
+	/**
540
+	 *    _initialize_checkout
541
+	 * loads and instantiates EE_Checkout
542
+	 *
543
+	 * @access    private
544
+	 * @throws EE_Error
545
+	 * @return EE_Checkout
546
+	 */
547
+	private function _initialize_checkout()
548
+	{
549
+		// look in session for existing checkout
550
+		/** @type EE_Checkout $checkout */
551
+		$checkout = EE_Registry::instance()->SSN->checkout();
552
+		// verify
553
+		if (! $checkout instanceof EE_Checkout) {
554
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
555
+			$checkout = EE_Registry::instance()->load_file(
556
+				SPCO_INC_PATH,
557
+				'EE_Checkout',
558
+				'class',
559
+				array(),
560
+				false
561
+			);
562
+		} else {
563
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
564
+				$this->unlock_transaction();
565
+				wp_safe_redirect($checkout->redirect_url);
566
+				exit();
567
+			}
568
+		}
569
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
570
+		// verify again
571
+		if (! $checkout instanceof EE_Checkout) {
572
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
573
+		}
574
+		// reset anything that needs a clean slate for each request
575
+		$checkout->reset_for_current_request();
576
+		return $checkout;
577
+	}
578
+
579
+
580
+	/**
581
+	 *    _get_request_vars
582
+	 *
583
+	 * @access    private
584
+	 * @return    void
585
+	 * @throws EE_Error
586
+	 */
587
+	private function _get_request_vars()
588
+	{
589
+		// load classes
590
+		EED_Single_Page_Checkout::load_request_handler();
591
+		// make sure this request is marked as belonging to EE
592
+		EE_Registry::instance()->REQ->set_espresso_page(true);
593
+		// which step is being requested ?
594
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
595
+		// which step is being edited ?
596
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
597
+		// and what we're doing on the current step
598
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
599
+		// timestamp
600
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
601
+		// returning to edit ?
602
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
603
+		// add reg url link to registration query params
604
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
605
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
606
+		}
607
+		// or some other kind of revisit ?
608
+		$this->checkout->revisit = filter_var(
609
+			EE_Registry::instance()->REQ->get('revisit', false),
610
+			FILTER_VALIDATE_BOOLEAN
611
+		);
612
+		// and whether or not to generate a reg form for this request
613
+		$this->checkout->generate_reg_form = filter_var(
614
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
615
+			FILTER_VALIDATE_BOOLEAN
616
+		);
617
+		// and whether or not to process a reg form submission for this request
618
+		$this->checkout->process_form_submission = filter_var(
619
+			EE_Registry::instance()->REQ->get(
620
+				'process_form_submission',
621
+				$this->checkout->action === 'process_reg_step'
622
+			),
623
+			FILTER_VALIDATE_BOOLEAN
624
+		);
625
+		$this->checkout->process_form_submission = filter_var(
626
+			$this->checkout->action !== 'display_spco_reg_step'
627
+				? $this->checkout->process_form_submission
628
+				: false,
629
+			FILTER_VALIDATE_BOOLEAN
630
+		);
631
+		// $this->_display_request_vars();
632
+	}
633
+
634
+
635
+	/**
636
+	 *  _display_request_vars
637
+	 *
638
+	 * @access    protected
639
+	 * @return    void
640
+	 */
641
+	protected function _display_request_vars()
642
+	{
643
+		if (! WP_DEBUG) {
644
+			return;
645
+		}
646
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
647
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
648
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
649
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
650
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
651
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
652
+		EEH_Debug_Tools::printr(
653
+			$this->checkout->generate_reg_form,
654
+			'$this->checkout->generate_reg_form',
655
+			__FILE__,
656
+			__LINE__
657
+		);
658
+		EEH_Debug_Tools::printr(
659
+			$this->checkout->process_form_submission,
660
+			'$this->checkout->process_form_submission',
661
+			__FILE__,
662
+			__LINE__
663
+		);
664
+	}
665
+
666
+
667
+	/**
668
+	 * _block_bots
669
+	 * checks that the incoming request has either of the following set:
670
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
671
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
672
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
673
+	 * then where you coming from man?
674
+	 *
675
+	 * @return boolean
676
+	 */
677
+	private function _block_bots()
678
+	{
679
+		$invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
680
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
681
+			return true;
682
+		}
683
+		return false;
684
+	}
685
+
686
+
687
+	/**
688
+	 *    _get_first_step
689
+	 *  gets slug for first step in $_reg_steps_array
690
+	 *
691
+	 * @access    private
692
+	 * @throws EE_Error
693
+	 * @return    string
694
+	 */
695
+	private function _get_first_step()
696
+	{
697
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
698
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
699
+	}
700
+
701
+
702
+	/**
703
+	 * instantiates each reg step based on the loaded reg_steps array
704
+	 *
705
+	 * @return    bool
706
+	 * @throws EE_Error
707
+	 * @throws InvalidArgumentException
708
+	 * @throws InvalidDataTypeException
709
+	 * @throws InvalidInterfaceException
710
+	 */
711
+	private function _load_and_instantiate_reg_steps()
712
+	{
713
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
714
+		// have reg_steps already been instantiated ?
715
+		if (empty($this->checkout->reg_steps)
716
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
717
+		) {
718
+			// if not, then loop through raw reg steps array
719
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
720
+				if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
721
+					return false;
722
+				}
723
+			}
724
+			if (isset($this->checkout->reg_steps['registration_confirmation'])) {
725
+				// skip the registration_confirmation page ?
726
+				if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
727
+					// just remove it from the reg steps array
728
+					$this->checkout->remove_reg_step('registration_confirmation', false);
729
+				} elseif (EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
+				) {
731
+					// set the order to something big like 100
732
+					$this->checkout->set_reg_step_order('registration_confirmation', 100);
733
+				}
734
+			}
735
+			// filter the array for good luck
736
+			$this->checkout->reg_steps = apply_filters(
737
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
738
+				$this->checkout->reg_steps
739
+			);
740
+			// finally re-sort based on the reg step class order properties
741
+			$this->checkout->sort_reg_steps();
742
+		} else {
743
+			foreach ($this->checkout->reg_steps as $reg_step) {
744
+				// set all current step stati to FALSE
745
+				$reg_step->set_is_current_step(false);
746
+			}
747
+		}
748
+		if (empty($this->checkout->reg_steps)) {
749
+			EE_Error::add_error(
750
+				__('No Reg Steps were loaded..', 'event_espresso'),
751
+				__FILE__,
752
+				__FUNCTION__,
753
+				__LINE__
754
+			);
755
+			return false;
756
+		}
757
+		// make reg step details available to JS
758
+		$this->checkout->set_reg_step_JSON_info();
759
+		return true;
760
+	}
761
+
762
+
763
+	/**
764
+	 *     _load_and_instantiate_reg_step
765
+	 *
766
+	 * @access    private
767
+	 * @param array $reg_step
768
+	 * @param int   $order
769
+	 * @return bool
770
+	 */
771
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
772
+	{
773
+		// we need a file_path, class_name, and slug to add a reg step
774
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
775
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
776
+			if ($this->checkout->reg_url_link
777
+				&& $this->checkout->step !== $reg_step['slug']
778
+				&& $reg_step['slug'] !== 'finalize_registration'
779
+				// normally at this point we would NOT load the reg step, but this filter can change that
780
+				&& apply_filters(
781
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
782
+					true,
783
+					$reg_step,
784
+					$this->checkout
785
+				)
786
+			) {
787
+				return true;
788
+			}
789
+			// instantiate step class using file path and class name
790
+			$reg_step_obj = EE_Registry::instance()->load_file(
791
+				$reg_step['file_path'],
792
+				$reg_step['class_name'],
793
+				'class',
794
+				$this->checkout,
795
+				false
796
+			);
797
+			// did we gets the goods ?
798
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
799
+				// set reg step order based on config
800
+				$reg_step_obj->set_order($order);
801
+				// add instantiated reg step object to the master reg steps array
802
+				$this->checkout->add_reg_step($reg_step_obj);
803
+			} else {
804
+				EE_Error::add_error(
805
+					__('The current step could not be set.', 'event_espresso'),
806
+					__FILE__,
807
+					__FUNCTION__,
808
+					__LINE__
809
+				);
810
+				return false;
811
+			}
812
+		} else {
813
+			if (WP_DEBUG) {
814
+				EE_Error::add_error(
815
+					sprintf(
816
+						__(
817
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
818
+							'event_espresso'
819
+						),
820
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
821
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
822
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
823
+						'<ul>',
824
+						'<li>',
825
+						'</li>',
826
+						'</ul>'
827
+					),
828
+					__FILE__,
829
+					__FUNCTION__,
830
+					__LINE__
831
+				);
832
+			}
833
+			return false;
834
+		}
835
+		return true;
836
+	}
837
+
838
+
839
+	/**
840
+	 * _verify_transaction_and_get_registrations
841
+	 *
842
+	 * @access private
843
+	 * @return bool
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws InvalidEntityException
846
+	 * @throws EE_Error
847
+	 */
848
+	private function _verify_transaction_and_get_registrations()
849
+	{
850
+		// was there already a valid transaction in the checkout from the session ?
851
+		if (! $this->checkout->transaction instanceof EE_Transaction) {
852
+			// get transaction from db or session
853
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
854
+				? $this->_get_transaction_and_cart_for_previous_visit()
855
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
856
+			if (! $this->checkout->transaction instanceof EE_Transaction) {
857
+				EE_Error::add_error(
858
+					__(
859
+						'Your Registration and Transaction information could not be retrieved from the db.',
860
+						'event_espresso'
861
+					),
862
+					__FILE__,
863
+					__FUNCTION__,
864
+					__LINE__
865
+				);
866
+				$this->checkout->transaction = EE_Transaction::new_instance();
867
+				// add some style and make it dance
868
+				$this->add_styles_and_scripts();
869
+				EED_Single_Page_Checkout::$_initialized = true;
870
+				return false;
871
+			}
872
+			// and the registrations for the transaction
873
+			$this->_get_registrations($this->checkout->transaction);
874
+		}
875
+		return true;
876
+	}
877
+
878
+
879
+	/**
880
+	 * _get_transaction_and_cart_for_previous_visit
881
+	 *
882
+	 * @access private
883
+	 * @return mixed EE_Transaction|NULL
884
+	 */
885
+	private function _get_transaction_and_cart_for_previous_visit()
886
+	{
887
+		/** @var $TXN_model EEM_Transaction */
888
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
889
+		// because the reg_url_link is present in the request,
890
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
891
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
892
+		// verify transaction
893
+		if ($transaction instanceof EE_Transaction) {
894
+			// and get the cart that was used for that transaction
895
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
896
+			return $transaction;
897
+		}
898
+		EE_Error::add_error(
899
+			__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
900
+			__FILE__,
901
+			__FUNCTION__,
902
+			__LINE__
903
+		);
904
+		return null;
905
+	}
906
+
907
+
908
+	/**
909
+	 * _get_cart_for_transaction
910
+	 *
911
+	 * @access private
912
+	 * @param EE_Transaction $transaction
913
+	 * @return EE_Cart
914
+	 */
915
+	private function _get_cart_for_transaction($transaction)
916
+	{
917
+		return $this->checkout->get_cart_for_transaction($transaction);
918
+	}
919
+
920
+
921
+	/**
922
+	 * get_cart_for_transaction
923
+	 *
924
+	 * @access public
925
+	 * @param EE_Transaction $transaction
926
+	 * @return EE_Cart
927
+	 */
928
+	public function get_cart_for_transaction(EE_Transaction $transaction)
929
+	{
930
+		return $this->checkout->get_cart_for_transaction($transaction);
931
+	}
932
+
933
+
934
+	/**
935
+	 * _get_transaction_and_cart_for_current_session
936
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
937
+	 *
938
+	 * @access private
939
+	 * @return EE_Transaction
940
+	 * @throws EE_Error
941
+	 */
942
+	private function _get_cart_for_current_session_and_setup_new_transaction()
943
+	{
944
+		//  if there's no transaction, then this is the FIRST visit to SPCO
945
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
946
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
947
+		// and then create a new transaction
948
+		$transaction = $this->_initialize_transaction();
949
+		// verify transaction
950
+		if ($transaction instanceof EE_Transaction) {
951
+			// save it so that we have an ID for other objects to use
952
+			$transaction->save();
953
+			// and save TXN data to the cart
954
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
955
+		} else {
956
+			EE_Error::add_error(
957
+				__('A Valid Transaction could not be initialized.', 'event_espresso'),
958
+				__FILE__,
959
+				__FUNCTION__,
960
+				__LINE__
961
+			);
962
+		}
963
+		return $transaction;
964
+	}
965
+
966
+
967
+	/**
968
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
969
+	 *
970
+	 * @access private
971
+	 * @return mixed EE_Transaction|NULL
972
+	 */
973
+	private function _initialize_transaction()
974
+	{
975
+		try {
976
+			// ensure cart totals have been calculated
977
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
978
+			// grab the cart grand total
979
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
980
+			// create new TXN
981
+			$transaction = EE_Transaction::new_instance(
982
+				array(
983
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
984
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
985
+					'TXN_paid'      => 0,
986
+					'STS_ID'        => EEM_Transaction::failed_status_code,
987
+				)
988
+			);
989
+			// save it so that we have an ID for other objects to use
990
+			$transaction->save();
991
+			// set cron job for following up on TXNs after their session has expired
992
+			EE_Cron_Tasks::schedule_expired_transaction_check(
993
+				EE_Registry::instance()->SSN->expiration() + 1,
994
+				$transaction->ID()
995
+			);
996
+			return $transaction;
997
+		} catch (Exception $e) {
998
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
999
+		}
1000
+		return null;
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * _get_registrations
1006
+	 *
1007
+	 * @access private
1008
+	 * @param EE_Transaction $transaction
1009
+	 * @return void
1010
+	 * @throws InvalidDataTypeException
1011
+	 * @throws InvalidEntityException
1012
+	 * @throws EE_Error
1013
+	 */
1014
+	private function _get_registrations(EE_Transaction $transaction)
1015
+	{
1016
+		// first step: grab the registrants  { : o
1017
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1018
+		$this->checkout->total_ticket_count = count($registrations);
1019
+		// verify registrations have been set
1020
+		if (empty($registrations)) {
1021
+			// if no cached registrations, then check the db
1022
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1023
+			// still nothing ? well as long as this isn't a revisit
1024
+			if (empty($registrations) && ! $this->checkout->revisit) {
1025
+				// generate new registrations from scratch
1026
+				$registrations = $this->_initialize_registrations($transaction);
1027
+			}
1028
+		}
1029
+		// sort by their original registration order
1030
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1031
+		// then loop thru the array
1032
+		foreach ($registrations as $registration) {
1033
+			// verify each registration
1034
+			if ($registration instanceof EE_Registration) {
1035
+				// we display all attendee info for the primary registrant
1036
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1037
+					&& $registration->is_primary_registrant()
1038
+				) {
1039
+					$this->checkout->primary_revisit = true;
1040
+					break;
1041
+				}
1042
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1043
+					// but hide info if it doesn't belong to you
1044
+					$transaction->clear_cache('Registration', $registration->ID());
1045
+					$this->checkout->total_ticket_count--;
1046
+				}
1047
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1048
+			}
1049
+		}
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1055
+	 *
1056
+	 * @access private
1057
+	 * @param EE_Transaction $transaction
1058
+	 * @return    array
1059
+	 * @throws InvalidDataTypeException
1060
+	 * @throws InvalidEntityException
1061
+	 * @throws EE_Error
1062
+	 */
1063
+	private function _initialize_registrations(EE_Transaction $transaction)
1064
+	{
1065
+		$att_nmbr = 0;
1066
+		$registrations = array();
1067
+		if ($transaction instanceof EE_Transaction) {
1068
+			/** @type EE_Registration_Processor $registration_processor */
1069
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1070
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1071
+			// now let's add the cart items to the $transaction
1072
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1073
+				// do the following for each ticket of this type they selected
1074
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1075
+					$att_nmbr++;
1076
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1077
+					$CreateRegistrationCommand = EE_Registry::instance()->create(
1078
+						'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1079
+						array(
1080
+							$transaction,
1081
+							$line_item,
1082
+							$att_nmbr,
1083
+							$this->checkout->total_ticket_count,
1084
+						)
1085
+					);
1086
+					// override capabilities for frontend registrations
1087
+					if (! is_admin()) {
1088
+						$CreateRegistrationCommand->setCapCheck(
1089
+							new PublicCapabilities('', 'create_new_registration')
1090
+						);
1091
+					}
1092
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1093
+					if (! $registration instanceof EE_Registration) {
1094
+						throw new InvalidEntityException($registration, 'EE_Registration');
1095
+					}
1096
+					$registrations[ $registration->ID() ] = $registration;
1097
+				}
1098
+			}
1099
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1100
+		}
1101
+		return $registrations;
1102
+	}
1103
+
1104
+
1105
+	/**
1106
+	 * sorts registrations by REG_count
1107
+	 *
1108
+	 * @access public
1109
+	 * @param EE_Registration $reg_A
1110
+	 * @param EE_Registration $reg_B
1111
+	 * @return int
1112
+	 */
1113
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1114
+	{
1115
+		// this shouldn't ever happen within the same TXN, but oh well
1116
+		if ($reg_A->count() === $reg_B->count()) {
1117
+			return 0;
1118
+		}
1119
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 *    _final_verifications
1125
+	 * just makes sure that everything is set up correctly before proceeding
1126
+	 *
1127
+	 * @access    private
1128
+	 * @return    bool
1129
+	 * @throws EE_Error
1130
+	 */
1131
+	private function _final_verifications()
1132
+	{
1133
+		// filter checkout
1134
+		$this->checkout = apply_filters(
1135
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1136
+			$this->checkout
1137
+		);
1138
+		// verify that current step is still set correctly
1139
+		if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1140
+			EE_Error::add_error(
1141
+				__(
1142
+					'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1143
+					'event_espresso'
1144
+				),
1145
+				__FILE__,
1146
+				__FUNCTION__,
1147
+				__LINE__
1148
+			);
1149
+			return false;
1150
+		}
1151
+		// if returning to SPCO, then verify that primary registrant is set
1152
+		if (! empty($this->checkout->reg_url_link)) {
1153
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1154
+			if (! $valid_registrant instanceof EE_Registration) {
1155
+				EE_Error::add_error(
1156
+					__(
1157
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1158
+						'event_espresso'
1159
+					),
1160
+					__FILE__,
1161
+					__FUNCTION__,
1162
+					__LINE__
1163
+				);
1164
+				return false;
1165
+			}
1166
+			$valid_registrant = null;
1167
+			foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1168
+				if ($registration instanceof EE_Registration
1169
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1170
+				) {
1171
+					$valid_registrant = $registration;
1172
+				}
1173
+			}
1174
+			if (! $valid_registrant instanceof EE_Registration) {
1175
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1176
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1177
+					// clear the session, mark the checkout as unverified, and try again
1178
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1179
+					EED_Single_Page_Checkout::$_initialized = false;
1180
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1181
+					$this->_initialize();
1182
+					EE_Error::reset_notices();
1183
+					return false;
1184
+				}
1185
+				EE_Error::add_error(
1186
+					__(
1187
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1188
+						'event_espresso'
1189
+					),
1190
+					__FILE__,
1191
+					__FUNCTION__,
1192
+					__LINE__
1193
+				);
1194
+				return false;
1195
+			}
1196
+		}
1197
+		// now that things have been kinda sufficiently verified,
1198
+		// let's add the checkout to the session so that it's available to other systems
1199
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1200
+		return true;
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 *    _initialize_reg_steps
1206
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1207
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1208
+	 *
1209
+	 * @access    private
1210
+	 * @param bool $reinitializing
1211
+	 * @throws EE_Error
1212
+	 */
1213
+	private function _initialize_reg_steps($reinitializing = false)
1214
+	{
1215
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1216
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1217
+		foreach ($this->checkout->reg_steps as $reg_step) {
1218
+			if (! $reg_step->initialize_reg_step()) {
1219
+				// if not initialized then maybe this step is being removed...
1220
+				if (! $reinitializing && $reg_step->is_current_step()) {
1221
+					// if it was the current step, then we need to start over here
1222
+					$this->_initialize_reg_steps(true);
1223
+					return;
1224
+				}
1225
+				continue;
1226
+			}
1227
+			// add css and JS for current step
1228
+			$reg_step->enqueue_styles_and_scripts();
1229
+			// i18n
1230
+			$reg_step->translate_js_strings();
1231
+			if ($reg_step->is_current_step()) {
1232
+				// the text that appears on the reg step form submit button
1233
+				$reg_step->set_submit_button_text();
1234
+			}
1235
+		}
1236
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1237
+		do_action(
1238
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1239
+			$this->checkout->current_step
1240
+		);
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * _check_form_submission
1246
+	 *
1247
+	 * @access private
1248
+	 * @return boolean
1249
+	 */
1250
+	private function _check_form_submission()
1251
+	{
1252
+		// does this request require the reg form to be generated ?
1253
+		if ($this->checkout->generate_reg_form) {
1254
+			// ever heard that song by Blue Rodeo ?
1255
+			try {
1256
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1257
+				// if not displaying a form, then check for form submission
1258
+				if ($this->checkout->process_form_submission
1259
+					&& $this->checkout->current_step->reg_form->was_submitted()
1260
+				) {
1261
+					// clear out any old data in case this step is being run again
1262
+					$this->checkout->current_step->set_valid_data(array());
1263
+					// capture submitted form data
1264
+					$this->checkout->current_step->reg_form->receive_form_submission(
1265
+						apply_filters(
1266
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1267
+							EE_Registry::instance()->REQ->params(),
1268
+							$this->checkout
1269
+						)
1270
+					);
1271
+					// validate submitted form data
1272
+					if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1273
+						// thou shall not pass !!!
1274
+						$this->checkout->continue_reg = false;
1275
+						// any form validation errors?
1276
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1277
+							EE_Error::add_error(
1278
+								$this->checkout->current_step->reg_form->submission_error_message(),
1279
+								__FILE__,
1280
+								__FUNCTION__,
1281
+								__LINE__
1282
+							);
1283
+						}
1284
+						// well not really... what will happen is
1285
+						// we'll just get redirected back to redo the current step
1286
+						$this->go_to_next_step();
1287
+						return false;
1288
+					}
1289
+				}
1290
+			} catch (EE_Error $e) {
1291
+				$e->get_error();
1292
+			}
1293
+		}
1294
+		return true;
1295
+	}
1296
+
1297
+
1298
+	/**
1299
+	 * _process_action
1300
+	 *
1301
+	 * @access private
1302
+	 * @return void
1303
+	 * @throws EE_Error
1304
+	 */
1305
+	private function _process_form_action()
1306
+	{
1307
+		// what cha wanna do?
1308
+		switch ($this->checkout->action) {
1309
+			// AJAX next step reg form
1310
+			case 'display_spco_reg_step':
1311
+				$this->checkout->redirect = false;
1312
+				if (EE_Registry::instance()->REQ->ajax) {
1313
+					$this->checkout->json_response->set_reg_step_html(
1314
+						$this->checkout->current_step->display_reg_form()
1315
+					);
1316
+				}
1317
+				break;
1318
+			default:
1319
+				// meh... do one of those other steps first
1320
+				if (! empty($this->checkout->action)
1321
+					&& is_callable(array($this->checkout->current_step, $this->checkout->action))
1322
+				) {
1323
+					// dynamically creates hook point like:
1324
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1325
+					do_action(
1326
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1327
+						$this->checkout->current_step
1328
+					);
1329
+					// call action on current step
1330
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1331
+						// good registrant, you get to proceed
1332
+						if ($this->checkout->current_step->success_message() !== ''
1333
+							&& apply_filters(
1334
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1335
+								false
1336
+							)
1337
+						) {
1338
+							EE_Error::add_success(
1339
+								$this->checkout->current_step->success_message()
1340
+								. '<br />' . $this->checkout->next_step->_instructions()
1341
+							);
1342
+						}
1343
+						// pack it up, pack it in...
1344
+						$this->_setup_redirect();
1345
+					}
1346
+					// dynamically creates hook point like:
1347
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1348
+					do_action(
1349
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1350
+						$this->checkout->current_step
1351
+					);
1352
+				} else {
1353
+					EE_Error::add_error(
1354
+						sprintf(
1355
+							__(
1356
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1357
+								'event_espresso'
1358
+							),
1359
+							$this->checkout->action,
1360
+							$this->checkout->current_step->name()
1361
+						),
1362
+						__FILE__,
1363
+						__FUNCTION__,
1364
+						__LINE__
1365
+					);
1366
+				}
1367
+			// end default
1368
+		}
1369
+		// store our progress so far
1370
+		$this->checkout->stash_transaction_and_checkout();
1371
+		// advance to the next step! If you pass GO, collect $200
1372
+		$this->go_to_next_step();
1373
+	}
1374
+
1375
+
1376
+	/**
1377
+	 *        add_styles_and_scripts
1378
+	 *
1379
+	 * @access        public
1380
+	 * @return        void
1381
+	 */
1382
+	public function add_styles_and_scripts()
1383
+	{
1384
+		// i18n
1385
+		$this->translate_js_strings();
1386
+		if ($this->checkout->admin_request) {
1387
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1388
+		} else {
1389
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1390
+		}
1391
+	}
1392
+
1393
+
1394
+	/**
1395
+	 *        translate_js_strings
1396
+	 *
1397
+	 * @access        public
1398
+	 * @return        void
1399
+	 */
1400
+	public function translate_js_strings()
1401
+	{
1402
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1403
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1404
+		EE_Registry::$i18n_js_strings['server_error'] = __(
1405
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1406
+			'event_espresso'
1407
+		);
1408
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1409
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1410
+			'event_espresso'
1411
+		);
1412
+		EE_Registry::$i18n_js_strings['validation_error'] = __(
1413
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1414
+			'event_espresso'
1415
+		);
1416
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1417
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1418
+			'event_espresso'
1419
+		);
1420
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1421
+			'This registration step could not be completed. Please refresh the page and try again.',
1422
+			'event_espresso'
1423
+		);
1424
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1425
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1426
+			'event_espresso'
1427
+		);
1428
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1429
+			__(
1430
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1431
+				'event_espresso'
1432
+			),
1433
+			'<br/>',
1434
+			'<br/>'
1435
+		);
1436
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1437
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1438
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1439
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1440
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1441
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1442
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1443
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1444
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1445
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1446
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1447
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1448
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1449
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1450
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1451
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1452
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1453
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1454
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
1455
+		);
1456
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1457
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1458
+			true
1459
+		);
1460
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1461
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1462
+		);
1463
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1464
+			'M d, Y H:i:s',
1465
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1466
+		);
1467
+	}
1468
+
1469
+
1470
+	/**
1471
+	 *    enqueue_styles_and_scripts
1472
+	 *
1473
+	 * @access        public
1474
+	 * @return        void
1475
+	 * @throws EE_Error
1476
+	 */
1477
+	public function enqueue_styles_and_scripts()
1478
+	{
1479
+		// load css
1480
+		wp_register_style(
1481
+			'single_page_checkout',
1482
+			SPCO_CSS_URL . 'single_page_checkout.css',
1483
+			array('espresso_default'),
1484
+			EVENT_ESPRESSO_VERSION
1485
+		);
1486
+		wp_enqueue_style('single_page_checkout');
1487
+		// load JS
1488
+		wp_register_script(
1489
+			'jquery_plugin',
1490
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1491
+			array('jquery'),
1492
+			'1.0.1',
1493
+			true
1494
+		);
1495
+		wp_register_script(
1496
+			'jquery_countdown',
1497
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1498
+			array('jquery_plugin'),
1499
+			'2.0.2',
1500
+			true
1501
+		);
1502
+		wp_register_script(
1503
+			'single_page_checkout',
1504
+			SPCO_JS_URL . 'single_page_checkout.js',
1505
+			array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1506
+			EVENT_ESPRESSO_VERSION,
1507
+			true
1508
+		);
1509
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1510
+			$this->checkout->registration_form->enqueue_js();
1511
+		}
1512
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1513
+			$this->checkout->current_step->reg_form->enqueue_js();
1514
+		}
1515
+		wp_enqueue_script('single_page_checkout');
1516
+		/**
1517
+		 * global action hook for enqueueing styles and scripts with
1518
+		 * spco calls.
1519
+		 */
1520
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1521
+		/**
1522
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1523
+		 * The hook will end up being something like:
1524
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1525
+		 */
1526
+		do_action(
1527
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1528
+			$this
1529
+		);
1530
+	}
1531
+
1532
+
1533
+	/**
1534
+	 *    display the Registration Single Page Checkout Form
1535
+	 *
1536
+	 * @access    private
1537
+	 * @return    void
1538
+	 * @throws EE_Error
1539
+	 */
1540
+	private function _display_spco_reg_form()
1541
+	{
1542
+		// if registering via the admin, just display the reg form for the current step
1543
+		if ($this->checkout->admin_request) {
1544
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1545
+		} else {
1546
+			// add powered by EE msg
1547
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1548
+			$empty_cart = count($this->checkout->transaction
1549
+									->registrations($this->checkout->reg_cache_where_params)) < 1;
1550
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1551
+			$cookies_not_set_msg = '';
1552
+			if ($empty_cart) {
1553
+				$cookies_not_set_msg = apply_filters(
1554
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1555
+					sprintf(
1556
+						__(
1557
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1558
+							'event_espresso'
1559
+						),
1560
+						'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1561
+						'</div>',
1562
+						'<h6 class="important-notice">',
1563
+						'</h6>',
1564
+						'<p>',
1565
+						'</p>',
1566
+						'<br />',
1567
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1568
+						'</a>'
1569
+					)
1570
+				);
1571
+			}
1572
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1573
+				array(
1574
+					'name'            => 'single-page-checkout',
1575
+					'html_id'         => 'ee-single-page-checkout-dv',
1576
+					'layout_strategy' =>
1577
+						new EE_Template_Layout(
1578
+							array(
1579
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1580
+								'template_args'        => array(
1581
+									'empty_cart'              => $empty_cart,
1582
+									'revisit'                 => $this->checkout->revisit,
1583
+									'reg_steps'               => $this->checkout->reg_steps,
1584
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1585
+										? $this->checkout->next_step->slug()
1586
+										: '',
1587
+									'empty_msg'               => apply_filters(
1588
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1589
+										sprintf(
1590
+											__(
1591
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1592
+												'event_espresso'
1593
+											),
1594
+											'<a href="'
1595
+											. get_post_type_archive_link('espresso_events')
1596
+											. '" title="',
1597
+											'">',
1598
+											'</a>'
1599
+										)
1600
+									),
1601
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1602
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1603
+									'session_expiration'      => gmdate(
1604
+										'M d, Y H:i:s',
1605
+										EE_Registry::instance()->SSN->expiration()
1606
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1607
+									),
1608
+								),
1609
+							)
1610
+						),
1611
+				)
1612
+			);
1613
+			// load template and add to output sent that gets filtered into the_content()
1614
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1615
+		}
1616
+	}
1617
+
1618
+
1619
+	/**
1620
+	 *    add_extra_finalize_registration_inputs
1621
+	 *
1622
+	 * @access    public
1623
+	 * @param $next_step
1624
+	 * @internal  param string $label
1625
+	 * @return void
1626
+	 */
1627
+	public function add_extra_finalize_registration_inputs($next_step)
1628
+	{
1629
+		if ($next_step === 'finalize_registration') {
1630
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1631
+		}
1632
+	}
1633
+
1634
+
1635
+	/**
1636
+	 *    display_registration_footer
1637
+	 *
1638
+	 * @access    public
1639
+	 * @return    string
1640
+	 */
1641
+	public static function display_registration_footer()
1642
+	{
1643
+		if (apply_filters(
1644
+			'FHEE__EE_Front__Controller__show_reg_footer',
1645
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1646
+		)) {
1647
+			add_filter(
1648
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1649
+				function ($url) {
1650
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1651
+				}
1652
+			);
1653
+			echo apply_filters(
1654
+				'FHEE__EE_Front_Controller__display_registration_footer',
1655
+				\EEH_Template::powered_by_event_espresso(
1656
+					'',
1657
+					'espresso-registration-footer-dv',
1658
+					array('utm_content' => 'registration_checkout')
1659
+				)
1660
+			);
1661
+		}
1662
+		return '';
1663
+	}
1664
+
1665
+
1666
+	/**
1667
+	 *    unlock_transaction
1668
+	 *
1669
+	 * @access    public
1670
+	 * @return    void
1671
+	 * @throws EE_Error
1672
+	 */
1673
+	public function unlock_transaction()
1674
+	{
1675
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1676
+			$this->checkout->transaction->unlock();
1677
+		}
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 *        _setup_redirect
1683
+	 *
1684
+	 * @access    private
1685
+	 * @return void
1686
+	 */
1687
+	private function _setup_redirect()
1688
+	{
1689
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1690
+			$this->checkout->redirect = true;
1691
+			if (empty($this->checkout->redirect_url)) {
1692
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1693
+			}
1694
+			$this->checkout->redirect_url = apply_filters(
1695
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1696
+				$this->checkout->redirect_url,
1697
+				$this->checkout
1698
+			);
1699
+		}
1700
+	}
1701
+
1702
+
1703
+	/**
1704
+	 *   handle ajax message responses and redirects
1705
+	 *
1706
+	 * @access public
1707
+	 * @return void
1708
+	 * @throws EE_Error
1709
+	 */
1710
+	public function go_to_next_step()
1711
+	{
1712
+		if (EE_Registry::instance()->REQ->ajax) {
1713
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1714
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1715
+		}
1716
+		$this->unlock_transaction();
1717
+		// just return for these conditions
1718
+		if ($this->checkout->admin_request
1719
+			|| $this->checkout->action === 'redirect_form'
1720
+			|| $this->checkout->action === 'update_checkout'
1721
+		) {
1722
+			return;
1723
+		}
1724
+		// AJAX response
1725
+		$this->_handle_json_response();
1726
+		// redirect to next step or the Thank You page
1727
+		$this->_handle_html_redirects();
1728
+		// hmmm... must be something wrong, so let's just display the form again !
1729
+		$this->_display_spco_reg_form();
1730
+	}
1731
+
1732
+
1733
+	/**
1734
+	 *   _handle_json_response
1735
+	 *
1736
+	 * @access protected
1737
+	 * @return void
1738
+	 */
1739
+	protected function _handle_json_response()
1740
+	{
1741
+		// if this is an ajax request
1742
+		if (EE_Registry::instance()->REQ->ajax) {
1743
+			$this->checkout->json_response->set_registration_time_limit(
1744
+				$this->checkout->get_registration_time_limit()
1745
+			);
1746
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1747
+			// just send the ajax (
1748
+			$json_response = apply_filters(
1749
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1750
+				$this->checkout->json_response
1751
+			);
1752
+			echo $json_response;
1753
+			exit();
1754
+		}
1755
+	}
1756
+
1757
+
1758
+	/**
1759
+	 *   _handle_redirects
1760
+	 *
1761
+	 * @access protected
1762
+	 * @return void
1763
+	 */
1764
+	protected function _handle_html_redirects()
1765
+	{
1766
+		// going somewhere ?
1767
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1768
+			// store notices in a transient
1769
+			EE_Error::get_notices(false, true, true);
1770
+			wp_safe_redirect($this->checkout->redirect_url);
1771
+			exit();
1772
+		}
1773
+	}
1774
+
1775
+
1776
+	/**
1777
+	 *   set_checkout_anchor
1778
+	 *
1779
+	 * @access public
1780
+	 * @return void
1781
+	 */
1782
+	public function set_checkout_anchor()
1783
+	{
1784
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1785
+	}
1786
+
1787
+	/**
1788
+	 *    getRegistrationExpirationNotice
1789
+	 *
1790
+	 * @since     4.9.59.p
1791
+	 * @access    public
1792
+	 * @return    string
1793
+	 */
1794
+	public static function getRegistrationExpirationNotice()
1795
+	{
1796
+		return sprintf(
1797
+			__(
1798
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1799
+				'event_espresso'
1800
+			),
1801
+			'<h4 class="important-notice">',
1802
+			'</h4>',
1803
+			'<br />',
1804
+			'<p>',
1805
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1806
+			'">',
1807
+			'</a>',
1808
+			'</p>'
1809
+		);
1810
+	}
1811 1811
 }
Please login to merge, or discard this patch.
Spacing   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
     public static function set_hooks_admin()
101 101
     {
102 102
         EED_Single_Page_Checkout::set_definitions();
103
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
103
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
104 104
             return;
105 105
         }
106 106
         // going to start an output buffer in case anything gets accidentally output
@@ -206,14 +206,14 @@  discard block
 block discarded – undo
206 206
         }
207 207
         define(
208 208
             'SPCO_BASE_PATH',
209
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
209
+            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS
210 210
         );
211
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
212
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
213
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
214
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
215
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
216
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
211
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css'.DS);
212
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img'.DS);
213
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js'.DS);
214
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc'.DS);
215
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps'.DS);
216
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates'.DS);
217 217
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
218 218
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
219 219
         );
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
             // we need a
246 246
             if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
247 247
                 // copy over to the reg_steps_array
248
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
248
+                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
249 249
                 // register custom key route for each reg step
250 250
                 // ie: step=>"slug" - this is the entire reason we load the reg steps array now
251 251
                 EE_Config::register_route(
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
                 // add AJAX or other hooks
258 258
                 if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
259 259
                     // setup autoloaders if necessary
260
-                    if (! class_exists($reg_step['class_name'])) {
260
+                    if ( ! class_exists($reg_step['class_name'])) {
261 261
                         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
262 262
                             $reg_step['file_path'],
263 263
                             true
@@ -285,19 +285,19 @@  discard block
 block discarded – undo
285 285
         if (empty($reg_steps)) {
286 286
             $reg_steps = array(
287 287
                 10  => array(
288
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
288
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
289 289
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
290 290
                     'slug'       => 'attendee_information',
291 291
                     'has_hooks'  => false,
292 292
                 ),
293 293
                 30  => array(
294
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
294
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
295 295
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
296 296
                     'slug'       => 'payment_options',
297 297
                     'has_hooks'  => true,
298 298
                 ),
299 299
                 999 => array(
300
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
300
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
301 301
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
302 302
                     'slug'       => 'finalize_registration',
303 303
                     'has_hooks'  => false,
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
                 $this->checkout
451 451
             );
452 452
             // load the reg steps array
453
-            if (! $this->_load_and_instantiate_reg_steps()) {
453
+            if ( ! $this->_load_and_instantiate_reg_steps()) {
454 454
                 EED_Single_Page_Checkout::$_initialized = true;
455 455
                 return;
456 456
             }
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
             // and the next step
460 460
             $this->checkout->set_next_step();
461 461
             // verify that everything has been setup correctly
462
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
462
+            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
463 463
                 EED_Single_Page_Checkout::$_initialized = true;
464 464
                 return;
465 465
             }
@@ -474,7 +474,7 @@  discard block
 block discarded – undo
474 474
             // DEBUG LOG
475 475
             // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
476 476
             // get reg form
477
-            if (! $this->_check_form_submission()) {
477
+            if ( ! $this->_check_form_submission()) {
478 478
                 EED_Single_Page_Checkout::$_initialized = true;
479 479
                 return;
480 480
             }
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
      */
506 506
     private function _verify_session()
507 507
     {
508
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
508
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
509 509
             throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
510 510
         }
511 511
         $clear_session_requested = filter_var(
@@ -523,7 +523,7 @@  discard block
 block discarded – undo
523 523
             // EE_Registry::instance()->SSN->reset_cart();
524 524
             // EE_Registry::instance()->SSN->reset_checkout();
525 525
             // EE_Registry::instance()->SSN->reset_transaction();
526
-            if (! $clear_session_requested) {
526
+            if ( ! $clear_session_requested) {
527 527
                 EE_Error::add_attention(
528 528
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
529 529
                     __FILE__,
@@ -550,7 +550,7 @@  discard block
 block discarded – undo
550 550
         /** @type EE_Checkout $checkout */
551 551
         $checkout = EE_Registry::instance()->SSN->checkout();
552 552
         // verify
553
-        if (! $checkout instanceof EE_Checkout) {
553
+        if ( ! $checkout instanceof EE_Checkout) {
554 554
             // instantiate EE_Checkout object for handling the properties of the current checkout process
555 555
             $checkout = EE_Registry::instance()->load_file(
556 556
                 SPCO_INC_PATH,
@@ -568,7 +568,7 @@  discard block
 block discarded – undo
568 568
         }
569 569
         $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
570 570
         // verify again
571
-        if (! $checkout instanceof EE_Checkout) {
571
+        if ( ! $checkout instanceof EE_Checkout) {
572 572
             throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
573 573
         }
574 574
         // reset anything that needs a clean slate for each request
@@ -640,7 +640,7 @@  discard block
 block discarded – undo
640 640
      */
641 641
     protected function _display_request_vars()
642 642
     {
643
-        if (! WP_DEBUG) {
643
+        if ( ! WP_DEBUG) {
644 644
             return;
645 645
         }
646 646
         EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
@@ -717,7 +717,7 @@  discard block
 block discarded – undo
717 717
         ) {
718 718
             // if not, then loop through raw reg steps array
719 719
             foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
720
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
720
+                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
721 721
                     return false;
722 722
                 }
723 723
             }
@@ -848,12 +848,12 @@  discard block
 block discarded – undo
848 848
     private function _verify_transaction_and_get_registrations()
849 849
     {
850 850
         // was there already a valid transaction in the checkout from the session ?
851
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
851
+        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
852 852
             // get transaction from db or session
853 853
             $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
854 854
                 ? $this->_get_transaction_and_cart_for_previous_visit()
855 855
                 : $this->_get_cart_for_current_session_and_setup_new_transaction();
856
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
856
+            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
857 857
                 EE_Error::add_error(
858 858
                     __(
859 859
                         'Your Registration and Transaction information could not be retrieved from the db.',
@@ -1084,16 +1084,16 @@  discard block
 block discarded – undo
1084 1084
                         )
1085 1085
                     );
1086 1086
                     // override capabilities for frontend registrations
1087
-                    if (! is_admin()) {
1087
+                    if ( ! is_admin()) {
1088 1088
                         $CreateRegistrationCommand->setCapCheck(
1089 1089
                             new PublicCapabilities('', 'create_new_registration')
1090 1090
                         );
1091 1091
                     }
1092 1092
                     $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1093
-                    if (! $registration instanceof EE_Registration) {
1093
+                    if ( ! $registration instanceof EE_Registration) {
1094 1094
                         throw new InvalidEntityException($registration, 'EE_Registration');
1095 1095
                     }
1096
-                    $registrations[ $registration->ID() ] = $registration;
1096
+                    $registrations[$registration->ID()] = $registration;
1097 1097
                 }
1098 1098
             }
1099 1099
             $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1136,7 +1136,7 @@  discard block
 block discarded – undo
1136 1136
             $this->checkout
1137 1137
         );
1138 1138
         // verify that current step is still set correctly
1139
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1139
+        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1140 1140
             EE_Error::add_error(
1141 1141
                 __(
1142 1142
                     'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
@@ -1149,9 +1149,9 @@  discard block
 block discarded – undo
1149 1149
             return false;
1150 1150
         }
1151 1151
         // if returning to SPCO, then verify that primary registrant is set
1152
-        if (! empty($this->checkout->reg_url_link)) {
1152
+        if ( ! empty($this->checkout->reg_url_link)) {
1153 1153
             $valid_registrant = $this->checkout->transaction->primary_registration();
1154
-            if (! $valid_registrant instanceof EE_Registration) {
1154
+            if ( ! $valid_registrant instanceof EE_Registration) {
1155 1155
                 EE_Error::add_error(
1156 1156
                     __(
1157 1157
                         'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
@@ -1171,7 +1171,7 @@  discard block
 block discarded – undo
1171 1171
                     $valid_registrant = $registration;
1172 1172
                 }
1173 1173
             }
1174
-            if (! $valid_registrant instanceof EE_Registration) {
1174
+            if ( ! $valid_registrant instanceof EE_Registration) {
1175 1175
                 // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1176 1176
                 if (EED_Single_Page_Checkout::$_checkout_verified) {
1177 1177
                     // clear the session, mark the checkout as unverified, and try again
@@ -1215,9 +1215,9 @@  discard block
 block discarded – undo
1215 1215
         $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1216 1216
         // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1217 1217
         foreach ($this->checkout->reg_steps as $reg_step) {
1218
-            if (! $reg_step->initialize_reg_step()) {
1218
+            if ( ! $reg_step->initialize_reg_step()) {
1219 1219
                 // if not initialized then maybe this step is being removed...
1220
-                if (! $reinitializing && $reg_step->is_current_step()) {
1220
+                if ( ! $reinitializing && $reg_step->is_current_step()) {
1221 1221
                     // if it was the current step, then we need to start over here
1222 1222
                     $this->_initialize_reg_steps(true);
1223 1223
                     return;
@@ -1269,7 +1269,7 @@  discard block
 block discarded – undo
1269 1269
                         )
1270 1270
                     );
1271 1271
                     // validate submitted form data
1272
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1272
+                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1273 1273
                         // thou shall not pass !!!
1274 1274
                         $this->checkout->continue_reg = false;
1275 1275
                         // any form validation errors?
@@ -1317,7 +1317,7 @@  discard block
 block discarded – undo
1317 1317
                 break;
1318 1318
             default:
1319 1319
                 // meh... do one of those other steps first
1320
-                if (! empty($this->checkout->action)
1320
+                if ( ! empty($this->checkout->action)
1321 1321
                     && is_callable(array($this->checkout->current_step, $this->checkout->action))
1322 1322
                 ) {
1323 1323
                     // dynamically creates hook point like:
@@ -1337,7 +1337,7 @@  discard block
 block discarded – undo
1337 1337
                         ) {
1338 1338
                             EE_Error::add_success(
1339 1339
                                 $this->checkout->current_step->success_message()
1340
-                                . '<br />' . $this->checkout->next_step->_instructions()
1340
+                                . '<br />'.$this->checkout->next_step->_instructions()
1341 1341
                             );
1342 1342
                         }
1343 1343
                         // pack it up, pack it in...
@@ -1479,7 +1479,7 @@  discard block
 block discarded – undo
1479 1479
         // load css
1480 1480
         wp_register_style(
1481 1481
             'single_page_checkout',
1482
-            SPCO_CSS_URL . 'single_page_checkout.css',
1482
+            SPCO_CSS_URL.'single_page_checkout.css',
1483 1483
             array('espresso_default'),
1484 1484
             EVENT_ESPRESSO_VERSION
1485 1485
         );
@@ -1487,21 +1487,21 @@  discard block
 block discarded – undo
1487 1487
         // load JS
1488 1488
         wp_register_script(
1489 1489
             'jquery_plugin',
1490
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1490
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1491 1491
             array('jquery'),
1492 1492
             '1.0.1',
1493 1493
             true
1494 1494
         );
1495 1495
         wp_register_script(
1496 1496
             'jquery_countdown',
1497
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1497
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1498 1498
             array('jquery_plugin'),
1499 1499
             '2.0.2',
1500 1500
             true
1501 1501
         );
1502 1502
         wp_register_script(
1503 1503
             'single_page_checkout',
1504
-            SPCO_JS_URL . 'single_page_checkout.js',
1504
+            SPCO_JS_URL.'single_page_checkout.js',
1505 1505
             array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1506 1506
             EVENT_ESPRESSO_VERSION,
1507 1507
             true
@@ -1524,7 +1524,7 @@  discard block
 block discarded – undo
1524 1524
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1525 1525
          */
1526 1526
         do_action(
1527
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1527
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1528 1528
             $this
1529 1529
         );
1530 1530
     }
@@ -1576,7 +1576,7 @@  discard block
 block discarded – undo
1576 1576
                     'layout_strategy' =>
1577 1577
                         new EE_Template_Layout(
1578 1578
                             array(
1579
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1579
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1580 1580
                                 'template_args'        => array(
1581 1581
                                     'empty_cart'              => $empty_cart,
1582 1582
                                     'revisit'                 => $this->checkout->revisit,
@@ -1646,7 +1646,7 @@  discard block
 block discarded – undo
1646 1646
         )) {
1647 1647
             add_filter(
1648 1648
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1649
-                function ($url) {
1649
+                function($url) {
1650 1650
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1651 1651
                 }
1652 1652
             );
@@ -1802,7 +1802,7 @@  discard block
 block discarded – undo
1802 1802
             '</h4>',
1803 1803
             '<br />',
1804 1804
             '<p>',
1805
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1805
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1806 1806
             '">',
1807 1807
             '</a>',
1808 1808
             '</p>'
Please login to merge, or discard this patch.
core/EE_Cart.core.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
      * @access  public
261 261
      * @param EE_Ticket $ticket
262 262
      * @param int       $qty
263
-     * @return TRUE on success, FALSE on fail
263
+     * @return boolean on success, FALSE on fail
264 264
      * @throws \EE_Error
265 265
      */
266 266
     public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
@@ -385,7 +385,7 @@  discard block
 block discarded – undo
385 385
      * @save   cart to session
386 386
      * @access public
387 387
      * @param bool $apply_taxes
388
-     * @return TRUE on success, FALSE on fail
388
+     * @return boolean on success, FALSE on fail
389 389
      * @throws \EE_Error
390 390
      */
391 391
     public function save_cart($apply_taxes = true)
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
 
420 420
 
421 421
     /**
422
-     * @return array
422
+     * @return string[]
423 423
      */
424 424
     public function __sleep()
425 425
     {
Please login to merge, or discard this patch.
Indentation   +392 added lines, -392 removed lines patch added patch discarded remove patch
@@ -17,396 +17,396 @@
 block discarded – undo
17 17
 class EE_Cart implements ResettableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * instance of the EE_Cart object
22
-     *
23
-     * @access    private
24
-     * @var EE_Cart $_instance
25
-     */
26
-    private static $_instance;
27
-
28
-    /**
29
-     * instance of the EE_Session object
30
-     *
31
-     * @access    protected
32
-     * @var EE_Session $_session
33
-     */
34
-    protected $_session;
35
-
36
-    /**
37
-     * The total Line item which comprises all the children line-item subtotals,
38
-     * which in turn each have their line items.
39
-     * Typically, the line item structure will look like:
40
-     * grand total
41
-     * -tickets-sub-total
42
-     * --ticket1
43
-     * --ticket2
44
-     * --...
45
-     * -taxes-sub-total
46
-     * --tax1
47
-     * --tax2
48
-     *
49
-     * @var EE_Line_Item
50
-     */
51
-    private $_grand_total;
52
-
53
-
54
-    /**
55
-     * @singleton method used to instantiate class object
56
-     * @access    public
57
-     * @param EE_Line_Item $grand_total
58
-     * @param EE_Session   $session
59
-     * @return \EE_Cart
60
-     * @throws \EE_Error
61
-     */
62
-    public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
63
-    {
64
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
65
-            self::$_instance = new self($grand_total, $session);
66
-        }
67
-        // or maybe retrieve an existing one ?
68
-        if (! self::$_instance instanceof EE_Cart) {
69
-            // try getting the cart out of the session
70
-            $saved_cart = $session instanceof EE_Session ? $session->cart() : null;
71
-            self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
72
-            unset($saved_cart);
73
-        }
74
-        // verify that cart is ok and grand total line item exists
75
-        if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
76
-            self::$_instance = new self($grand_total, $session);
77
-        }
78
-        self::$_instance->get_grand_total();
79
-        // once everything is all said and done, save the cart to the EE_Session
80
-        add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
81
-        return self::$_instance;
82
-    }
83
-
84
-
85
-    /**
86
-     * private constructor to prevent direct creation
87
-     *
88
-     * @Constructor
89
-     * @access private
90
-     * @param EE_Line_Item $grand_total
91
-     * @param EE_Session   $session
92
-     */
93
-    private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
94
-    {
95
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
96
-        $this->set_session($session);
97
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
98
-            $this->set_grand_total_line_item($grand_total);
99
-        }
100
-    }
101
-
102
-
103
-    /**
104
-     * Resets the cart completely (whereas empty_cart
105
-     *
106
-     * @param EE_Line_Item $grand_total
107
-     * @param EE_Session   $session
108
-     * @return EE_Cart
109
-     * @throws \EE_Error
110
-     */
111
-    public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
112
-    {
113
-        remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
114
-        if ($session instanceof EE_Session) {
115
-            $session->reset_cart();
116
-        }
117
-        self::$_instance = null;
118
-        return self::instance($grand_total, $session);
119
-    }
120
-
121
-
122
-    /**
123
-     * @return \EE_Session
124
-     */
125
-    public function session()
126
-    {
127
-        if (! $this->_session instanceof EE_Session) {
128
-            $this->set_session();
129
-        }
130
-        return $this->_session;
131
-    }
132
-
133
-
134
-    /**
135
-     * @param EE_Session $session
136
-     */
137
-    public function set_session(EE_Session $session = null)
138
-    {
139
-        $this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
140
-    }
141
-
142
-
143
-    /**
144
-     * Sets the cart to match the line item. Especially handy for loading an old cart where you
145
-     *  know the grand total line item on it
146
-     *
147
-     * @param EE_Line_Item $line_item
148
-     */
149
-    public function set_grand_total_line_item(EE_Line_Item $line_item)
150
-    {
151
-        $this->_grand_total = $line_item;
152
-    }
153
-
154
-
155
-    /**
156
-     * get_cart_from_reg_url_link
157
-     *
158
-     * @access public
159
-     * @param EE_Transaction $transaction
160
-     * @param EE_Session     $session
161
-     * @return \EE_Cart
162
-     * @throws \EE_Error
163
-     */
164
-    public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
165
-    {
166
-        $grand_total = $transaction->total_line_item();
167
-        $grand_total->get_items();
168
-        $grand_total->tax_descendants();
169
-        return EE_Cart::instance($grand_total, $session);
170
-    }
171
-
172
-
173
-    /**
174
-     * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
175
-     *
176
-     * @return EE_Line_Item
177
-     * @throws \EE_Error
178
-     */
179
-    private function _create_grand_total()
180
-    {
181
-        $this->_grand_total = EEH_Line_Item::create_total_line_item();
182
-        return $this->_grand_total;
183
-    }
184
-
185
-
186
-    /**
187
-     * Gets all the line items of object type Ticket
188
-     *
189
-     * @access public
190
-     * @return \EE_Line_Item[]
191
-     */
192
-    public function get_tickets()
193
-    {
194
-        if ($this->_grand_total === null) {
195
-            return array();
196
-        }
197
-        return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
198
-    }
199
-
200
-
201
-    /**
202
-     * returns the total quantity of tickets in the cart
203
-     *
204
-     * @access public
205
-     * @return int
206
-     * @throws \EE_Error
207
-     */
208
-    public function all_ticket_quantity_count()
209
-    {
210
-        $tickets = $this->get_tickets();
211
-        if (empty($tickets)) {
212
-            return 0;
213
-        }
214
-        $count = 0;
215
-        foreach ($tickets as $ticket) {
216
-            $count += $ticket->get('LIN_quantity');
217
-        }
218
-        return $count;
219
-    }
220
-
221
-
222
-    /**
223
-     * Gets all the tax line items
224
-     *
225
-     * @return \EE_Line_Item[]
226
-     * @throws \EE_Error
227
-     */
228
-    public function get_taxes()
229
-    {
230
-        return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
231
-    }
232
-
233
-
234
-    /**
235
-     * Gets the total line item (which is a parent of all other line items) on this cart
236
-     *
237
-     * @return EE_Line_Item
238
-     * @throws \EE_Error
239
-     */
240
-    public function get_grand_total()
241
-    {
242
-        return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
243
-    }
244
-
245
-
246
-    /**
247
-     * @process items for adding to cart
248
-     * @access  public
249
-     * @param EE_Ticket $ticket
250
-     * @param int       $qty
251
-     * @return TRUE on success, FALSE on fail
252
-     * @throws \EE_Error
253
-     */
254
-    public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
255
-    {
256
-        EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
257
-        return $this->save_cart() ? true : false;
258
-    }
259
-
260
-
261
-    /**
262
-     * get_cart_total_before_tax
263
-     *
264
-     * @access public
265
-     * @return float
266
-     * @throws \EE_Error
267
-     */
268
-    public function get_cart_total_before_tax()
269
-    {
270
-        return $this->get_grand_total()->recalculate_pre_tax_total();
271
-    }
272
-
273
-
274
-    /**
275
-     * gets the total amount of tax paid for items in this cart
276
-     *
277
-     * @access public
278
-     * @return float
279
-     * @throws \EE_Error
280
-     */
281
-    public function get_applied_taxes()
282
-    {
283
-        return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
284
-    }
285
-
286
-
287
-    /**
288
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
289
-     *
290
-     * @access public
291
-     * @return float
292
-     * @throws \EE_Error
293
-     */
294
-    public function get_cart_grand_total()
295
-    {
296
-        EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
297
-        return $this->get_grand_total()->total();
298
-    }
299
-
300
-
301
-    /**
302
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
303
-     *
304
-     * @access public
305
-     * @return float
306
-     * @throws \EE_Error
307
-     */
308
-    public function recalculate_all_cart_totals()
309
-    {
310
-        $pre_tax_total = $this->get_cart_total_before_tax();
311
-        $taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
312
-        $this->_grand_total->set_total($pre_tax_total + $taxes_total);
313
-        $this->_grand_total->save_this_and_descendants_to_txn();
314
-        return $this->get_grand_total()->total();
315
-    }
316
-
317
-
318
-    /**
319
-     * deletes an item from the cart
320
-     *
321
-     * @access public
322
-     * @param array|bool|string $line_item_codes
323
-     * @return int on success, FALSE on fail
324
-     * @throws \EE_Error
325
-     */
326
-    public function delete_items($line_item_codes = false)
327
-    {
328
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
329
-        return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
330
-    }
331
-
332
-
333
-    /**
334
-     * @remove ALL items from cart and zero ALL totals
335
-     * @access public
336
-     * @return bool
337
-     * @throws \EE_Error
338
-     */
339
-    public function empty_cart()
340
-    {
341
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
342
-        $this->_grand_total = $this->_create_grand_total();
343
-        return $this->save_cart(true);
344
-    }
345
-
346
-
347
-    /**
348
-     * @remove ALL items from cart and delete total as well
349
-     * @access public
350
-     * @return bool
351
-     * @throws \EE_Error
352
-     */
353
-    public function delete_cart()
354
-    {
355
-        if ($this->_grand_total instanceof EE_Line_Item) {
356
-            $deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
357
-            if ($deleted) {
358
-                $deleted += $this->_grand_total->delete();
359
-                $this->_grand_total = null;
360
-                return true;
361
-            }
362
-        }
363
-        return false;
364
-    }
365
-
366
-
367
-    /**
368
-     * @save   cart to session
369
-     * @access public
370
-     * @param bool $apply_taxes
371
-     * @return TRUE on success, FALSE on fail
372
-     * @throws \EE_Error
373
-     */
374
-    public function save_cart($apply_taxes = true)
375
-    {
376
-        if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
377
-            EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
378
-            // make sure we don't cache the transaction because it can get stale
379
-            if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
380
-                && $this->_grand_total->get_one_from_cache('Transaction')->ID()
381
-            ) {
382
-                $this->_grand_total->clear_cache('Transaction', null, true);
383
-            }
384
-        }
385
-        if ($this->session() instanceof EE_Session) {
386
-            return $this->session()->set_cart($this);
387
-        } else {
388
-            return false;
389
-        }
390
-    }
391
-
392
-
393
-    public function __wakeup()
394
-    {
395
-        if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
396
-            // $this->_grand_total is actually just an ID, so use it to get the object from the db
397
-            $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
398
-        }
399
-    }
400
-
401
-
402
-    /**
403
-     * @return array
404
-     */
405
-    public function __sleep()
406
-    {
407
-        if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
408
-            $this->_grand_total = $this->_grand_total->ID();
409
-        }
410
-        return array('_grand_total');
411
-    }
20
+	/**
21
+	 * instance of the EE_Cart object
22
+	 *
23
+	 * @access    private
24
+	 * @var EE_Cart $_instance
25
+	 */
26
+	private static $_instance;
27
+
28
+	/**
29
+	 * instance of the EE_Session object
30
+	 *
31
+	 * @access    protected
32
+	 * @var EE_Session $_session
33
+	 */
34
+	protected $_session;
35
+
36
+	/**
37
+	 * The total Line item which comprises all the children line-item subtotals,
38
+	 * which in turn each have their line items.
39
+	 * Typically, the line item structure will look like:
40
+	 * grand total
41
+	 * -tickets-sub-total
42
+	 * --ticket1
43
+	 * --ticket2
44
+	 * --...
45
+	 * -taxes-sub-total
46
+	 * --tax1
47
+	 * --tax2
48
+	 *
49
+	 * @var EE_Line_Item
50
+	 */
51
+	private $_grand_total;
52
+
53
+
54
+	/**
55
+	 * @singleton method used to instantiate class object
56
+	 * @access    public
57
+	 * @param EE_Line_Item $grand_total
58
+	 * @param EE_Session   $session
59
+	 * @return \EE_Cart
60
+	 * @throws \EE_Error
61
+	 */
62
+	public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
63
+	{
64
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
65
+			self::$_instance = new self($grand_total, $session);
66
+		}
67
+		// or maybe retrieve an existing one ?
68
+		if (! self::$_instance instanceof EE_Cart) {
69
+			// try getting the cart out of the session
70
+			$saved_cart = $session instanceof EE_Session ? $session->cart() : null;
71
+			self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
72
+			unset($saved_cart);
73
+		}
74
+		// verify that cart is ok and grand total line item exists
75
+		if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
76
+			self::$_instance = new self($grand_total, $session);
77
+		}
78
+		self::$_instance->get_grand_total();
79
+		// once everything is all said and done, save the cart to the EE_Session
80
+		add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
81
+		return self::$_instance;
82
+	}
83
+
84
+
85
+	/**
86
+	 * private constructor to prevent direct creation
87
+	 *
88
+	 * @Constructor
89
+	 * @access private
90
+	 * @param EE_Line_Item $grand_total
91
+	 * @param EE_Session   $session
92
+	 */
93
+	private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
94
+	{
95
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
96
+		$this->set_session($session);
97
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
98
+			$this->set_grand_total_line_item($grand_total);
99
+		}
100
+	}
101
+
102
+
103
+	/**
104
+	 * Resets the cart completely (whereas empty_cart
105
+	 *
106
+	 * @param EE_Line_Item $grand_total
107
+	 * @param EE_Session   $session
108
+	 * @return EE_Cart
109
+	 * @throws \EE_Error
110
+	 */
111
+	public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
112
+	{
113
+		remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
114
+		if ($session instanceof EE_Session) {
115
+			$session->reset_cart();
116
+		}
117
+		self::$_instance = null;
118
+		return self::instance($grand_total, $session);
119
+	}
120
+
121
+
122
+	/**
123
+	 * @return \EE_Session
124
+	 */
125
+	public function session()
126
+	{
127
+		if (! $this->_session instanceof EE_Session) {
128
+			$this->set_session();
129
+		}
130
+		return $this->_session;
131
+	}
132
+
133
+
134
+	/**
135
+	 * @param EE_Session $session
136
+	 */
137
+	public function set_session(EE_Session $session = null)
138
+	{
139
+		$this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
140
+	}
141
+
142
+
143
+	/**
144
+	 * Sets the cart to match the line item. Especially handy for loading an old cart where you
145
+	 *  know the grand total line item on it
146
+	 *
147
+	 * @param EE_Line_Item $line_item
148
+	 */
149
+	public function set_grand_total_line_item(EE_Line_Item $line_item)
150
+	{
151
+		$this->_grand_total = $line_item;
152
+	}
153
+
154
+
155
+	/**
156
+	 * get_cart_from_reg_url_link
157
+	 *
158
+	 * @access public
159
+	 * @param EE_Transaction $transaction
160
+	 * @param EE_Session     $session
161
+	 * @return \EE_Cart
162
+	 * @throws \EE_Error
163
+	 */
164
+	public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
165
+	{
166
+		$grand_total = $transaction->total_line_item();
167
+		$grand_total->get_items();
168
+		$grand_total->tax_descendants();
169
+		return EE_Cart::instance($grand_total, $session);
170
+	}
171
+
172
+
173
+	/**
174
+	 * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
175
+	 *
176
+	 * @return EE_Line_Item
177
+	 * @throws \EE_Error
178
+	 */
179
+	private function _create_grand_total()
180
+	{
181
+		$this->_grand_total = EEH_Line_Item::create_total_line_item();
182
+		return $this->_grand_total;
183
+	}
184
+
185
+
186
+	/**
187
+	 * Gets all the line items of object type Ticket
188
+	 *
189
+	 * @access public
190
+	 * @return \EE_Line_Item[]
191
+	 */
192
+	public function get_tickets()
193
+	{
194
+		if ($this->_grand_total === null) {
195
+			return array();
196
+		}
197
+		return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
198
+	}
199
+
200
+
201
+	/**
202
+	 * returns the total quantity of tickets in the cart
203
+	 *
204
+	 * @access public
205
+	 * @return int
206
+	 * @throws \EE_Error
207
+	 */
208
+	public function all_ticket_quantity_count()
209
+	{
210
+		$tickets = $this->get_tickets();
211
+		if (empty($tickets)) {
212
+			return 0;
213
+		}
214
+		$count = 0;
215
+		foreach ($tickets as $ticket) {
216
+			$count += $ticket->get('LIN_quantity');
217
+		}
218
+		return $count;
219
+	}
220
+
221
+
222
+	/**
223
+	 * Gets all the tax line items
224
+	 *
225
+	 * @return \EE_Line_Item[]
226
+	 * @throws \EE_Error
227
+	 */
228
+	public function get_taxes()
229
+	{
230
+		return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
231
+	}
232
+
233
+
234
+	/**
235
+	 * Gets the total line item (which is a parent of all other line items) on this cart
236
+	 *
237
+	 * @return EE_Line_Item
238
+	 * @throws \EE_Error
239
+	 */
240
+	public function get_grand_total()
241
+	{
242
+		return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
243
+	}
244
+
245
+
246
+	/**
247
+	 * @process items for adding to cart
248
+	 * @access  public
249
+	 * @param EE_Ticket $ticket
250
+	 * @param int       $qty
251
+	 * @return TRUE on success, FALSE on fail
252
+	 * @throws \EE_Error
253
+	 */
254
+	public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
255
+	{
256
+		EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
257
+		return $this->save_cart() ? true : false;
258
+	}
259
+
260
+
261
+	/**
262
+	 * get_cart_total_before_tax
263
+	 *
264
+	 * @access public
265
+	 * @return float
266
+	 * @throws \EE_Error
267
+	 */
268
+	public function get_cart_total_before_tax()
269
+	{
270
+		return $this->get_grand_total()->recalculate_pre_tax_total();
271
+	}
272
+
273
+
274
+	/**
275
+	 * gets the total amount of tax paid for items in this cart
276
+	 *
277
+	 * @access public
278
+	 * @return float
279
+	 * @throws \EE_Error
280
+	 */
281
+	public function get_applied_taxes()
282
+	{
283
+		return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
284
+	}
285
+
286
+
287
+	/**
288
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
289
+	 *
290
+	 * @access public
291
+	 * @return float
292
+	 * @throws \EE_Error
293
+	 */
294
+	public function get_cart_grand_total()
295
+	{
296
+		EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
297
+		return $this->get_grand_total()->total();
298
+	}
299
+
300
+
301
+	/**
302
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
303
+	 *
304
+	 * @access public
305
+	 * @return float
306
+	 * @throws \EE_Error
307
+	 */
308
+	public function recalculate_all_cart_totals()
309
+	{
310
+		$pre_tax_total = $this->get_cart_total_before_tax();
311
+		$taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
312
+		$this->_grand_total->set_total($pre_tax_total + $taxes_total);
313
+		$this->_grand_total->save_this_and_descendants_to_txn();
314
+		return $this->get_grand_total()->total();
315
+	}
316
+
317
+
318
+	/**
319
+	 * deletes an item from the cart
320
+	 *
321
+	 * @access public
322
+	 * @param array|bool|string $line_item_codes
323
+	 * @return int on success, FALSE on fail
324
+	 * @throws \EE_Error
325
+	 */
326
+	public function delete_items($line_item_codes = false)
327
+	{
328
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
329
+		return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
330
+	}
331
+
332
+
333
+	/**
334
+	 * @remove ALL items from cart and zero ALL totals
335
+	 * @access public
336
+	 * @return bool
337
+	 * @throws \EE_Error
338
+	 */
339
+	public function empty_cart()
340
+	{
341
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
342
+		$this->_grand_total = $this->_create_grand_total();
343
+		return $this->save_cart(true);
344
+	}
345
+
346
+
347
+	/**
348
+	 * @remove ALL items from cart and delete total as well
349
+	 * @access public
350
+	 * @return bool
351
+	 * @throws \EE_Error
352
+	 */
353
+	public function delete_cart()
354
+	{
355
+		if ($this->_grand_total instanceof EE_Line_Item) {
356
+			$deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
357
+			if ($deleted) {
358
+				$deleted += $this->_grand_total->delete();
359
+				$this->_grand_total = null;
360
+				return true;
361
+			}
362
+		}
363
+		return false;
364
+	}
365
+
366
+
367
+	/**
368
+	 * @save   cart to session
369
+	 * @access public
370
+	 * @param bool $apply_taxes
371
+	 * @return TRUE on success, FALSE on fail
372
+	 * @throws \EE_Error
373
+	 */
374
+	public function save_cart($apply_taxes = true)
375
+	{
376
+		if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
377
+			EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
378
+			// make sure we don't cache the transaction because it can get stale
379
+			if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
380
+				&& $this->_grand_total->get_one_from_cache('Transaction')->ID()
381
+			) {
382
+				$this->_grand_total->clear_cache('Transaction', null, true);
383
+			}
384
+		}
385
+		if ($this->session() instanceof EE_Session) {
386
+			return $this->session()->set_cart($this);
387
+		} else {
388
+			return false;
389
+		}
390
+	}
391
+
392
+
393
+	public function __wakeup()
394
+	{
395
+		if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
396
+			// $this->_grand_total is actually just an ID, so use it to get the object from the db
397
+			$this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
398
+		}
399
+	}
400
+
401
+
402
+	/**
403
+	 * @return array
404
+	 */
405
+	public function __sleep()
406
+	{
407
+		if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
408
+			$this->_grand_total = $this->_grand_total->ID();
409
+		}
410
+		return array('_grand_total');
411
+	}
412 412
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -65,14 +65,14 @@  discard block
 block discarded – undo
65 65
             self::$_instance = new self($grand_total, $session);
66 66
         }
67 67
         // or maybe retrieve an existing one ?
68
-        if (! self::$_instance instanceof EE_Cart) {
68
+        if ( ! self::$_instance instanceof EE_Cart) {
69 69
             // try getting the cart out of the session
70 70
             $saved_cart = $session instanceof EE_Session ? $session->cart() : null;
71 71
             self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
72 72
             unset($saved_cart);
73 73
         }
74 74
         // verify that cart is ok and grand total line item exists
75
-        if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
75
+        if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
76 76
             self::$_instance = new self($grand_total, $session);
77 77
         }
78 78
         self::$_instance->get_grand_total();
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
      */
125 125
     public function session()
126 126
     {
127
-        if (! $this->_session instanceof EE_Session) {
127
+        if ( ! $this->_session instanceof EE_Session) {
128 128
             $this->set_session();
129 129
         }
130 130
         return $this->_session;
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
 
393 393
     public function __wakeup()
394 394
     {
395
-        if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
395
+        if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
396 396
             // $this->_grand_total is actually just an ID, so use it to get the object from the db
397 397
             $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
398 398
         }
Please login to merge, or discard this patch.
core/helpers/EEH_Activation.helper.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
      *
614 614
      * @since  4.6.0
615 615
      * @global WPDB $wpdb
616
-     * @return mixed null|int WP_user ID or NULL
616
+     * @return integer|null null|int WP_user ID or NULL
617 617
      */
618 618
     public static function get_default_creator_id()
619 619
     {
@@ -774,7 +774,7 @@  discard block
 block discarded – undo
774 774
      * @static
775 775
      * @deprecated instead use TableManager::dropTable()
776 776
      * @param string $table_name
777
-     * @return bool | int
777
+     * @return integer | int
778 778
      */
779 779
     public static function delete_unused_db_table($table_name)
780 780
     {
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
      * @deprecated instead use TableManager::dropIndex()
792 792
      * @param string $table_name
793 793
      * @param string $index_name
794
-     * @return bool | int
794
+     * @return integer | int
795 795
      */
796 796
     public static function drop_index($table_name, $index_name)
797 797
     {
Please login to merge, or discard this patch.
Indentation   +1576 added lines, -1576 removed lines patch added patch discarded remove patch
@@ -15,232 +15,232 @@  discard block
 block discarded – undo
15 15
 class EEH_Activation implements ResettableInterface
16 16
 {
17 17
 
18
-    /**
19
-     * constant used to indicate a cron task is no longer in use
20
-     */
21
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
22
-
23
-    /**
24
-     * WP_User->ID
25
-     *
26
-     * @var int
27
-     */
28
-    private static $_default_creator_id;
29
-
30
-    /**
31
-     * indicates whether or not we've already verified core's default data during this request,
32
-     * because after migrations are done, any addons activated while in maintenance mode
33
-     * will want to setup their own default data, and they might hook into core's default data
34
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
35
-     * This prevents doing that for EVERY single addon.
36
-     *
37
-     * @var boolean
38
-     */
39
-    protected static $_initialized_db_content_already_in_this_request = false;
40
-
41
-    /**
42
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
43
-     */
44
-    private static $table_analysis;
45
-
46
-    /**
47
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
48
-     */
49
-    private static $table_manager;
50
-
51
-
52
-    /**
53
-     * @return \EventEspresso\core\services\database\TableAnalysis
54
-     */
55
-    public static function getTableAnalysis()
56
-    {
57
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
58
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
59
-        }
60
-        return self::$table_analysis;
61
-    }
62
-
63
-
64
-    /**
65
-     * @return \EventEspresso\core\services\database\TableManager
66
-     */
67
-    public static function getTableManager()
68
-    {
69
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
70
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
71
-        }
72
-        return self::$table_manager;
73
-    }
74
-
75
-
76
-    /**
77
-     *    _ensure_table_name_has_prefix
78
-     *
79
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
80
-     * @access     public
81
-     * @static
82
-     * @param $table_name
83
-     * @return string
84
-     */
85
-    public static function ensure_table_name_has_prefix($table_name)
86
-    {
87
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
88
-    }
89
-
90
-
91
-    /**
92
-     *    system_initialization
93
-     *    ensures the EE configuration settings are loaded with at least default options set
94
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
95
-     *
96
-     * @access public
97
-     * @static
98
-     * @return void
99
-     */
100
-    public static function system_initialization()
101
-    {
102
-        EEH_Activation::reset_and_update_config();
103
-        // which is fired BEFORE activation of plugin anyways
104
-        EEH_Activation::verify_default_pages_exist();
105
-    }
106
-
107
-
108
-    /**
109
-     * Sets the database schema and creates folders. This should
110
-     * be called on plugin activation and reactivation
111
-     *
112
-     * @return boolean success, whether the database and folders are setup properly
113
-     * @throws \EE_Error
114
-     */
115
-    public static function initialize_db_and_folders()
116
-    {
117
-        return EEH_Activation::create_database_tables();
118
-    }
119
-
120
-
121
-    /**
122
-     * assuming we have an up-to-date database schema, this will populate it
123
-     * with default and initial data. This should be called
124
-     * upon activation of a new plugin, reactivation, and at the end
125
-     * of running migration scripts
126
-     *
127
-     * @throws \EE_Error
128
-     */
129
-    public static function initialize_db_content()
130
-    {
131
-        // let's avoid doing all this logic repeatedly, especially when addons are requesting it
132
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
133
-            return;
134
-        }
135
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
136
-
137
-        EEH_Activation::initialize_system_questions();
138
-        EEH_Activation::insert_default_status_codes();
139
-        EEH_Activation::generate_default_message_templates();
140
-        EEH_Activation::create_no_ticket_prices_array();
141
-
142
-        EEH_Activation::validate_messages_system();
143
-        EEH_Activation::insert_default_payment_methods();
144
-        // in case we've
145
-        EEH_Activation::remove_cron_tasks();
146
-        EEH_Activation::create_cron_tasks();
147
-        // remove all TXN locks since that is being done via extra meta now
148
-        delete_option('ee_locked_transactions');
149
-        // also, check for CAF default db content
150
-        do_action('AHEE__EEH_Activation__initialize_db_content');
151
-        // also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
152
-        // which users really won't care about on initial activation
153
-        EE_Error::overwrite_success();
154
-    }
155
-
156
-
157
-    /**
158
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
159
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
160
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
161
-     * (null)
162
-     *
163
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
164
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
165
-     * @return array
166
-     * @throws \EE_Error
167
-     */
168
-    public static function get_cron_tasks($which_to_include)
169
-    {
170
-        $cron_tasks = apply_filters(
171
-            'FHEE__EEH_Activation__get_cron_tasks',
172
-            array(
173
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
174
-            //              'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
175
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
176
-                // there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
177
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
178
-            )
179
-        );
180
-        if ($which_to_include === 'old') {
181
-            $cron_tasks = array_filter(
182
-                $cron_tasks,
183
-                function ($value) {
184
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
185
-                }
186
-            );
187
-        } elseif ($which_to_include === 'current') {
188
-            $cron_tasks = array_filter($cron_tasks);
189
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
190
-            throw new EE_Error(
191
-                sprintf(
192
-                    __(
193
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
194
-                        'event_espresso'
195
-                    ),
196
-                    $which_to_include
197
-                )
198
-            );
199
-        }
200
-        return $cron_tasks;
201
-    }
202
-
203
-
204
-    /**
205
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
206
-     *
207
-     * @throws \EE_Error
208
-     */
209
-    public static function create_cron_tasks()
210
-    {
211
-
212
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
213
-            if (! wp_next_scheduled($hook_name)) {
214
-                /**
215
-                 * This allows client code to define the initial start timestamp for this schedule.
216
-                 */
217
-                if (is_array($frequency)
218
-                    && count($frequency) === 2
219
-                    && isset($frequency[0], $frequency[1])
220
-                ) {
221
-                    $start_timestamp = $frequency[0];
222
-                    $frequency = $frequency[1];
223
-                } else {
224
-                    $start_timestamp = time();
225
-                }
226
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
227
-            }
228
-        }
229
-    }
230
-
231
-
232
-    /**
233
-     * Remove the currently-existing and now-removed cron tasks.
234
-     *
235
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
236
-     * @throws \EE_Error
237
-     */
238
-    public static function remove_cron_tasks($remove_all = true)
239
-    {
240
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
241
-        $crons                = _get_cron_array();
242
-        $crons                = is_array($crons) ? $crons : array();
243
-        /* reminder of what $crons look like:
18
+	/**
19
+	 * constant used to indicate a cron task is no longer in use
20
+	 */
21
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
22
+
23
+	/**
24
+	 * WP_User->ID
25
+	 *
26
+	 * @var int
27
+	 */
28
+	private static $_default_creator_id;
29
+
30
+	/**
31
+	 * indicates whether or not we've already verified core's default data during this request,
32
+	 * because after migrations are done, any addons activated while in maintenance mode
33
+	 * will want to setup their own default data, and they might hook into core's default data
34
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
35
+	 * This prevents doing that for EVERY single addon.
36
+	 *
37
+	 * @var boolean
38
+	 */
39
+	protected static $_initialized_db_content_already_in_this_request = false;
40
+
41
+	/**
42
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
43
+	 */
44
+	private static $table_analysis;
45
+
46
+	/**
47
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
48
+	 */
49
+	private static $table_manager;
50
+
51
+
52
+	/**
53
+	 * @return \EventEspresso\core\services\database\TableAnalysis
54
+	 */
55
+	public static function getTableAnalysis()
56
+	{
57
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
58
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
59
+		}
60
+		return self::$table_analysis;
61
+	}
62
+
63
+
64
+	/**
65
+	 * @return \EventEspresso\core\services\database\TableManager
66
+	 */
67
+	public static function getTableManager()
68
+	{
69
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
70
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
71
+		}
72
+		return self::$table_manager;
73
+	}
74
+
75
+
76
+	/**
77
+	 *    _ensure_table_name_has_prefix
78
+	 *
79
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
80
+	 * @access     public
81
+	 * @static
82
+	 * @param $table_name
83
+	 * @return string
84
+	 */
85
+	public static function ensure_table_name_has_prefix($table_name)
86
+	{
87
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
88
+	}
89
+
90
+
91
+	/**
92
+	 *    system_initialization
93
+	 *    ensures the EE configuration settings are loaded with at least default options set
94
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
95
+	 *
96
+	 * @access public
97
+	 * @static
98
+	 * @return void
99
+	 */
100
+	public static function system_initialization()
101
+	{
102
+		EEH_Activation::reset_and_update_config();
103
+		// which is fired BEFORE activation of plugin anyways
104
+		EEH_Activation::verify_default_pages_exist();
105
+	}
106
+
107
+
108
+	/**
109
+	 * Sets the database schema and creates folders. This should
110
+	 * be called on plugin activation and reactivation
111
+	 *
112
+	 * @return boolean success, whether the database and folders are setup properly
113
+	 * @throws \EE_Error
114
+	 */
115
+	public static function initialize_db_and_folders()
116
+	{
117
+		return EEH_Activation::create_database_tables();
118
+	}
119
+
120
+
121
+	/**
122
+	 * assuming we have an up-to-date database schema, this will populate it
123
+	 * with default and initial data. This should be called
124
+	 * upon activation of a new plugin, reactivation, and at the end
125
+	 * of running migration scripts
126
+	 *
127
+	 * @throws \EE_Error
128
+	 */
129
+	public static function initialize_db_content()
130
+	{
131
+		// let's avoid doing all this logic repeatedly, especially when addons are requesting it
132
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
133
+			return;
134
+		}
135
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
136
+
137
+		EEH_Activation::initialize_system_questions();
138
+		EEH_Activation::insert_default_status_codes();
139
+		EEH_Activation::generate_default_message_templates();
140
+		EEH_Activation::create_no_ticket_prices_array();
141
+
142
+		EEH_Activation::validate_messages_system();
143
+		EEH_Activation::insert_default_payment_methods();
144
+		// in case we've
145
+		EEH_Activation::remove_cron_tasks();
146
+		EEH_Activation::create_cron_tasks();
147
+		// remove all TXN locks since that is being done via extra meta now
148
+		delete_option('ee_locked_transactions');
149
+		// also, check for CAF default db content
150
+		do_action('AHEE__EEH_Activation__initialize_db_content');
151
+		// also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
152
+		// which users really won't care about on initial activation
153
+		EE_Error::overwrite_success();
154
+	}
155
+
156
+
157
+	/**
158
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
159
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
160
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
161
+	 * (null)
162
+	 *
163
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
164
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
165
+	 * @return array
166
+	 * @throws \EE_Error
167
+	 */
168
+	public static function get_cron_tasks($which_to_include)
169
+	{
170
+		$cron_tasks = apply_filters(
171
+			'FHEE__EEH_Activation__get_cron_tasks',
172
+			array(
173
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
174
+			//              'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
175
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
176
+				// there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
177
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
178
+			)
179
+		);
180
+		if ($which_to_include === 'old') {
181
+			$cron_tasks = array_filter(
182
+				$cron_tasks,
183
+				function ($value) {
184
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
185
+				}
186
+			);
187
+		} elseif ($which_to_include === 'current') {
188
+			$cron_tasks = array_filter($cron_tasks);
189
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
190
+			throw new EE_Error(
191
+				sprintf(
192
+					__(
193
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
194
+						'event_espresso'
195
+					),
196
+					$which_to_include
197
+				)
198
+			);
199
+		}
200
+		return $cron_tasks;
201
+	}
202
+
203
+
204
+	/**
205
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
206
+	 *
207
+	 * @throws \EE_Error
208
+	 */
209
+	public static function create_cron_tasks()
210
+	{
211
+
212
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
213
+			if (! wp_next_scheduled($hook_name)) {
214
+				/**
215
+				 * This allows client code to define the initial start timestamp for this schedule.
216
+				 */
217
+				if (is_array($frequency)
218
+					&& count($frequency) === 2
219
+					&& isset($frequency[0], $frequency[1])
220
+				) {
221
+					$start_timestamp = $frequency[0];
222
+					$frequency = $frequency[1];
223
+				} else {
224
+					$start_timestamp = time();
225
+				}
226
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
227
+			}
228
+		}
229
+	}
230
+
231
+
232
+	/**
233
+	 * Remove the currently-existing and now-removed cron tasks.
234
+	 *
235
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
236
+	 * @throws \EE_Error
237
+	 */
238
+	public static function remove_cron_tasks($remove_all = true)
239
+	{
240
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
241
+		$crons                = _get_cron_array();
242
+		$crons                = is_array($crons) ? $crons : array();
243
+		/* reminder of what $crons look like:
244 244
          * Top-level keys are timestamps, and their values are arrays.
245 245
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
246 246
          * and their values are arrays.
@@ -257,909 +257,909 @@  discard block
 block discarded – undo
257 257
          *                  ...
258 258
          *      ...
259 259
          */
260
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
261
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
262
-            if (is_array($hooks_to_fire_at_time)) {
263
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
264
-                    if (isset($ee_cron_tasks_to_remove[ $hook_name ])
265
-                        && is_array($ee_cron_tasks_to_remove[ $hook_name ])
266
-                    ) {
267
-                        unset($crons[ $timestamp ][ $hook_name ]);
268
-                    }
269
-                }
270
-                // also take care of any empty cron timestamps.
271
-                if (empty($hooks_to_fire_at_time)) {
272
-                    unset($crons[ $timestamp ]);
273
-                }
274
-            }
275
-        }
276
-        _set_cron_array($crons);
277
-    }
278
-
279
-
280
-    /**
281
-     *    CPT_initialization
282
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
283
-     *
284
-     * @access public
285
-     * @static
286
-     * @return void
287
-     */
288
-    public static function CPT_initialization()
289
-    {
290
-        // register Custom Post Types
291
-        EE_Registry::instance()->load_core('Register_CPTs');
292
-        flush_rewrite_rules();
293
-    }
294
-
295
-
296
-
297
-    /**
298
-     *    reset_and_update_config
299
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
300
-     * If there is old calendar config data saved, then it will get converted on activation.
301
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
302
-     *
303
-     * @access public
304
-     * @static
305
-     * @return void
306
-     */
307
-    public static function reset_and_update_config()
308
-    {
309
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
310
-        add_filter(
311
-            'FHEE__EE_Config___load_core_config__config_settings',
312
-            array('EEH_Activation', 'migrate_old_config_data'),
313
-            10,
314
-            3
315
-        );
316
-        // EE_Config::reset();
317
-        if (! EE_Config::logging_enabled()) {
318
-            delete_option(EE_Config::LOG_NAME);
319
-        }
320
-    }
321
-
322
-
323
-    /**
324
-     *    load_calendar_config
325
-     *
326
-     * @access    public
327
-     * @return    void
328
-     */
329
-    public static function load_calendar_config()
330
-    {
331
-        // grab array of all plugin folders and loop thru it
332
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
333
-        if (empty($plugins)) {
334
-            return;
335
-        }
336
-        foreach ($plugins as $plugin_path) {
337
-            // grab plugin folder name from path
338
-            $plugin = basename($plugin_path);
339
-            // drill down to Espresso plugins
340
-            // then to calendar related plugins
341
-            if (strpos($plugin, 'espresso') !== false
342
-                || strpos($plugin, 'Espresso') !== false
343
-                || strpos($plugin, 'ee4') !== false
344
-                || strpos($plugin, 'EE4') !== false
345
-                || strpos($plugin, 'calendar') !== false
346
-            ) {
347
-                // this is what we are looking for
348
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
349
-                // does it exist in this folder ?
350
-                if (is_readable($calendar_config)) {
351
-                    // YEAH! let's load it
352
-                    require_once($calendar_config);
353
-                }
354
-            }
355
-        }
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     *    _migrate_old_config_data
362
-     *
363
-     * @access    public
364
-     * @param array|stdClass $settings
365
-     * @param string         $config
366
-     * @param \EE_Config     $EE_Config
367
-     * @return \stdClass
368
-     */
369
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
370
-    {
371
-        $convert_from_array = array('addons');
372
-        // in case old settings were saved as an array
373
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
374
-            // convert existing settings to an object
375
-            $config_array = $settings;
376
-            $settings = new stdClass();
377
-            foreach ($config_array as $key => $value) {
378
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
379
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
380
-                } else {
381
-                    $settings->{$key} = $value;
382
-                }
383
-            }
384
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
385
-        }
386
-        return $settings;
387
-    }
388
-
389
-
390
-    /**
391
-     * deactivate_event_espresso
392
-     *
393
-     * @access public
394
-     * @static
395
-     * @return void
396
-     */
397
-    public static function deactivate_event_espresso()
398
-    {
399
-        // check permissions
400
-        if (current_user_can('activate_plugins')) {
401
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
402
-        }
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     * verify_default_pages_exist
409
-     *
410
-     * @access public
411
-     * @static
412
-     * @return void
413
-     * @throws InvalidDataTypeException
414
-     */
415
-    public static function verify_default_pages_exist()
416
-    {
417
-        $critical_page_problem = false;
418
-        $critical_pages = array(
419
-            array(
420
-                'id'   => 'reg_page_id',
421
-                'name' => __('Registration Checkout', 'event_espresso'),
422
-                'post' => null,
423
-                'code' => 'ESPRESSO_CHECKOUT',
424
-            ),
425
-            array(
426
-                'id'   => 'txn_page_id',
427
-                'name' => __('Transactions', 'event_espresso'),
428
-                'post' => null,
429
-                'code' => 'ESPRESSO_TXN_PAGE',
430
-            ),
431
-            array(
432
-                'id'   => 'thank_you_page_id',
433
-                'name' => __('Thank You', 'event_espresso'),
434
-                'post' => null,
435
-                'code' => 'ESPRESSO_THANK_YOU',
436
-            ),
437
-            array(
438
-                'id'   => 'cancel_page_id',
439
-                'name' => __('Registration Cancelled', 'event_espresso'),
440
-                'post' => null,
441
-                'code' => 'ESPRESSO_CANCELLED',
442
-            ),
443
-        );
444
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
445
-        foreach ($critical_pages as $critical_page) {
446
-            // is critical page ID set in config ?
447
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
448
-                // attempt to find post by ID
449
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
450
-            }
451
-            // no dice?
452
-            if ($critical_page['post'] === null) {
453
-                // attempt to find post by title
454
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
455
-                // still nothing?
456
-                if ($critical_page['post'] === null) {
457
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
458
-                    // REALLY? Still nothing ??!?!?
459
-                    if ($critical_page['post'] === null) {
460
-                        $msg = __(
461
-                            'The Event Espresso critical page configuration settings could not be updated.',
462
-                            'event_espresso'
463
-                        );
464
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
465
-                        break;
466
-                    }
467
-                }
468
-            }
469
-            // check that Post ID matches critical page ID in config
470
-            if (isset($critical_page['post']->ID)
471
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
472
-            ) {
473
-                // update Config with post ID
474
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
475
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
476
-                    $msg = __(
477
-                        'The Event Espresso critical page configuration settings could not be updated.',
478
-                        'event_espresso'
479
-                    );
480
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
-                }
482
-            }
483
-            $critical_page_problem =
484
-                ! isset($critical_page['post']->post_status)
485
-                || $critical_page['post']->post_status !== 'publish'
486
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
487
-                    ? true
488
-                    : $critical_page_problem;
489
-        }
490
-        if ($critical_page_problem) {
491
-            new PersistentAdminNotice(
492
-                'critical_page_problem',
493
-                sprintf(
494
-                    esc_html__(
495
-                        'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
496
-                        'event_espresso'
497
-                    ),
498
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
499
-                    . __('Event Espresso Critical Pages Settings', 'event_espresso')
500
-                    . '</a>'
501
-                )
502
-            );
503
-        }
504
-        if (EE_Error::has_notices()) {
505
-            EE_Error::get_notices(false, true, true);
506
-        }
507
-    }
508
-
509
-
510
-
511
-    /**
512
-     * Returns the first post which uses the specified shortcode
513
-     *
514
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
515
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
516
-     *                             "[ESPRESSO_THANK_YOU"
517
-     *                             (we don't search for the closing shortcode bracket because they might have added
518
-     *                             parameter to the shortcode
519
-     * @return WP_Post or NULl
520
-     */
521
-    public static function get_page_by_ee_shortcode($ee_shortcode)
522
-    {
523
-        global $wpdb;
524
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
525
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
526
-        if ($post_id) {
527
-            return get_post($post_id);
528
-        } else {
529
-            return null;
530
-        }
531
-    }
532
-
533
-
534
-    /**
535
-     *    This function generates a post for critical espresso pages
536
-     *
537
-     * @access public
538
-     * @static
539
-     * @param array $critical_page
540
-     * @return array
541
-     */
542
-    public static function create_critical_page($critical_page)
543
-    {
544
-
545
-        $post_args = array(
546
-            'post_title'     => $critical_page['name'],
547
-            'post_status'    => 'publish',
548
-            'post_type'      => 'page',
549
-            'comment_status' => 'closed',
550
-            'post_content'   => '[' . $critical_page['code'] . ']',
551
-        );
552
-
553
-        $post_id = wp_insert_post($post_args);
554
-        if (! $post_id) {
555
-            $msg = sprintf(
556
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
557
-                $critical_page['name']
558
-            );
559
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
560
-            return $critical_page;
561
-        }
562
-        // get newly created post's details
563
-        if (! $critical_page['post'] = get_post($post_id)) {
564
-            $msg = sprintf(
565
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
566
-                $critical_page['name']
567
-            );
568
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
569
-        }
570
-
571
-        return $critical_page;
572
-    }
573
-
574
-
575
-
576
-
577
-    /**
578
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
579
-     * The role being used to check is filterable.
580
-     *
581
-     * @since  4.6.0
582
-     * @global WPDB $wpdb
583
-     * @return mixed null|int WP_user ID or NULL
584
-     */
585
-    public static function get_default_creator_id()
586
-    {
587
-        global $wpdb;
588
-        if (! empty(self::$_default_creator_id)) {
589
-            return self::$_default_creator_id;
590
-        }/**/
591
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
592
-        // let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
593
-        $pre_filtered_id = apply_filters(
594
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
595
-            false,
596
-            $role_to_check
597
-        );
598
-        if ($pre_filtered_id !== false) {
599
-            return (int) $pre_filtered_id;
600
-        }
601
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
602
-        $query = $wpdb->prepare(
603
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
604
-            '%' . $role_to_check . '%'
605
-        );
606
-        $user_id = $wpdb->get_var($query);
607
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
608
-        if ($user_id && (int) $user_id) {
609
-            self::$_default_creator_id = (int) $user_id;
610
-            return self::$_default_creator_id;
611
-        } else {
612
-            return null;
613
-        }
614
-    }
615
-
616
-
617
-
618
-    /**
619
-     * used by EE and EE addons during plugin activation to create tables.
620
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
621
-     * but includes extra logic regarding activations.
622
-     *
623
-     * @access public
624
-     * @static
625
-     * @param string  $table_name              without the $wpdb->prefix
626
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
627
-     *                                         table query)
628
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
629
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
630
-     *                                         and new once this function is done (ie, you really do want to CREATE a
631
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
632
-     *                                         you just want to verify the table exists and matches this definition
633
-     *                                         (and if it HAS data in it you want to leave it be)
634
-     * @return void
635
-     * @throws EE_Error if there are database errors
636
-     */
637
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
638
-    {
639
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
640
-            return;
641
-        }
642
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
643
-        if (! function_exists('dbDelta')) {
644
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
645
-        }
646
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
647
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
648
-        // do we need to first delete an existing version of this table ?
649
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
650
-            // ok, delete the table... but ONLY if it's empty
651
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
652
-            // table is NOT empty, are you SURE you want to delete this table ???
653
-            if (! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
654
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
655
-            } elseif (! $deleted_safely) {
656
-                // so we should be more cautious rather than just dropping tables so easily
657
-                error_log(
658
-                    sprintf(
659
-                        __(
660
-                            'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
661
-                            'event_espresso'
662
-                        ),
663
-                        $wp_table_name,
664
-                        '<br/>',
665
-                        'espresso_db_update'
666
-                    )
667
-                );
668
-            }
669
-        }
670
-        $engine = str_replace('ENGINE=', '', $engine);
671
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
672
-    }
673
-
674
-
675
-
676
-    /**
677
-     *    add_column_if_it_doesn't_exist
678
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
679
-     *
680
-     * @access     public
681
-     * @static
682
-     * @deprecated instead use TableManager::addColumn()
683
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
684
-     * @param string $column_name
685
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
686
-     *                            'VARCHAR(10)'
687
-     * @return bool|int
688
-     */
689
-    public static function add_column_if_it_doesnt_exist(
690
-        $table_name,
691
-        $column_name,
692
-        $column_info = 'INT UNSIGNED NOT NULL'
693
-    ) {
694
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
695
-    }
696
-
697
-
698
-    /**
699
-     * get_fields_on_table
700
-     * Gets all the fields on the database table.
701
-     *
702
-     * @access     public
703
-     * @deprecated instead use TableManager::getTableColumns()
704
-     * @static
705
-     * @param string $table_name , without prefixed $wpdb->prefix
706
-     * @return array of database column names
707
-     */
708
-    public static function get_fields_on_table($table_name = null)
709
-    {
710
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
711
-    }
712
-
713
-
714
-    /**
715
-     * db_table_is_empty
716
-     *
717
-     * @access     public\
718
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
719
-     * @static
720
-     * @param string $table_name
721
-     * @return bool
722
-     */
723
-    public static function db_table_is_empty($table_name)
724
-    {
725
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
726
-    }
727
-
728
-
729
-    /**
730
-     * delete_db_table_if_empty
731
-     *
732
-     * @access public
733
-     * @static
734
-     * @param string $table_name
735
-     * @return bool | int
736
-     */
737
-    public static function delete_db_table_if_empty($table_name)
738
-    {
739
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
740
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
741
-        }
742
-        return false;
743
-    }
744
-
745
-
746
-    /**
747
-     * delete_unused_db_table
748
-     *
749
-     * @access     public
750
-     * @static
751
-     * @deprecated instead use TableManager::dropTable()
752
-     * @param string $table_name
753
-     * @return bool | int
754
-     */
755
-    public static function delete_unused_db_table($table_name)
756
-    {
757
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
758
-    }
759
-
760
-
761
-    /**
762
-     * drop_index
763
-     *
764
-     * @access     public
765
-     * @static
766
-     * @deprecated instead use TableManager::dropIndex()
767
-     * @param string $table_name
768
-     * @param string $index_name
769
-     * @return bool | int
770
-     */
771
-    public static function drop_index($table_name, $index_name)
772
-    {
773
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
774
-    }
775
-
776
-
777
-
778
-    /**
779
-     * create_database_tables
780
-     *
781
-     * @access public
782
-     * @static
783
-     * @throws EE_Error
784
-     * @return boolean success (whether database is setup properly or not)
785
-     */
786
-    public static function create_database_tables()
787
-    {
788
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
789
-        // find the migration script that sets the database to be compatible with the code
790
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
791
-        if ($dms_name) {
792
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
793
-            $current_data_migration_script->set_migrating(false);
794
-            $current_data_migration_script->schema_changes_before_migration();
795
-            $current_data_migration_script->schema_changes_after_migration();
796
-            if ($current_data_migration_script->get_errors()) {
797
-                if (WP_DEBUG) {
798
-                    foreach ($current_data_migration_script->get_errors() as $error) {
799
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
800
-                    }
801
-                } else {
802
-                    EE_Error::add_error(
803
-                        __(
804
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
260
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
261
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
262
+			if (is_array($hooks_to_fire_at_time)) {
263
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
264
+					if (isset($ee_cron_tasks_to_remove[ $hook_name ])
265
+						&& is_array($ee_cron_tasks_to_remove[ $hook_name ])
266
+					) {
267
+						unset($crons[ $timestamp ][ $hook_name ]);
268
+					}
269
+				}
270
+				// also take care of any empty cron timestamps.
271
+				if (empty($hooks_to_fire_at_time)) {
272
+					unset($crons[ $timestamp ]);
273
+				}
274
+			}
275
+		}
276
+		_set_cron_array($crons);
277
+	}
278
+
279
+
280
+	/**
281
+	 *    CPT_initialization
282
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
283
+	 *
284
+	 * @access public
285
+	 * @static
286
+	 * @return void
287
+	 */
288
+	public static function CPT_initialization()
289
+	{
290
+		// register Custom Post Types
291
+		EE_Registry::instance()->load_core('Register_CPTs');
292
+		flush_rewrite_rules();
293
+	}
294
+
295
+
296
+
297
+	/**
298
+	 *    reset_and_update_config
299
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
300
+	 * If there is old calendar config data saved, then it will get converted on activation.
301
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
302
+	 *
303
+	 * @access public
304
+	 * @static
305
+	 * @return void
306
+	 */
307
+	public static function reset_and_update_config()
308
+	{
309
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
310
+		add_filter(
311
+			'FHEE__EE_Config___load_core_config__config_settings',
312
+			array('EEH_Activation', 'migrate_old_config_data'),
313
+			10,
314
+			3
315
+		);
316
+		// EE_Config::reset();
317
+		if (! EE_Config::logging_enabled()) {
318
+			delete_option(EE_Config::LOG_NAME);
319
+		}
320
+	}
321
+
322
+
323
+	/**
324
+	 *    load_calendar_config
325
+	 *
326
+	 * @access    public
327
+	 * @return    void
328
+	 */
329
+	public static function load_calendar_config()
330
+	{
331
+		// grab array of all plugin folders and loop thru it
332
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
333
+		if (empty($plugins)) {
334
+			return;
335
+		}
336
+		foreach ($plugins as $plugin_path) {
337
+			// grab plugin folder name from path
338
+			$plugin = basename($plugin_path);
339
+			// drill down to Espresso plugins
340
+			// then to calendar related plugins
341
+			if (strpos($plugin, 'espresso') !== false
342
+				|| strpos($plugin, 'Espresso') !== false
343
+				|| strpos($plugin, 'ee4') !== false
344
+				|| strpos($plugin, 'EE4') !== false
345
+				|| strpos($plugin, 'calendar') !== false
346
+			) {
347
+				// this is what we are looking for
348
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
349
+				// does it exist in this folder ?
350
+				if (is_readable($calendar_config)) {
351
+					// YEAH! let's load it
352
+					require_once($calendar_config);
353
+				}
354
+			}
355
+		}
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 *    _migrate_old_config_data
362
+	 *
363
+	 * @access    public
364
+	 * @param array|stdClass $settings
365
+	 * @param string         $config
366
+	 * @param \EE_Config     $EE_Config
367
+	 * @return \stdClass
368
+	 */
369
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
370
+	{
371
+		$convert_from_array = array('addons');
372
+		// in case old settings were saved as an array
373
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
374
+			// convert existing settings to an object
375
+			$config_array = $settings;
376
+			$settings = new stdClass();
377
+			foreach ($config_array as $key => $value) {
378
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
379
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
380
+				} else {
381
+					$settings->{$key} = $value;
382
+				}
383
+			}
384
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
385
+		}
386
+		return $settings;
387
+	}
388
+
389
+
390
+	/**
391
+	 * deactivate_event_espresso
392
+	 *
393
+	 * @access public
394
+	 * @static
395
+	 * @return void
396
+	 */
397
+	public static function deactivate_event_espresso()
398
+	{
399
+		// check permissions
400
+		if (current_user_can('activate_plugins')) {
401
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
402
+		}
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 * verify_default_pages_exist
409
+	 *
410
+	 * @access public
411
+	 * @static
412
+	 * @return void
413
+	 * @throws InvalidDataTypeException
414
+	 */
415
+	public static function verify_default_pages_exist()
416
+	{
417
+		$critical_page_problem = false;
418
+		$critical_pages = array(
419
+			array(
420
+				'id'   => 'reg_page_id',
421
+				'name' => __('Registration Checkout', 'event_espresso'),
422
+				'post' => null,
423
+				'code' => 'ESPRESSO_CHECKOUT',
424
+			),
425
+			array(
426
+				'id'   => 'txn_page_id',
427
+				'name' => __('Transactions', 'event_espresso'),
428
+				'post' => null,
429
+				'code' => 'ESPRESSO_TXN_PAGE',
430
+			),
431
+			array(
432
+				'id'   => 'thank_you_page_id',
433
+				'name' => __('Thank You', 'event_espresso'),
434
+				'post' => null,
435
+				'code' => 'ESPRESSO_THANK_YOU',
436
+			),
437
+			array(
438
+				'id'   => 'cancel_page_id',
439
+				'name' => __('Registration Cancelled', 'event_espresso'),
440
+				'post' => null,
441
+				'code' => 'ESPRESSO_CANCELLED',
442
+			),
443
+		);
444
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
445
+		foreach ($critical_pages as $critical_page) {
446
+			// is critical page ID set in config ?
447
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
448
+				// attempt to find post by ID
449
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
450
+			}
451
+			// no dice?
452
+			if ($critical_page['post'] === null) {
453
+				// attempt to find post by title
454
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
455
+				// still nothing?
456
+				if ($critical_page['post'] === null) {
457
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
458
+					// REALLY? Still nothing ??!?!?
459
+					if ($critical_page['post'] === null) {
460
+						$msg = __(
461
+							'The Event Espresso critical page configuration settings could not be updated.',
462
+							'event_espresso'
463
+						);
464
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
465
+						break;
466
+					}
467
+				}
468
+			}
469
+			// check that Post ID matches critical page ID in config
470
+			if (isset($critical_page['post']->ID)
471
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
472
+			) {
473
+				// update Config with post ID
474
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
475
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
476
+					$msg = __(
477
+						'The Event Espresso critical page configuration settings could not be updated.',
478
+						'event_espresso'
479
+					);
480
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
+				}
482
+			}
483
+			$critical_page_problem =
484
+				! isset($critical_page['post']->post_status)
485
+				|| $critical_page['post']->post_status !== 'publish'
486
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
487
+					? true
488
+					: $critical_page_problem;
489
+		}
490
+		if ($critical_page_problem) {
491
+			new PersistentAdminNotice(
492
+				'critical_page_problem',
493
+				sprintf(
494
+					esc_html__(
495
+						'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
496
+						'event_espresso'
497
+					),
498
+					'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
499
+					. __('Event Espresso Critical Pages Settings', 'event_espresso')
500
+					. '</a>'
501
+				)
502
+			);
503
+		}
504
+		if (EE_Error::has_notices()) {
505
+			EE_Error::get_notices(false, true, true);
506
+		}
507
+	}
508
+
509
+
510
+
511
+	/**
512
+	 * Returns the first post which uses the specified shortcode
513
+	 *
514
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
515
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
516
+	 *                             "[ESPRESSO_THANK_YOU"
517
+	 *                             (we don't search for the closing shortcode bracket because they might have added
518
+	 *                             parameter to the shortcode
519
+	 * @return WP_Post or NULl
520
+	 */
521
+	public static function get_page_by_ee_shortcode($ee_shortcode)
522
+	{
523
+		global $wpdb;
524
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
525
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
526
+		if ($post_id) {
527
+			return get_post($post_id);
528
+		} else {
529
+			return null;
530
+		}
531
+	}
532
+
533
+
534
+	/**
535
+	 *    This function generates a post for critical espresso pages
536
+	 *
537
+	 * @access public
538
+	 * @static
539
+	 * @param array $critical_page
540
+	 * @return array
541
+	 */
542
+	public static function create_critical_page($critical_page)
543
+	{
544
+
545
+		$post_args = array(
546
+			'post_title'     => $critical_page['name'],
547
+			'post_status'    => 'publish',
548
+			'post_type'      => 'page',
549
+			'comment_status' => 'closed',
550
+			'post_content'   => '[' . $critical_page['code'] . ']',
551
+		);
552
+
553
+		$post_id = wp_insert_post($post_args);
554
+		if (! $post_id) {
555
+			$msg = sprintf(
556
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
557
+				$critical_page['name']
558
+			);
559
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
560
+			return $critical_page;
561
+		}
562
+		// get newly created post's details
563
+		if (! $critical_page['post'] = get_post($post_id)) {
564
+			$msg = sprintf(
565
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
566
+				$critical_page['name']
567
+			);
568
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
569
+		}
570
+
571
+		return $critical_page;
572
+	}
573
+
574
+
575
+
576
+
577
+	/**
578
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
579
+	 * The role being used to check is filterable.
580
+	 *
581
+	 * @since  4.6.0
582
+	 * @global WPDB $wpdb
583
+	 * @return mixed null|int WP_user ID or NULL
584
+	 */
585
+	public static function get_default_creator_id()
586
+	{
587
+		global $wpdb;
588
+		if (! empty(self::$_default_creator_id)) {
589
+			return self::$_default_creator_id;
590
+		}/**/
591
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
592
+		// let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
593
+		$pre_filtered_id = apply_filters(
594
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
595
+			false,
596
+			$role_to_check
597
+		);
598
+		if ($pre_filtered_id !== false) {
599
+			return (int) $pre_filtered_id;
600
+		}
601
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
602
+		$query = $wpdb->prepare(
603
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
604
+			'%' . $role_to_check . '%'
605
+		);
606
+		$user_id = $wpdb->get_var($query);
607
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
608
+		if ($user_id && (int) $user_id) {
609
+			self::$_default_creator_id = (int) $user_id;
610
+			return self::$_default_creator_id;
611
+		} else {
612
+			return null;
613
+		}
614
+	}
615
+
616
+
617
+
618
+	/**
619
+	 * used by EE and EE addons during plugin activation to create tables.
620
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
621
+	 * but includes extra logic regarding activations.
622
+	 *
623
+	 * @access public
624
+	 * @static
625
+	 * @param string  $table_name              without the $wpdb->prefix
626
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
627
+	 *                                         table query)
628
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
629
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
630
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
631
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
632
+	 *                                         you just want to verify the table exists and matches this definition
633
+	 *                                         (and if it HAS data in it you want to leave it be)
634
+	 * @return void
635
+	 * @throws EE_Error if there are database errors
636
+	 */
637
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
638
+	{
639
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
640
+			return;
641
+		}
642
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
643
+		if (! function_exists('dbDelta')) {
644
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
645
+		}
646
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
647
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
648
+		// do we need to first delete an existing version of this table ?
649
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
650
+			// ok, delete the table... but ONLY if it's empty
651
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
652
+			// table is NOT empty, are you SURE you want to delete this table ???
653
+			if (! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
654
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
655
+			} elseif (! $deleted_safely) {
656
+				// so we should be more cautious rather than just dropping tables so easily
657
+				error_log(
658
+					sprintf(
659
+						__(
660
+							'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
661
+							'event_espresso'
662
+						),
663
+						$wp_table_name,
664
+						'<br/>',
665
+						'espresso_db_update'
666
+					)
667
+				);
668
+			}
669
+		}
670
+		$engine = str_replace('ENGINE=', '', $engine);
671
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
672
+	}
673
+
674
+
675
+
676
+	/**
677
+	 *    add_column_if_it_doesn't_exist
678
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
679
+	 *
680
+	 * @access     public
681
+	 * @static
682
+	 * @deprecated instead use TableManager::addColumn()
683
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
684
+	 * @param string $column_name
685
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
686
+	 *                            'VARCHAR(10)'
687
+	 * @return bool|int
688
+	 */
689
+	public static function add_column_if_it_doesnt_exist(
690
+		$table_name,
691
+		$column_name,
692
+		$column_info = 'INT UNSIGNED NOT NULL'
693
+	) {
694
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
695
+	}
696
+
697
+
698
+	/**
699
+	 * get_fields_on_table
700
+	 * Gets all the fields on the database table.
701
+	 *
702
+	 * @access     public
703
+	 * @deprecated instead use TableManager::getTableColumns()
704
+	 * @static
705
+	 * @param string $table_name , without prefixed $wpdb->prefix
706
+	 * @return array of database column names
707
+	 */
708
+	public static function get_fields_on_table($table_name = null)
709
+	{
710
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
711
+	}
712
+
713
+
714
+	/**
715
+	 * db_table_is_empty
716
+	 *
717
+	 * @access     public\
718
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
719
+	 * @static
720
+	 * @param string $table_name
721
+	 * @return bool
722
+	 */
723
+	public static function db_table_is_empty($table_name)
724
+	{
725
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
726
+	}
727
+
728
+
729
+	/**
730
+	 * delete_db_table_if_empty
731
+	 *
732
+	 * @access public
733
+	 * @static
734
+	 * @param string $table_name
735
+	 * @return bool | int
736
+	 */
737
+	public static function delete_db_table_if_empty($table_name)
738
+	{
739
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
740
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
741
+		}
742
+		return false;
743
+	}
744
+
745
+
746
+	/**
747
+	 * delete_unused_db_table
748
+	 *
749
+	 * @access     public
750
+	 * @static
751
+	 * @deprecated instead use TableManager::dropTable()
752
+	 * @param string $table_name
753
+	 * @return bool | int
754
+	 */
755
+	public static function delete_unused_db_table($table_name)
756
+	{
757
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
758
+	}
759
+
760
+
761
+	/**
762
+	 * drop_index
763
+	 *
764
+	 * @access     public
765
+	 * @static
766
+	 * @deprecated instead use TableManager::dropIndex()
767
+	 * @param string $table_name
768
+	 * @param string $index_name
769
+	 * @return bool | int
770
+	 */
771
+	public static function drop_index($table_name, $index_name)
772
+	{
773
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
774
+	}
775
+
776
+
777
+
778
+	/**
779
+	 * create_database_tables
780
+	 *
781
+	 * @access public
782
+	 * @static
783
+	 * @throws EE_Error
784
+	 * @return boolean success (whether database is setup properly or not)
785
+	 */
786
+	public static function create_database_tables()
787
+	{
788
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
789
+		// find the migration script that sets the database to be compatible with the code
790
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
791
+		if ($dms_name) {
792
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
793
+			$current_data_migration_script->set_migrating(false);
794
+			$current_data_migration_script->schema_changes_before_migration();
795
+			$current_data_migration_script->schema_changes_after_migration();
796
+			if ($current_data_migration_script->get_errors()) {
797
+				if (WP_DEBUG) {
798
+					foreach ($current_data_migration_script->get_errors() as $error) {
799
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
800
+					}
801
+				} else {
802
+					EE_Error::add_error(
803
+						__(
804
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
805 805
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
806
-                            'event_espresso'
807
-                        )
808
-                    );
809
-                }
810
-                return false;
811
-            }
812
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
813
-        } else {
814
-            EE_Error::add_error(
815
-                __(
816
-                    'Could not determine most up-to-date data migration script from which to pull database schema
806
+							'event_espresso'
807
+						)
808
+					);
809
+				}
810
+				return false;
811
+			}
812
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
813
+		} else {
814
+			EE_Error::add_error(
815
+				__(
816
+					'Could not determine most up-to-date data migration script from which to pull database schema
817 817
                      structure. So database is probably not setup properly',
818
-                    'event_espresso'
819
-                ),
820
-                __FILE__,
821
-                __FUNCTION__,
822
-                __LINE__
823
-            );
824
-            return false;
825
-        }
826
-        return true;
827
-    }
828
-
829
-
830
-
831
-    /**
832
-     * initialize_system_questions
833
-     *
834
-     * @access public
835
-     * @static
836
-     * @return void
837
-     */
838
-    public static function initialize_system_questions()
839
-    {
840
-        // QUESTION GROUPS
841
-        global $wpdb;
842
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
843
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
844
-        // what we have
845
-        $question_groups = $wpdb->get_col($SQL);
846
-        // check the response
847
-        $question_groups = is_array($question_groups) ? $question_groups : array();
848
-        // what we should have
849
-        $QSG_systems = array(1, 2);
850
-        // loop thru what we should have and compare to what we have
851
-        foreach ($QSG_systems as $QSG_system) {
852
-            // reset values array
853
-            $QSG_values = array();
854
-            // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
855
-            if (! in_array("$QSG_system", $question_groups)) {
856
-                // add it
857
-                switch ($QSG_system) {
858
-                    case 1:
859
-                        $QSG_values = array(
860
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
861
-                            'QSG_identifier'      => 'personal-information-' . time(),
862
-                            'QSG_desc'            => '',
863
-                            'QSG_order'           => 1,
864
-                            'QSG_show_group_name' => 1,
865
-                            'QSG_show_group_desc' => 1,
866
-                            'QSG_system'          => EEM_Question_Group::system_personal,
867
-                            'QSG_deleted'         => 0,
868
-                        );
869
-                        break;
870
-                    case 2:
871
-                        $QSG_values = array(
872
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
873
-                            'QSG_identifier'      => 'address-information-' . time(),
874
-                            'QSG_desc'            => '',
875
-                            'QSG_order'           => 2,
876
-                            'QSG_show_group_name' => 1,
877
-                            'QSG_show_group_desc' => 1,
878
-                            'QSG_system'          => EEM_Question_Group::system_address,
879
-                            'QSG_deleted'         => 0,
880
-                        );
881
-                        break;
882
-                }
883
-                // make sure we have some values before inserting them
884
-                if (! empty($QSG_values)) {
885
-                    // insert system question
886
-                    $wpdb->insert(
887
-                        $table_name,
888
-                        $QSG_values,
889
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
890
-                    );
891
-                    $QSG_IDs[ $QSG_system ] = $wpdb->insert_id;
892
-                }
893
-            }
894
-        }
895
-        // QUESTIONS
896
-        global $wpdb;
897
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
898
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
899
-        // what we have
900
-        $questions = $wpdb->get_col($SQL);
901
-        // what we should have
902
-        $QST_systems = array(
903
-            'fname',
904
-            'lname',
905
-            'email',
906
-            'address',
907
-            'address2',
908
-            'city',
909
-            'country',
910
-            'state',
911
-            'zip',
912
-            'phone',
913
-        );
914
-        $order_for_group_1 = 1;
915
-        $order_for_group_2 = 1;
916
-        // loop thru what we should have and compare to what we have
917
-        foreach ($QST_systems as $QST_system) {
918
-            // reset values array
919
-            $QST_values = array();
920
-            // if we don't have what we should have
921
-            if (! in_array($QST_system, $questions)) {
922
-                // add it
923
-                switch ($QST_system) {
924
-                    case 'fname':
925
-                        $QST_values = array(
926
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
927
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
928
-                            'QST_system'        => 'fname',
929
-                            'QST_type'          => 'TEXT',
930
-                            'QST_required'      => 1,
931
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
932
-                            'QST_order'         => 1,
933
-                            'QST_admin_only'    => 0,
934
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
935
-                            'QST_wp_user'       => self::get_default_creator_id(),
936
-                            'QST_deleted'       => 0,
937
-                        );
938
-                        break;
939
-                    case 'lname':
940
-                        $QST_values = array(
941
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
942
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
943
-                            'QST_system'        => 'lname',
944
-                            'QST_type'          => 'TEXT',
945
-                            'QST_required'      => 1,
946
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
947
-                            'QST_order'         => 2,
948
-                            'QST_admin_only'    => 0,
949
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
950
-                            'QST_wp_user'       => self::get_default_creator_id(),
951
-                            'QST_deleted'       => 0,
952
-                        );
953
-                        break;
954
-                    case 'email':
955
-                        $QST_values = array(
956
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
957
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
958
-                            'QST_system'        => 'email',
959
-                            'QST_type'          => 'EMAIL',
960
-                            'QST_required'      => 1,
961
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
962
-                            'QST_order'         => 3,
963
-                            'QST_admin_only'    => 0,
964
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
965
-                            'QST_wp_user'       => self::get_default_creator_id(),
966
-                            'QST_deleted'       => 0,
967
-                        );
968
-                        break;
969
-                    case 'address':
970
-                        $QST_values = array(
971
-                            'QST_display_text'  => __('Address', 'event_espresso'),
972
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
973
-                            'QST_system'        => 'address',
974
-                            'QST_type'          => 'TEXT',
975
-                            'QST_required'      => 0,
976
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
977
-                            'QST_order'         => 4,
978
-                            'QST_admin_only'    => 0,
979
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
980
-                            'QST_wp_user'       => self::get_default_creator_id(),
981
-                            'QST_deleted'       => 0,
982
-                        );
983
-                        break;
984
-                    case 'address2':
985
-                        $QST_values = array(
986
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
987
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
988
-                            'QST_system'        => 'address2',
989
-                            'QST_type'          => 'TEXT',
990
-                            'QST_required'      => 0,
991
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
992
-                            'QST_order'         => 5,
993
-                            'QST_admin_only'    => 0,
994
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
995
-                            'QST_wp_user'       => self::get_default_creator_id(),
996
-                            'QST_deleted'       => 0,
997
-                        );
998
-                        break;
999
-                    case 'city':
1000
-                        $QST_values = array(
1001
-                            'QST_display_text'  => __('City', 'event_espresso'),
1002
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1003
-                            'QST_system'        => 'city',
1004
-                            'QST_type'          => 'TEXT',
1005
-                            'QST_required'      => 0,
1006
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1007
-                            'QST_order'         => 6,
1008
-                            'QST_admin_only'    => 0,
1009
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1010
-                            'QST_wp_user'       => self::get_default_creator_id(),
1011
-                            'QST_deleted'       => 0,
1012
-                        );
1013
-                        break;
1014
-                    case 'country':
1015
-                        $QST_values = array(
1016
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1017
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1018
-                            'QST_system'        => 'country',
1019
-                            'QST_type'          => 'COUNTRY',
1020
-                            'QST_required'      => 0,
1021
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1022
-                            'QST_order'         => 7,
1023
-                            'QST_admin_only'    => 0,
1024
-                            'QST_wp_user'       => self::get_default_creator_id(),
1025
-                            'QST_deleted'       => 0,
1026
-                        );
1027
-                        break;
1028
-                    case 'state':
1029
-                        $QST_values = array(
1030
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1031
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1032
-                            'QST_system'        => 'state',
1033
-                            'QST_type'          => 'STATE',
1034
-                            'QST_required'      => 0,
1035
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1036
-                            'QST_order'         => 8,
1037
-                            'QST_admin_only'    => 0,
1038
-                            'QST_wp_user'       => self::get_default_creator_id(),
1039
-                            'QST_deleted'       => 0,
1040
-                        );
1041
-                        break;
1042
-                    case 'zip':
1043
-                        $QST_values = array(
1044
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1045
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1046
-                            'QST_system'        => 'zip',
1047
-                            'QST_type'          => 'TEXT',
1048
-                            'QST_required'      => 0,
1049
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1050
-                            'QST_order'         => 9,
1051
-                            'QST_admin_only'    => 0,
1052
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1053
-                            'QST_wp_user'       => self::get_default_creator_id(),
1054
-                            'QST_deleted'       => 0,
1055
-                        );
1056
-                        break;
1057
-                    case 'phone':
1058
-                        $QST_values = array(
1059
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1060
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1061
-                            'QST_system'        => 'phone',
1062
-                            'QST_type'          => 'TEXT',
1063
-                            'QST_required'      => 0,
1064
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1065
-                            'QST_order'         => 10,
1066
-                            'QST_admin_only'    => 0,
1067
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1068
-                            'QST_wp_user'       => self::get_default_creator_id(),
1069
-                            'QST_deleted'       => 0,
1070
-                        );
1071
-                        break;
1072
-                }
1073
-                if (! empty($QST_values)) {
1074
-                    // insert system question
1075
-                    $wpdb->insert(
1076
-                        $table_name,
1077
-                        $QST_values,
1078
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1079
-                    );
1080
-                    $QST_ID = $wpdb->insert_id;
1081
-                    // QUESTION GROUP QUESTIONS
1082
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1083
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1084
-                    } else {
1085
-                        $system_question_we_want = EEM_Question_Group::system_address;
1086
-                    }
1087
-                    if (isset($QSG_IDs[ $system_question_we_want ])) {
1088
-                        $QSG_ID = $QSG_IDs[ $system_question_we_want ];
1089
-                    } else {
1090
-                        $id_col = EEM_Question_Group::instance()
1091
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1092
-                        if (is_array($id_col)) {
1093
-                            $QSG_ID = reset($id_col);
1094
-                        } else {
1095
-                            // ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1096
-                            EE_Log::instance()->log(
1097
-                                __FILE__,
1098
-                                __FUNCTION__,
1099
-                                sprintf(
1100
-                                    __(
1101
-                                        'Could not associate question %1$s to a question group because no system question
818
+					'event_espresso'
819
+				),
820
+				__FILE__,
821
+				__FUNCTION__,
822
+				__LINE__
823
+			);
824
+			return false;
825
+		}
826
+		return true;
827
+	}
828
+
829
+
830
+
831
+	/**
832
+	 * initialize_system_questions
833
+	 *
834
+	 * @access public
835
+	 * @static
836
+	 * @return void
837
+	 */
838
+	public static function initialize_system_questions()
839
+	{
840
+		// QUESTION GROUPS
841
+		global $wpdb;
842
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
843
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
844
+		// what we have
845
+		$question_groups = $wpdb->get_col($SQL);
846
+		// check the response
847
+		$question_groups = is_array($question_groups) ? $question_groups : array();
848
+		// what we should have
849
+		$QSG_systems = array(1, 2);
850
+		// loop thru what we should have and compare to what we have
851
+		foreach ($QSG_systems as $QSG_system) {
852
+			// reset values array
853
+			$QSG_values = array();
854
+			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
855
+			if (! in_array("$QSG_system", $question_groups)) {
856
+				// add it
857
+				switch ($QSG_system) {
858
+					case 1:
859
+						$QSG_values = array(
860
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
861
+							'QSG_identifier'      => 'personal-information-' . time(),
862
+							'QSG_desc'            => '',
863
+							'QSG_order'           => 1,
864
+							'QSG_show_group_name' => 1,
865
+							'QSG_show_group_desc' => 1,
866
+							'QSG_system'          => EEM_Question_Group::system_personal,
867
+							'QSG_deleted'         => 0,
868
+						);
869
+						break;
870
+					case 2:
871
+						$QSG_values = array(
872
+							'QSG_name'            => __('Address Information', 'event_espresso'),
873
+							'QSG_identifier'      => 'address-information-' . time(),
874
+							'QSG_desc'            => '',
875
+							'QSG_order'           => 2,
876
+							'QSG_show_group_name' => 1,
877
+							'QSG_show_group_desc' => 1,
878
+							'QSG_system'          => EEM_Question_Group::system_address,
879
+							'QSG_deleted'         => 0,
880
+						);
881
+						break;
882
+				}
883
+				// make sure we have some values before inserting them
884
+				if (! empty($QSG_values)) {
885
+					// insert system question
886
+					$wpdb->insert(
887
+						$table_name,
888
+						$QSG_values,
889
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
890
+					);
891
+					$QSG_IDs[ $QSG_system ] = $wpdb->insert_id;
892
+				}
893
+			}
894
+		}
895
+		// QUESTIONS
896
+		global $wpdb;
897
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
898
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
899
+		// what we have
900
+		$questions = $wpdb->get_col($SQL);
901
+		// what we should have
902
+		$QST_systems = array(
903
+			'fname',
904
+			'lname',
905
+			'email',
906
+			'address',
907
+			'address2',
908
+			'city',
909
+			'country',
910
+			'state',
911
+			'zip',
912
+			'phone',
913
+		);
914
+		$order_for_group_1 = 1;
915
+		$order_for_group_2 = 1;
916
+		// loop thru what we should have and compare to what we have
917
+		foreach ($QST_systems as $QST_system) {
918
+			// reset values array
919
+			$QST_values = array();
920
+			// if we don't have what we should have
921
+			if (! in_array($QST_system, $questions)) {
922
+				// add it
923
+				switch ($QST_system) {
924
+					case 'fname':
925
+						$QST_values = array(
926
+							'QST_display_text'  => __('First Name', 'event_espresso'),
927
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
928
+							'QST_system'        => 'fname',
929
+							'QST_type'          => 'TEXT',
930
+							'QST_required'      => 1,
931
+							'QST_required_text' => __('This field is required', 'event_espresso'),
932
+							'QST_order'         => 1,
933
+							'QST_admin_only'    => 0,
934
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
935
+							'QST_wp_user'       => self::get_default_creator_id(),
936
+							'QST_deleted'       => 0,
937
+						);
938
+						break;
939
+					case 'lname':
940
+						$QST_values = array(
941
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
942
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
943
+							'QST_system'        => 'lname',
944
+							'QST_type'          => 'TEXT',
945
+							'QST_required'      => 1,
946
+							'QST_required_text' => __('This field is required', 'event_espresso'),
947
+							'QST_order'         => 2,
948
+							'QST_admin_only'    => 0,
949
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
950
+							'QST_wp_user'       => self::get_default_creator_id(),
951
+							'QST_deleted'       => 0,
952
+						);
953
+						break;
954
+					case 'email':
955
+						$QST_values = array(
956
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
957
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
958
+							'QST_system'        => 'email',
959
+							'QST_type'          => 'EMAIL',
960
+							'QST_required'      => 1,
961
+							'QST_required_text' => __('This field is required', 'event_espresso'),
962
+							'QST_order'         => 3,
963
+							'QST_admin_only'    => 0,
964
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
965
+							'QST_wp_user'       => self::get_default_creator_id(),
966
+							'QST_deleted'       => 0,
967
+						);
968
+						break;
969
+					case 'address':
970
+						$QST_values = array(
971
+							'QST_display_text'  => __('Address', 'event_espresso'),
972
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
973
+							'QST_system'        => 'address',
974
+							'QST_type'          => 'TEXT',
975
+							'QST_required'      => 0,
976
+							'QST_required_text' => __('This field is required', 'event_espresso'),
977
+							'QST_order'         => 4,
978
+							'QST_admin_only'    => 0,
979
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
980
+							'QST_wp_user'       => self::get_default_creator_id(),
981
+							'QST_deleted'       => 0,
982
+						);
983
+						break;
984
+					case 'address2':
985
+						$QST_values = array(
986
+							'QST_display_text'  => __('Address2', 'event_espresso'),
987
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
988
+							'QST_system'        => 'address2',
989
+							'QST_type'          => 'TEXT',
990
+							'QST_required'      => 0,
991
+							'QST_required_text' => __('This field is required', 'event_espresso'),
992
+							'QST_order'         => 5,
993
+							'QST_admin_only'    => 0,
994
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
995
+							'QST_wp_user'       => self::get_default_creator_id(),
996
+							'QST_deleted'       => 0,
997
+						);
998
+						break;
999
+					case 'city':
1000
+						$QST_values = array(
1001
+							'QST_display_text'  => __('City', 'event_espresso'),
1002
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1003
+							'QST_system'        => 'city',
1004
+							'QST_type'          => 'TEXT',
1005
+							'QST_required'      => 0,
1006
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1007
+							'QST_order'         => 6,
1008
+							'QST_admin_only'    => 0,
1009
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1010
+							'QST_wp_user'       => self::get_default_creator_id(),
1011
+							'QST_deleted'       => 0,
1012
+						);
1013
+						break;
1014
+					case 'country':
1015
+						$QST_values = array(
1016
+							'QST_display_text'  => __('Country', 'event_espresso'),
1017
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1018
+							'QST_system'        => 'country',
1019
+							'QST_type'          => 'COUNTRY',
1020
+							'QST_required'      => 0,
1021
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1022
+							'QST_order'         => 7,
1023
+							'QST_admin_only'    => 0,
1024
+							'QST_wp_user'       => self::get_default_creator_id(),
1025
+							'QST_deleted'       => 0,
1026
+						);
1027
+						break;
1028
+					case 'state':
1029
+						$QST_values = array(
1030
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1031
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1032
+							'QST_system'        => 'state',
1033
+							'QST_type'          => 'STATE',
1034
+							'QST_required'      => 0,
1035
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1036
+							'QST_order'         => 8,
1037
+							'QST_admin_only'    => 0,
1038
+							'QST_wp_user'       => self::get_default_creator_id(),
1039
+							'QST_deleted'       => 0,
1040
+						);
1041
+						break;
1042
+					case 'zip':
1043
+						$QST_values = array(
1044
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1045
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1046
+							'QST_system'        => 'zip',
1047
+							'QST_type'          => 'TEXT',
1048
+							'QST_required'      => 0,
1049
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1050
+							'QST_order'         => 9,
1051
+							'QST_admin_only'    => 0,
1052
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1053
+							'QST_wp_user'       => self::get_default_creator_id(),
1054
+							'QST_deleted'       => 0,
1055
+						);
1056
+						break;
1057
+					case 'phone':
1058
+						$QST_values = array(
1059
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1060
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1061
+							'QST_system'        => 'phone',
1062
+							'QST_type'          => 'TEXT',
1063
+							'QST_required'      => 0,
1064
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1065
+							'QST_order'         => 10,
1066
+							'QST_admin_only'    => 0,
1067
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1068
+							'QST_wp_user'       => self::get_default_creator_id(),
1069
+							'QST_deleted'       => 0,
1070
+						);
1071
+						break;
1072
+				}
1073
+				if (! empty($QST_values)) {
1074
+					// insert system question
1075
+					$wpdb->insert(
1076
+						$table_name,
1077
+						$QST_values,
1078
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1079
+					);
1080
+					$QST_ID = $wpdb->insert_id;
1081
+					// QUESTION GROUP QUESTIONS
1082
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1083
+						$system_question_we_want = EEM_Question_Group::system_personal;
1084
+					} else {
1085
+						$system_question_we_want = EEM_Question_Group::system_address;
1086
+					}
1087
+					if (isset($QSG_IDs[ $system_question_we_want ])) {
1088
+						$QSG_ID = $QSG_IDs[ $system_question_we_want ];
1089
+					} else {
1090
+						$id_col = EEM_Question_Group::instance()
1091
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1092
+						if (is_array($id_col)) {
1093
+							$QSG_ID = reset($id_col);
1094
+						} else {
1095
+							// ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1096
+							EE_Log::instance()->log(
1097
+								__FILE__,
1098
+								__FUNCTION__,
1099
+								sprintf(
1100
+									__(
1101
+										'Could not associate question %1$s to a question group because no system question
1102 1102
                                          group existed',
1103
-                                        'event_espresso'
1104
-                                    ),
1105
-                                    $QST_ID
1106
-                                ),
1107
-                                'error'
1108
-                            );
1109
-                            continue;
1110
-                        }
1111
-                    }
1112
-                    // add system questions to groups
1113
-                    $wpdb->insert(
1114
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1115
-                        array(
1116
-                            'QSG_ID'    => $QSG_ID,
1117
-                            'QST_ID'    => $QST_ID,
1118
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1119
-                        ),
1120
-                        array('%d', '%d', '%d')
1121
-                    );
1122
-                }
1123
-            }
1124
-        }
1125
-    }
1126
-
1127
-
1128
-    /**
1129
-     * Makes sure the default payment method (Invoice) is active.
1130
-     * This used to be done automatically as part of constructing the old gateways config
1131
-     *
1132
-     * @throws \EE_Error
1133
-     */
1134
-    public static function insert_default_payment_methods()
1135
-    {
1136
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1137
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1138
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1139
-        } else {
1140
-            EEM_Payment_Method::instance()->verify_button_urls();
1141
-        }
1142
-    }
1143
-
1144
-    /**
1145
-     * insert_default_status_codes
1146
-     *
1147
-     * @access public
1148
-     * @static
1149
-     * @return void
1150
-     */
1151
-    public static function insert_default_status_codes()
1152
-    {
1153
-
1154
-        global $wpdb;
1155
-
1156
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1157
-            $table_name = EEM_Status::instance()->table();
1158
-
1159
-            $SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1160
-            $wpdb->query($SQL);
1161
-
1162
-            $SQL = "INSERT INTO $table_name
1103
+										'event_espresso'
1104
+									),
1105
+									$QST_ID
1106
+								),
1107
+								'error'
1108
+							);
1109
+							continue;
1110
+						}
1111
+					}
1112
+					// add system questions to groups
1113
+					$wpdb->insert(
1114
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1115
+						array(
1116
+							'QSG_ID'    => $QSG_ID,
1117
+							'QST_ID'    => $QST_ID,
1118
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1119
+						),
1120
+						array('%d', '%d', '%d')
1121
+					);
1122
+				}
1123
+			}
1124
+		}
1125
+	}
1126
+
1127
+
1128
+	/**
1129
+	 * Makes sure the default payment method (Invoice) is active.
1130
+	 * This used to be done automatically as part of constructing the old gateways config
1131
+	 *
1132
+	 * @throws \EE_Error
1133
+	 */
1134
+	public static function insert_default_payment_methods()
1135
+	{
1136
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1137
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1138
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1139
+		} else {
1140
+			EEM_Payment_Method::instance()->verify_button_urls();
1141
+		}
1142
+	}
1143
+
1144
+	/**
1145
+	 * insert_default_status_codes
1146
+	 *
1147
+	 * @access public
1148
+	 * @static
1149
+	 * @return void
1150
+	 */
1151
+	public static function insert_default_status_codes()
1152
+	{
1153
+
1154
+		global $wpdb;
1155
+
1156
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1157
+			$table_name = EEM_Status::instance()->table();
1158
+
1159
+			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1160
+			$wpdb->query($SQL);
1161
+
1162
+			$SQL = "INSERT INTO $table_name
1163 1163
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1164 1164
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1165 1165
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1199,457 +1199,457 @@  discard block
 block discarded – undo
1199 1199
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1200 1200
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1201 1201
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1202
-            $wpdb->query($SQL);
1203
-        }
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * generate_default_message_templates
1209
-     *
1210
-     * @static
1211
-     * @throws EE_Error
1212
-     * @return bool     true means new templates were created.
1213
-     *                  false means no templates were created.
1214
-     *                  This is NOT an error flag. To check for errors you will want
1215
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1216
-     */
1217
-    public static function generate_default_message_templates()
1218
-    {
1219
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1220
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1221
-        /*
1202
+			$wpdb->query($SQL);
1203
+		}
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * generate_default_message_templates
1209
+	 *
1210
+	 * @static
1211
+	 * @throws EE_Error
1212
+	 * @return bool     true means new templates were created.
1213
+	 *                  false means no templates were created.
1214
+	 *                  This is NOT an error flag. To check for errors you will want
1215
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1216
+	 */
1217
+	public static function generate_default_message_templates()
1218
+	{
1219
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1220
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1221
+		/*
1222 1222
          * This first method is taking care of ensuring any default messengers
1223 1223
          * that should be made active and have templates generated are done.
1224 1224
          */
1225
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1226
-            $message_resource_manager
1227
-        );
1228
-        /**
1229
-         * This method is verifying there are no NEW default message types
1230
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1231
-         */
1232
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1233
-            $message_resource_manager
1234
-        );
1235
-        // after all is done, let's persist these changes to the db.
1236
-        $message_resource_manager->update_has_activated_messengers_option();
1237
-        $message_resource_manager->update_active_messengers_option();
1238
-        // will return true if either of these are true.  Otherwise will return false.
1239
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1240
-    }
1241
-
1242
-
1243
-
1244
-    /**
1245
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1246
-     * @return array|bool
1247
-     * @throws \EE_Error
1248
-     */
1249
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1250
-        EE_Message_Resource_Manager $message_resource_manager
1251
-    ) {
1252
-        /** @type EE_messenger[] $active_messengers */
1253
-        $active_messengers = $message_resource_manager->active_messengers();
1254
-        $installed_message_types = $message_resource_manager->installed_message_types();
1255
-        $templates_created = false;
1256
-        foreach ($active_messengers as $active_messenger) {
1257
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1258
-            $default_message_type_names_to_activate = array();
1259
-            // looping through each default message type reported by the messenger
1260
-            // and setup the actual message types to activate.
1261
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1262
-                // if already active or has already been activated before we skip
1263
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1264
-                // we also skip if the message type is not installed.
1265
-                if ($message_resource_manager->has_message_type_been_activated_for_messenger(
1266
-                    $default_message_type_name_for_messenger,
1267
-                    $active_messenger->name
1268
-                )
1269
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1270
-                        $active_messenger->name,
1271
-                        $default_message_type_name_for_messenger
1272
-                    )
1273
-                    || ! isset($installed_message_types[ $default_message_type_name_for_messenger ])
1274
-                ) {
1275
-                    continue;
1276
-                }
1277
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1278
-            }
1279
-            // let's activate!
1280
-            $message_resource_manager->ensure_message_types_are_active(
1281
-                $default_message_type_names_to_activate,
1282
-                $active_messenger->name,
1283
-                false
1284
-            );
1285
-            // activate the templates for these message types
1286
-            if (! empty($default_message_type_names_to_activate)) {
1287
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1288
-                    $active_messenger->name,
1289
-                    $default_message_type_names_for_messenger,
1290
-                    '',
1291
-                    true
1292
-                );
1293
-            }
1294
-        }
1295
-        return $templates_created;
1296
-    }
1297
-
1298
-
1299
-
1300
-    /**
1301
-     * This will activate and generate default messengers and default message types for those messengers.
1302
-     *
1303
-     * @param EE_message_Resource_Manager $message_resource_manager
1304
-     * @return array|bool  True means there were default messengers and message type templates generated.
1305
-     *                     False means that there were no templates generated
1306
-     *                     (which could simply mean there are no default message types for a messenger).
1307
-     * @throws EE_Error
1308
-     */
1309
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1310
-        EE_Message_Resource_Manager $message_resource_manager
1311
-    ) {
1312
-        /** @type EE_messenger[] $messengers_to_generate */
1313
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1314
-        $installed_message_types = $message_resource_manager->installed_message_types();
1315
-        $templates_generated = false;
1316
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1317
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1318
-            // verify the default message types match an installed message type.
1319
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1320
-                if (! isset($installed_message_types[ $name ])
1321
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1322
-                        $name,
1323
-                        $messenger_to_generate->name
1324
-                    )
1325
-                ) {
1326
-                    unset($default_message_type_names_for_messenger[ $key ]);
1327
-                }
1328
-            }
1329
-            // in previous iterations, the active_messengers option in the db
1330
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1331
-            // This comment is left here just in case we discover that we _do_ need to update before
1332
-            // passing off to create templates (after the refactor is done).
1333
-            // @todo remove this comment when determined not necessary.
1334
-            $message_resource_manager->activate_messenger(
1335
-                $messenger_to_generate->name,
1336
-                $default_message_type_names_for_messenger,
1337
-                false
1338
-            );
1339
-            // create any templates needing created (or will reactivate templates already generated as necessary).
1340
-            if (! empty($default_message_type_names_for_messenger)) {
1341
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1342
-                    $messenger_to_generate->name,
1343
-                    $default_message_type_names_for_messenger,
1344
-                    '',
1345
-                    true
1346
-                );
1347
-            }
1348
-        }
1349
-        return $templates_generated;
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * This returns the default messengers to generate templates for on activation of EE.
1355
-     * It considers:
1356
-     * - whether a messenger is already active in the db.
1357
-     * - whether a messenger has been made active at any time in the past.
1358
-     *
1359
-     * @static
1360
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1361
-     * @return EE_messenger[]
1362
-     */
1363
-    protected static function _get_default_messengers_to_generate_on_activation(
1364
-        EE_Message_Resource_Manager $message_resource_manager
1365
-    ) {
1366
-        $active_messengers    = $message_resource_manager->active_messengers();
1367
-        $installed_messengers = $message_resource_manager->installed_messengers();
1368
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1369
-
1370
-        $messengers_to_generate = array();
1371
-        foreach ($installed_messengers as $installed_messenger) {
1372
-            // if installed messenger is a messenger that should be activated on install
1373
-            // and is not already active
1374
-            // and has never been activated
1375
-            if (! $installed_messenger->activate_on_install
1376
-                || isset($active_messengers[ $installed_messenger->name ])
1377
-                || isset($has_activated[ $installed_messenger->name ])
1378
-            ) {
1379
-                continue;
1380
-            }
1381
-            $messengers_to_generate[ $installed_messenger->name ] = $installed_messenger;
1382
-        }
1383
-        return $messengers_to_generate;
1384
-    }
1385
-
1386
-
1387
-    /**
1388
-     * This simply validates active message types to ensure they actually match installed
1389
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1390
-     * rows are set inactive.
1391
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1392
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1393
-     * are still handled in here.
1394
-     *
1395
-     * @since 4.3.1
1396
-     * @return void
1397
-     */
1398
-    public static function validate_messages_system()
1399
-    {
1400
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1401
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1402
-        $message_resource_manager->validate_active_message_types_are_installed();
1403
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * create_no_ticket_prices_array
1409
-     *
1410
-     * @access public
1411
-     * @static
1412
-     * @return void
1413
-     */
1414
-    public static function create_no_ticket_prices_array()
1415
-    {
1416
-        // this creates an array for tracking events that have no active ticket prices created
1417
-        // this allows us to warn admins of the situation so that it can be corrected
1418
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1419
-        if (! $espresso_no_ticket_prices) {
1420
-            add_option('ee_no_ticket_prices', array(), '', false);
1421
-        }
1422
-    }
1423
-
1424
-
1425
-    /**
1426
-     * plugin_deactivation
1427
-     *
1428
-     * @access public
1429
-     * @static
1430
-     * @return void
1431
-     */
1432
-    public static function plugin_deactivation()
1433
-    {
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1439
-     * (like post meta or term relations)
1440
-     *
1441
-     * @global wpdb $wpdb
1442
-     * @throws \EE_Error
1443
-     */
1444
-    public static function delete_all_espresso_cpt_data()
1445
-    {
1446
-        global $wpdb;
1447
-        // get all the CPT post_types
1448
-        $ee_post_types = array();
1449
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1450
-            if (method_exists($model_name, 'instance')) {
1451
-                $model_obj = call_user_func(array($model_name, 'instance'));
1452
-                if ($model_obj instanceof EEM_CPT_Base) {
1453
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1454
-                }
1455
-            }
1456
-        }
1457
-        // get all our CPTs
1458
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1459
-        $cpt_ids = $wpdb->get_col($query);
1460
-        // delete each post meta and term relations too
1461
-        foreach ($cpt_ids as $post_id) {
1462
-            wp_delete_post($post_id, true);
1463
-        }
1464
-    }
1465
-
1466
-    /**
1467
-     * Deletes all EE custom tables
1468
-     *
1469
-     * @return array
1470
-     */
1471
-    public static function drop_espresso_tables()
1472
-    {
1473
-        $tables = array();
1474
-        // load registry
1475
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1476
-            if (method_exists($model_name, 'instance')) {
1477
-                $model_obj = call_user_func(array($model_name, 'instance'));
1478
-                if ($model_obj instanceof EEM_Base) {
1479
-                    foreach ($model_obj->get_tables() as $table) {
1480
-                        if (strpos($table->get_table_name(), 'esp_')
1481
-                            &&
1482
-                            (
1483
-                                is_main_site()// main site? nuke them all
1484
-                                || ! $table->is_global()// not main site,but not global either. nuke it
1485
-                            )
1486
-                        ) {
1487
-                            $tables[ $table->get_table_name() ] = $table->get_table_name();
1488
-                        }
1489
-                    }
1490
-                }
1491
-            }
1492
-        }
1493
-
1494
-        // there are some tables whose models were removed.
1495
-        // they should be removed when removing all EE core's data
1496
-        $tables_without_models = array(
1497
-            'esp_promotion',
1498
-            'esp_promotion_applied',
1499
-            'esp_promotion_object',
1500
-            'esp_promotion_rule',
1501
-            'esp_rule',
1502
-        );
1503
-        foreach ($tables_without_models as $table) {
1504
-            $tables[ $table ] = $table;
1505
-        }
1506
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1507
-    }
1508
-
1509
-
1510
-
1511
-    /**
1512
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1513
-     * each table name provided has a wpdb prefix attached, and that it exists.
1514
-     * Returns the list actually deleted
1515
-     *
1516
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1517
-     * @global WPDB $wpdb
1518
-     * @param array $table_names
1519
-     * @return array of table names which we deleted
1520
-     */
1521
-    public static function drop_tables($table_names)
1522
-    {
1523
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1524
-    }
1525
-
1526
-
1527
-
1528
-    /**
1529
-     * plugin_uninstall
1530
-     *
1531
-     * @access public
1532
-     * @static
1533
-     * @param bool $remove_all
1534
-     * @return void
1535
-     */
1536
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1537
-    {
1538
-        global $wpdb;
1539
-        self::drop_espresso_tables();
1540
-        $wp_options_to_delete = array(
1541
-            'ee_no_ticket_prices'                => true,
1542
-            'ee_active_messengers'               => true,
1543
-            'ee_has_activated_messenger'         => true,
1544
-            RewriteRules::OPTION_KEY_FLUSH_REWRITE_RULES => true,
1545
-            'ee_config'                          => false,
1546
-            'ee_data_migration_current_db_state' => true,
1547
-            'ee_data_migration_mapping_'         => false,
1548
-            'ee_data_migration_script_'          => false,
1549
-            'ee_data_migrations'                 => true,
1550
-            'ee_dms_map'                         => false,
1551
-            'ee_notices'                         => true,
1552
-            'lang_file_check_'                   => false,
1553
-            'ee_maintenance_mode'                => true,
1554
-            'ee_ueip_optin'                      => true,
1555
-            'ee_ueip_has_notified'               => true,
1556
-            'ee_plugin_activation_errors'        => true,
1557
-            'ee_id_mapping_from'                 => false,
1558
-            'espresso_persistent_admin_notices'  => true,
1559
-            'ee_encryption_key'                  => true,
1560
-            'pue_force_upgrade_'                 => false,
1561
-            'pue_json_error_'                    => false,
1562
-            'pue_install_key_'                   => false,
1563
-            'pue_verification_error_'            => false,
1564
-            'pu_dismissed_upgrade_'              => false,
1565
-            'external_updates-'                  => false,
1566
-            'ee_extra_data'                      => true,
1567
-            'ee_ssn_'                            => false,
1568
-            'ee_rss_'                            => false,
1569
-            'ee_rte_n_tx_'                       => false,
1570
-            'ee_pers_admin_notices'              => true,
1571
-            'ee_job_parameters_'                 => false,
1572
-            'ee_upload_directories_incomplete'   => true,
1573
-            'ee_verified_db_collations'          => true,
1574
-        );
1575
-        if (is_main_site()) {
1576
-            $wp_options_to_delete['ee_network_config'] = true;
1577
-        }
1578
-        $undeleted_options = array();
1579
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1580
-            if ($no_wildcard) {
1581
-                if (! delete_option($option_name)) {
1582
-                    $undeleted_options[] = $option_name;
1583
-                }
1584
-            } else {
1585
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1586
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1587
-                    if (! delete_option($option_name_from_wildcard)) {
1588
-                        $undeleted_options[] = $option_name_from_wildcard;
1589
-                    }
1590
-                }
1591
-            }
1592
-        }
1593
-        // also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1594
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1595
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1596
-            $db_update_sans_ee4 = array();
1597
-            foreach ($espresso_db_update as $version => $times_activated) {
1598
-                if ((string) $version[0] === '3') {// if its NON EE4
1599
-                    $db_update_sans_ee4[ $version ] = $times_activated;
1600
-                }
1601
-            }
1602
-            update_option('espresso_db_update', $db_update_sans_ee4);
1603
-        }
1604
-        $errors = '';
1605
-        if (! empty($undeleted_options)) {
1606
-            $errors .= sprintf(
1607
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1608
-                '<br/>',
1609
-                implode(',<br/>', $undeleted_options)
1610
-            );
1611
-        }
1612
-        if (! empty($errors)) {
1613
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1614
-        }
1615
-    }
1616
-
1617
-    /**
1618
-     * Gets the mysql error code from the last used query by wpdb
1619
-     *
1620
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1621
-     */
1622
-    public static function last_wpdb_error_code()
1623
-    {
1624
-        // phpcs:disable PHPCompatibility.PHP.RemovedExtensions.mysql_DeprecatedRemoved
1625
-        global $wpdb;
1626
-        if ($wpdb->use_mysqli) {
1627
-            return mysqli_errno($wpdb->dbh);
1628
-        } else {
1629
-            return mysql_errno($wpdb->dbh);
1630
-        }
1631
-        // phpcs:enable
1632
-    }
1633
-
1634
-    /**
1635
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1636
-     *
1637
-     * @global wpdb  $wpdb
1638
-     * @deprecated instead use TableAnalysis::tableExists()
1639
-     * @param string $table_name with or without $wpdb->prefix
1640
-     * @return boolean
1641
-     */
1642
-    public static function table_exists($table_name)
1643
-    {
1644
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1645
-    }
1646
-
1647
-    /**
1648
-     * Resets the cache on EEH_Activation
1649
-     */
1650
-    public static function reset()
1651
-    {
1652
-        self::$_default_creator_id                             = null;
1653
-        self::$_initialized_db_content_already_in_this_request = false;
1654
-    }
1225
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1226
+			$message_resource_manager
1227
+		);
1228
+		/**
1229
+		 * This method is verifying there are no NEW default message types
1230
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1231
+		 */
1232
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1233
+			$message_resource_manager
1234
+		);
1235
+		// after all is done, let's persist these changes to the db.
1236
+		$message_resource_manager->update_has_activated_messengers_option();
1237
+		$message_resource_manager->update_active_messengers_option();
1238
+		// will return true if either of these are true.  Otherwise will return false.
1239
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1240
+	}
1241
+
1242
+
1243
+
1244
+	/**
1245
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1246
+	 * @return array|bool
1247
+	 * @throws \EE_Error
1248
+	 */
1249
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1250
+		EE_Message_Resource_Manager $message_resource_manager
1251
+	) {
1252
+		/** @type EE_messenger[] $active_messengers */
1253
+		$active_messengers = $message_resource_manager->active_messengers();
1254
+		$installed_message_types = $message_resource_manager->installed_message_types();
1255
+		$templates_created = false;
1256
+		foreach ($active_messengers as $active_messenger) {
1257
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1258
+			$default_message_type_names_to_activate = array();
1259
+			// looping through each default message type reported by the messenger
1260
+			// and setup the actual message types to activate.
1261
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1262
+				// if already active or has already been activated before we skip
1263
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1264
+				// we also skip if the message type is not installed.
1265
+				if ($message_resource_manager->has_message_type_been_activated_for_messenger(
1266
+					$default_message_type_name_for_messenger,
1267
+					$active_messenger->name
1268
+				)
1269
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1270
+						$active_messenger->name,
1271
+						$default_message_type_name_for_messenger
1272
+					)
1273
+					|| ! isset($installed_message_types[ $default_message_type_name_for_messenger ])
1274
+				) {
1275
+					continue;
1276
+				}
1277
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1278
+			}
1279
+			// let's activate!
1280
+			$message_resource_manager->ensure_message_types_are_active(
1281
+				$default_message_type_names_to_activate,
1282
+				$active_messenger->name,
1283
+				false
1284
+			);
1285
+			// activate the templates for these message types
1286
+			if (! empty($default_message_type_names_to_activate)) {
1287
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1288
+					$active_messenger->name,
1289
+					$default_message_type_names_for_messenger,
1290
+					'',
1291
+					true
1292
+				);
1293
+			}
1294
+		}
1295
+		return $templates_created;
1296
+	}
1297
+
1298
+
1299
+
1300
+	/**
1301
+	 * This will activate and generate default messengers and default message types for those messengers.
1302
+	 *
1303
+	 * @param EE_message_Resource_Manager $message_resource_manager
1304
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1305
+	 *                     False means that there were no templates generated
1306
+	 *                     (which could simply mean there are no default message types for a messenger).
1307
+	 * @throws EE_Error
1308
+	 */
1309
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1310
+		EE_Message_Resource_Manager $message_resource_manager
1311
+	) {
1312
+		/** @type EE_messenger[] $messengers_to_generate */
1313
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1314
+		$installed_message_types = $message_resource_manager->installed_message_types();
1315
+		$templates_generated = false;
1316
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1317
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1318
+			// verify the default message types match an installed message type.
1319
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1320
+				if (! isset($installed_message_types[ $name ])
1321
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1322
+						$name,
1323
+						$messenger_to_generate->name
1324
+					)
1325
+				) {
1326
+					unset($default_message_type_names_for_messenger[ $key ]);
1327
+				}
1328
+			}
1329
+			// in previous iterations, the active_messengers option in the db
1330
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1331
+			// This comment is left here just in case we discover that we _do_ need to update before
1332
+			// passing off to create templates (after the refactor is done).
1333
+			// @todo remove this comment when determined not necessary.
1334
+			$message_resource_manager->activate_messenger(
1335
+				$messenger_to_generate->name,
1336
+				$default_message_type_names_for_messenger,
1337
+				false
1338
+			);
1339
+			// create any templates needing created (or will reactivate templates already generated as necessary).
1340
+			if (! empty($default_message_type_names_for_messenger)) {
1341
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1342
+					$messenger_to_generate->name,
1343
+					$default_message_type_names_for_messenger,
1344
+					'',
1345
+					true
1346
+				);
1347
+			}
1348
+		}
1349
+		return $templates_generated;
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * This returns the default messengers to generate templates for on activation of EE.
1355
+	 * It considers:
1356
+	 * - whether a messenger is already active in the db.
1357
+	 * - whether a messenger has been made active at any time in the past.
1358
+	 *
1359
+	 * @static
1360
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1361
+	 * @return EE_messenger[]
1362
+	 */
1363
+	protected static function _get_default_messengers_to_generate_on_activation(
1364
+		EE_Message_Resource_Manager $message_resource_manager
1365
+	) {
1366
+		$active_messengers    = $message_resource_manager->active_messengers();
1367
+		$installed_messengers = $message_resource_manager->installed_messengers();
1368
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1369
+
1370
+		$messengers_to_generate = array();
1371
+		foreach ($installed_messengers as $installed_messenger) {
1372
+			// if installed messenger is a messenger that should be activated on install
1373
+			// and is not already active
1374
+			// and has never been activated
1375
+			if (! $installed_messenger->activate_on_install
1376
+				|| isset($active_messengers[ $installed_messenger->name ])
1377
+				|| isset($has_activated[ $installed_messenger->name ])
1378
+			) {
1379
+				continue;
1380
+			}
1381
+			$messengers_to_generate[ $installed_messenger->name ] = $installed_messenger;
1382
+		}
1383
+		return $messengers_to_generate;
1384
+	}
1385
+
1386
+
1387
+	/**
1388
+	 * This simply validates active message types to ensure they actually match installed
1389
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1390
+	 * rows are set inactive.
1391
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1392
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1393
+	 * are still handled in here.
1394
+	 *
1395
+	 * @since 4.3.1
1396
+	 * @return void
1397
+	 */
1398
+	public static function validate_messages_system()
1399
+	{
1400
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1401
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1402
+		$message_resource_manager->validate_active_message_types_are_installed();
1403
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * create_no_ticket_prices_array
1409
+	 *
1410
+	 * @access public
1411
+	 * @static
1412
+	 * @return void
1413
+	 */
1414
+	public static function create_no_ticket_prices_array()
1415
+	{
1416
+		// this creates an array for tracking events that have no active ticket prices created
1417
+		// this allows us to warn admins of the situation so that it can be corrected
1418
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1419
+		if (! $espresso_no_ticket_prices) {
1420
+			add_option('ee_no_ticket_prices', array(), '', false);
1421
+		}
1422
+	}
1423
+
1424
+
1425
+	/**
1426
+	 * plugin_deactivation
1427
+	 *
1428
+	 * @access public
1429
+	 * @static
1430
+	 * @return void
1431
+	 */
1432
+	public static function plugin_deactivation()
1433
+	{
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1439
+	 * (like post meta or term relations)
1440
+	 *
1441
+	 * @global wpdb $wpdb
1442
+	 * @throws \EE_Error
1443
+	 */
1444
+	public static function delete_all_espresso_cpt_data()
1445
+	{
1446
+		global $wpdb;
1447
+		// get all the CPT post_types
1448
+		$ee_post_types = array();
1449
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1450
+			if (method_exists($model_name, 'instance')) {
1451
+				$model_obj = call_user_func(array($model_name, 'instance'));
1452
+				if ($model_obj instanceof EEM_CPT_Base) {
1453
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1454
+				}
1455
+			}
1456
+		}
1457
+		// get all our CPTs
1458
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1459
+		$cpt_ids = $wpdb->get_col($query);
1460
+		// delete each post meta and term relations too
1461
+		foreach ($cpt_ids as $post_id) {
1462
+			wp_delete_post($post_id, true);
1463
+		}
1464
+	}
1465
+
1466
+	/**
1467
+	 * Deletes all EE custom tables
1468
+	 *
1469
+	 * @return array
1470
+	 */
1471
+	public static function drop_espresso_tables()
1472
+	{
1473
+		$tables = array();
1474
+		// load registry
1475
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1476
+			if (method_exists($model_name, 'instance')) {
1477
+				$model_obj = call_user_func(array($model_name, 'instance'));
1478
+				if ($model_obj instanceof EEM_Base) {
1479
+					foreach ($model_obj->get_tables() as $table) {
1480
+						if (strpos($table->get_table_name(), 'esp_')
1481
+							&&
1482
+							(
1483
+								is_main_site()// main site? nuke them all
1484
+								|| ! $table->is_global()// not main site,but not global either. nuke it
1485
+							)
1486
+						) {
1487
+							$tables[ $table->get_table_name() ] = $table->get_table_name();
1488
+						}
1489
+					}
1490
+				}
1491
+			}
1492
+		}
1493
+
1494
+		// there are some tables whose models were removed.
1495
+		// they should be removed when removing all EE core's data
1496
+		$tables_without_models = array(
1497
+			'esp_promotion',
1498
+			'esp_promotion_applied',
1499
+			'esp_promotion_object',
1500
+			'esp_promotion_rule',
1501
+			'esp_rule',
1502
+		);
1503
+		foreach ($tables_without_models as $table) {
1504
+			$tables[ $table ] = $table;
1505
+		}
1506
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1507
+	}
1508
+
1509
+
1510
+
1511
+	/**
1512
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1513
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1514
+	 * Returns the list actually deleted
1515
+	 *
1516
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1517
+	 * @global WPDB $wpdb
1518
+	 * @param array $table_names
1519
+	 * @return array of table names which we deleted
1520
+	 */
1521
+	public static function drop_tables($table_names)
1522
+	{
1523
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1524
+	}
1525
+
1526
+
1527
+
1528
+	/**
1529
+	 * plugin_uninstall
1530
+	 *
1531
+	 * @access public
1532
+	 * @static
1533
+	 * @param bool $remove_all
1534
+	 * @return void
1535
+	 */
1536
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1537
+	{
1538
+		global $wpdb;
1539
+		self::drop_espresso_tables();
1540
+		$wp_options_to_delete = array(
1541
+			'ee_no_ticket_prices'                => true,
1542
+			'ee_active_messengers'               => true,
1543
+			'ee_has_activated_messenger'         => true,
1544
+			RewriteRules::OPTION_KEY_FLUSH_REWRITE_RULES => true,
1545
+			'ee_config'                          => false,
1546
+			'ee_data_migration_current_db_state' => true,
1547
+			'ee_data_migration_mapping_'         => false,
1548
+			'ee_data_migration_script_'          => false,
1549
+			'ee_data_migrations'                 => true,
1550
+			'ee_dms_map'                         => false,
1551
+			'ee_notices'                         => true,
1552
+			'lang_file_check_'                   => false,
1553
+			'ee_maintenance_mode'                => true,
1554
+			'ee_ueip_optin'                      => true,
1555
+			'ee_ueip_has_notified'               => true,
1556
+			'ee_plugin_activation_errors'        => true,
1557
+			'ee_id_mapping_from'                 => false,
1558
+			'espresso_persistent_admin_notices'  => true,
1559
+			'ee_encryption_key'                  => true,
1560
+			'pue_force_upgrade_'                 => false,
1561
+			'pue_json_error_'                    => false,
1562
+			'pue_install_key_'                   => false,
1563
+			'pue_verification_error_'            => false,
1564
+			'pu_dismissed_upgrade_'              => false,
1565
+			'external_updates-'                  => false,
1566
+			'ee_extra_data'                      => true,
1567
+			'ee_ssn_'                            => false,
1568
+			'ee_rss_'                            => false,
1569
+			'ee_rte_n_tx_'                       => false,
1570
+			'ee_pers_admin_notices'              => true,
1571
+			'ee_job_parameters_'                 => false,
1572
+			'ee_upload_directories_incomplete'   => true,
1573
+			'ee_verified_db_collations'          => true,
1574
+		);
1575
+		if (is_main_site()) {
1576
+			$wp_options_to_delete['ee_network_config'] = true;
1577
+		}
1578
+		$undeleted_options = array();
1579
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1580
+			if ($no_wildcard) {
1581
+				if (! delete_option($option_name)) {
1582
+					$undeleted_options[] = $option_name;
1583
+				}
1584
+			} else {
1585
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1586
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1587
+					if (! delete_option($option_name_from_wildcard)) {
1588
+						$undeleted_options[] = $option_name_from_wildcard;
1589
+					}
1590
+				}
1591
+			}
1592
+		}
1593
+		// also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1594
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1595
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1596
+			$db_update_sans_ee4 = array();
1597
+			foreach ($espresso_db_update as $version => $times_activated) {
1598
+				if ((string) $version[0] === '3') {// if its NON EE4
1599
+					$db_update_sans_ee4[ $version ] = $times_activated;
1600
+				}
1601
+			}
1602
+			update_option('espresso_db_update', $db_update_sans_ee4);
1603
+		}
1604
+		$errors = '';
1605
+		if (! empty($undeleted_options)) {
1606
+			$errors .= sprintf(
1607
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1608
+				'<br/>',
1609
+				implode(',<br/>', $undeleted_options)
1610
+			);
1611
+		}
1612
+		if (! empty($errors)) {
1613
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1614
+		}
1615
+	}
1616
+
1617
+	/**
1618
+	 * Gets the mysql error code from the last used query by wpdb
1619
+	 *
1620
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1621
+	 */
1622
+	public static function last_wpdb_error_code()
1623
+	{
1624
+		// phpcs:disable PHPCompatibility.PHP.RemovedExtensions.mysql_DeprecatedRemoved
1625
+		global $wpdb;
1626
+		if ($wpdb->use_mysqli) {
1627
+			return mysqli_errno($wpdb->dbh);
1628
+		} else {
1629
+			return mysql_errno($wpdb->dbh);
1630
+		}
1631
+		// phpcs:enable
1632
+	}
1633
+
1634
+	/**
1635
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1636
+	 *
1637
+	 * @global wpdb  $wpdb
1638
+	 * @deprecated instead use TableAnalysis::tableExists()
1639
+	 * @param string $table_name with or without $wpdb->prefix
1640
+	 * @return boolean
1641
+	 */
1642
+	public static function table_exists($table_name)
1643
+	{
1644
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1645
+	}
1646
+
1647
+	/**
1648
+	 * Resets the cache on EEH_Activation
1649
+	 */
1650
+	public static function reset()
1651
+	{
1652
+		self::$_default_creator_id                             = null;
1653
+		self::$_initialized_db_content_already_in_this_request = false;
1654
+	}
1655 1655
 }
Please login to merge, or discard this patch.
Spacing   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -54,7 +54,7 @@  discard block
 block discarded – undo
54 54
      */
55 55
     public static function getTableAnalysis()
56 56
     {
57
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
57
+        if ( ! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
58 58
             self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
59 59
         }
60 60
         return self::$table_analysis;
@@ -66,7 +66,7 @@  discard block
 block discarded – undo
66 66
      */
67 67
     public static function getTableManager()
68 68
     {
69
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
69
+        if ( ! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
70 70
             self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
71 71
         }
72 72
         return self::$table_manager;
@@ -180,7 +180,7 @@  discard block
 block discarded – undo
180 180
         if ($which_to_include === 'old') {
181 181
             $cron_tasks = array_filter(
182 182
                 $cron_tasks,
183
-                function ($value) {
183
+                function($value) {
184 184
                     return $value === EEH_Activation::cron_task_no_longer_in_use;
185 185
                 }
186 186
             );
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
     {
211 211
 
212 212
         foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
213
-            if (! wp_next_scheduled($hook_name)) {
213
+            if ( ! wp_next_scheduled($hook_name)) {
214 214
                 /**
215 215
                  * This allows client code to define the initial start timestamp for this schedule.
216 216
                  */
@@ -261,15 +261,15 @@  discard block
 block discarded – undo
261 261
         foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
262 262
             if (is_array($hooks_to_fire_at_time)) {
263 263
                 foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
264
-                    if (isset($ee_cron_tasks_to_remove[ $hook_name ])
265
-                        && is_array($ee_cron_tasks_to_remove[ $hook_name ])
264
+                    if (isset($ee_cron_tasks_to_remove[$hook_name])
265
+                        && is_array($ee_cron_tasks_to_remove[$hook_name])
266 266
                     ) {
267
-                        unset($crons[ $timestamp ][ $hook_name ]);
267
+                        unset($crons[$timestamp][$hook_name]);
268 268
                     }
269 269
                 }
270 270
                 // also take care of any empty cron timestamps.
271 271
                 if (empty($hooks_to_fire_at_time)) {
272
-                    unset($crons[ $timestamp ]);
272
+                    unset($crons[$timestamp]);
273 273
                 }
274 274
             }
275 275
         }
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
             3
315 315
         );
316 316
         // EE_Config::reset();
317
-        if (! EE_Config::logging_enabled()) {
317
+        if ( ! EE_Config::logging_enabled()) {
318 318
             delete_option(EE_Config::LOG_NAME);
319 319
         }
320 320
     }
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
     public static function load_calendar_config()
330 330
     {
331 331
         // grab array of all plugin folders and loop thru it
332
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
332
+        $plugins = glob(WP_PLUGIN_DIR.DS.'*', GLOB_ONLYDIR);
333 333
         if (empty($plugins)) {
334 334
             return;
335 335
         }
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
                 || strpos($plugin, 'calendar') !== false
346 346
             ) {
347 347
                 // this is what we are looking for
348
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
348
+                $calendar_config = $plugin_path.DS.'EE_Calendar_Config.php';
349 349
                 // does it exist in this folder ?
350 350
                 if (is_readable($calendar_config)) {
351 351
                     // YEAH! let's load it
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
             ) {
473 473
                 // update Config with post ID
474 474
                 $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
475
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
475
+                if ( ! EE_Config::instance()->update_espresso_config(false, false)) {
476 476
                     $msg = __(
477 477
                         'The Event Espresso critical page configuration settings could not be updated.',
478 478
                         'event_espresso'
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
                         'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
496 496
                         'event_espresso'
497 497
                     ),
498
-                    '<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">'
498
+                    '<a href="'.admin_url('admin.php?page=espresso_general_settings&action=critical_pages').'">'
499 499
                     . __('Event Espresso Critical Pages Settings', 'event_espresso')
500 500
                     . '</a>'
501 501
                 )
@@ -521,7 +521,7 @@  discard block
 block discarded – undo
521 521
     public static function get_page_by_ee_shortcode($ee_shortcode)
522 522
     {
523 523
         global $wpdb;
524
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
524
+        $shortcode_and_opening_bracket = '['.$ee_shortcode;
525 525
         $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
526 526
         if ($post_id) {
527 527
             return get_post($post_id);
@@ -547,11 +547,11 @@  discard block
 block discarded – undo
547 547
             'post_status'    => 'publish',
548 548
             'post_type'      => 'page',
549 549
             'comment_status' => 'closed',
550
-            'post_content'   => '[' . $critical_page['code'] . ']',
550
+            'post_content'   => '['.$critical_page['code'].']',
551 551
         );
552 552
 
553 553
         $post_id = wp_insert_post($post_args);
554
-        if (! $post_id) {
554
+        if ( ! $post_id) {
555 555
             $msg = sprintf(
556 556
                 __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
557 557
                 $critical_page['name']
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
             return $critical_page;
561 561
         }
562 562
         // get newly created post's details
563
-        if (! $critical_page['post'] = get_post($post_id)) {
563
+        if ( ! $critical_page['post'] = get_post($post_id)) {
564 564
             $msg = sprintf(
565 565
                 __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
566 566
                 $critical_page['name']
@@ -585,7 +585,7 @@  discard block
 block discarded – undo
585 585
     public static function get_default_creator_id()
586 586
     {
587 587
         global $wpdb;
588
-        if (! empty(self::$_default_creator_id)) {
588
+        if ( ! empty(self::$_default_creator_id)) {
589 589
             return self::$_default_creator_id;
590 590
         }/**/
591 591
         $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
         $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
602 602
         $query = $wpdb->prepare(
603 603
             "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
604
-            '%' . $role_to_check . '%'
604
+            '%'.$role_to_check.'%'
605 605
         );
606 606
         $user_id = $wpdb->get_var($query);
607 607
         $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
@@ -640,8 +640,8 @@  discard block
 block discarded – undo
640 640
             return;
641 641
         }
642 642
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
643
-        if (! function_exists('dbDelta')) {
644
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
643
+        if ( ! function_exists('dbDelta')) {
644
+            require_once(ABSPATH.'wp-admin/includes/upgrade.php');
645 645
         }
646 646
         $tableAnalysis = \EEH_Activation::getTableAnalysis();
647 647
         $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
@@ -650,9 +650,9 @@  discard block
 block discarded – undo
650 650
             // ok, delete the table... but ONLY if it's empty
651 651
             $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
652 652
             // table is NOT empty, are you SURE you want to delete this table ???
653
-            if (! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
653
+            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
654 654
                 \EEH_Activation::getTableManager()->dropTable($wp_table_name);
655
-            } elseif (! $deleted_safely) {
655
+            } elseif ( ! $deleted_safely) {
656 656
                 // so we should be more cautious rather than just dropping tables so easily
657 657
                 error_log(
658 658
                     sprintf(
@@ -852,13 +852,13 @@  discard block
 block discarded – undo
852 852
             // reset values array
853 853
             $QSG_values = array();
854 854
             // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
855
-            if (! in_array("$QSG_system", $question_groups)) {
855
+            if ( ! in_array("$QSG_system", $question_groups)) {
856 856
                 // add it
857 857
                 switch ($QSG_system) {
858 858
                     case 1:
859 859
                         $QSG_values = array(
860 860
                             'QSG_name'            => __('Personal Information', 'event_espresso'),
861
-                            'QSG_identifier'      => 'personal-information-' . time(),
861
+                            'QSG_identifier'      => 'personal-information-'.time(),
862 862
                             'QSG_desc'            => '',
863 863
                             'QSG_order'           => 1,
864 864
                             'QSG_show_group_name' => 1,
@@ -870,7 +870,7 @@  discard block
 block discarded – undo
870 870
                     case 2:
871 871
                         $QSG_values = array(
872 872
                             'QSG_name'            => __('Address Information', 'event_espresso'),
873
-                            'QSG_identifier'      => 'address-information-' . time(),
873
+                            'QSG_identifier'      => 'address-information-'.time(),
874 874
                             'QSG_desc'            => '',
875 875
                             'QSG_order'           => 2,
876 876
                             'QSG_show_group_name' => 1,
@@ -881,14 +881,14 @@  discard block
 block discarded – undo
881 881
                         break;
882 882
                 }
883 883
                 // make sure we have some values before inserting them
884
-                if (! empty($QSG_values)) {
884
+                if ( ! empty($QSG_values)) {
885 885
                     // insert system question
886 886
                     $wpdb->insert(
887 887
                         $table_name,
888 888
                         $QSG_values,
889 889
                         array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
890 890
                     );
891
-                    $QSG_IDs[ $QSG_system ] = $wpdb->insert_id;
891
+                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
892 892
                 }
893 893
             }
894 894
         }
@@ -918,7 +918,7 @@  discard block
 block discarded – undo
918 918
             // reset values array
919 919
             $QST_values = array();
920 920
             // if we don't have what we should have
921
-            if (! in_array($QST_system, $questions)) {
921
+            if ( ! in_array($QST_system, $questions)) {
922 922
                 // add it
923 923
                 switch ($QST_system) {
924 924
                     case 'fname':
@@ -1070,7 +1070,7 @@  discard block
 block discarded – undo
1070 1070
                         );
1071 1071
                         break;
1072 1072
                 }
1073
-                if (! empty($QST_values)) {
1073
+                if ( ! empty($QST_values)) {
1074 1074
                     // insert system question
1075 1075
                     $wpdb->insert(
1076 1076
                         $table_name,
@@ -1084,8 +1084,8 @@  discard block
 block discarded – undo
1084 1084
                     } else {
1085 1085
                         $system_question_we_want = EEM_Question_Group::system_address;
1086 1086
                     }
1087
-                    if (isset($QSG_IDs[ $system_question_we_want ])) {
1088
-                        $QSG_ID = $QSG_IDs[ $system_question_we_want ];
1087
+                    if (isset($QSG_IDs[$system_question_we_want])) {
1088
+                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1089 1089
                     } else {
1090 1090
                         $id_col = EEM_Question_Group::instance()
1091 1091
                                                     ->get_col(array(array('QSG_system' => $system_question_we_want)));
@@ -1133,7 +1133,7 @@  discard block
 block discarded – undo
1133 1133
      */
1134 1134
     public static function insert_default_payment_methods()
1135 1135
     {
1136
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1136
+        if ( ! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1137 1137
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
1138 1138
             EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1139 1139
         } else {
@@ -1270,7 +1270,7 @@  discard block
 block discarded – undo
1270 1270
                         $active_messenger->name,
1271 1271
                         $default_message_type_name_for_messenger
1272 1272
                     )
1273
-                    || ! isset($installed_message_types[ $default_message_type_name_for_messenger ])
1273
+                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1274 1274
                 ) {
1275 1275
                     continue;
1276 1276
                 }
@@ -1283,7 +1283,7 @@  discard block
 block discarded – undo
1283 1283
                 false
1284 1284
             );
1285 1285
             // activate the templates for these message types
1286
-            if (! empty($default_message_type_names_to_activate)) {
1286
+            if ( ! empty($default_message_type_names_to_activate)) {
1287 1287
                 $templates_created = EEH_MSG_Template::generate_new_templates(
1288 1288
                     $active_messenger->name,
1289 1289
                     $default_message_type_names_for_messenger,
@@ -1317,13 +1317,13 @@  discard block
 block discarded – undo
1317 1317
             $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1318 1318
             // verify the default message types match an installed message type.
1319 1319
             foreach ($default_message_type_names_for_messenger as $key => $name) {
1320
-                if (! isset($installed_message_types[ $name ])
1320
+                if ( ! isset($installed_message_types[$name])
1321 1321
                     || $message_resource_manager->has_message_type_been_activated_for_messenger(
1322 1322
                         $name,
1323 1323
                         $messenger_to_generate->name
1324 1324
                     )
1325 1325
                 ) {
1326
-                    unset($default_message_type_names_for_messenger[ $key ]);
1326
+                    unset($default_message_type_names_for_messenger[$key]);
1327 1327
                 }
1328 1328
             }
1329 1329
             // in previous iterations, the active_messengers option in the db
@@ -1337,7 +1337,7 @@  discard block
 block discarded – undo
1337 1337
                 false
1338 1338
             );
1339 1339
             // create any templates needing created (or will reactivate templates already generated as necessary).
1340
-            if (! empty($default_message_type_names_for_messenger)) {
1340
+            if ( ! empty($default_message_type_names_for_messenger)) {
1341 1341
                 $templates_generated = EEH_MSG_Template::generate_new_templates(
1342 1342
                     $messenger_to_generate->name,
1343 1343
                     $default_message_type_names_for_messenger,
@@ -1372,13 +1372,13 @@  discard block
 block discarded – undo
1372 1372
             // if installed messenger is a messenger that should be activated on install
1373 1373
             // and is not already active
1374 1374
             // and has never been activated
1375
-            if (! $installed_messenger->activate_on_install
1376
-                || isset($active_messengers[ $installed_messenger->name ])
1377
-                || isset($has_activated[ $installed_messenger->name ])
1375
+            if ( ! $installed_messenger->activate_on_install
1376
+                || isset($active_messengers[$installed_messenger->name])
1377
+                || isset($has_activated[$installed_messenger->name])
1378 1378
             ) {
1379 1379
                 continue;
1380 1380
             }
1381
-            $messengers_to_generate[ $installed_messenger->name ] = $installed_messenger;
1381
+            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1382 1382
         }
1383 1383
         return $messengers_to_generate;
1384 1384
     }
@@ -1416,7 +1416,7 @@  discard block
 block discarded – undo
1416 1416
         // this creates an array for tracking events that have no active ticket prices created
1417 1417
         // this allows us to warn admins of the situation so that it can be corrected
1418 1418
         $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1419
-        if (! $espresso_no_ticket_prices) {
1419
+        if ( ! $espresso_no_ticket_prices) {
1420 1420
             add_option('ee_no_ticket_prices', array(), '', false);
1421 1421
         }
1422 1422
     }
@@ -1455,7 +1455,7 @@  discard block
 block discarded – undo
1455 1455
             }
1456 1456
         }
1457 1457
         // get all our CPTs
1458
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1458
+        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",", $ee_post_types).")";
1459 1459
         $cpt_ids = $wpdb->get_col($query);
1460 1460
         // delete each post meta and term relations too
1461 1461
         foreach ($cpt_ids as $post_id) {
@@ -1484,7 +1484,7 @@  discard block
 block discarded – undo
1484 1484
                                 || ! $table->is_global()// not main site,but not global either. nuke it
1485 1485
                             )
1486 1486
                         ) {
1487
-                            $tables[ $table->get_table_name() ] = $table->get_table_name();
1487
+                            $tables[$table->get_table_name()] = $table->get_table_name();
1488 1488
                         }
1489 1489
                     }
1490 1490
                 }
@@ -1501,7 +1501,7 @@  discard block
 block discarded – undo
1501 1501
             'esp_rule',
1502 1502
         );
1503 1503
         foreach ($tables_without_models as $table) {
1504
-            $tables[ $table ] = $table;
1504
+            $tables[$table] = $table;
1505 1505
         }
1506 1506
         return \EEH_Activation::getTableManager()->dropTables($tables);
1507 1507
     }
@@ -1578,13 +1578,13 @@  discard block
 block discarded – undo
1578 1578
         $undeleted_options = array();
1579 1579
         foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1580 1580
             if ($no_wildcard) {
1581
-                if (! delete_option($option_name)) {
1581
+                if ( ! delete_option($option_name)) {
1582 1582
                     $undeleted_options[] = $option_name;
1583 1583
                 }
1584 1584
             } else {
1585 1585
                 $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1586 1586
                 foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1587
-                    if (! delete_option($option_name_from_wildcard)) {
1587
+                    if ( ! delete_option($option_name_from_wildcard)) {
1588 1588
                         $undeleted_options[] = $option_name_from_wildcard;
1589 1589
                     }
1590 1590
                 }
@@ -1596,20 +1596,20 @@  discard block
 block discarded – undo
1596 1596
             $db_update_sans_ee4 = array();
1597 1597
             foreach ($espresso_db_update as $version => $times_activated) {
1598 1598
                 if ((string) $version[0] === '3') {// if its NON EE4
1599
-                    $db_update_sans_ee4[ $version ] = $times_activated;
1599
+                    $db_update_sans_ee4[$version] = $times_activated;
1600 1600
                 }
1601 1601
             }
1602 1602
             update_option('espresso_db_update', $db_update_sans_ee4);
1603 1603
         }
1604 1604
         $errors = '';
1605
-        if (! empty($undeleted_options)) {
1605
+        if ( ! empty($undeleted_options)) {
1606 1606
             $errors .= sprintf(
1607 1607
                 __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1608 1608
                 '<br/>',
1609 1609
                 implode(',<br/>', $undeleted_options)
1610 1610
             );
1611 1611
         }
1612
-        if (! empty($errors)) {
1612
+        if ( ! empty($errors)) {
1613 1613
             EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1614 1614
         }
1615 1615
     }
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -529,7 +529,7 @@
 block discarded – undo
529 529
     /**
530 530
      * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
531 531
      *
532
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
532
+     * @param  string[] $stati_to_include If included you can restrict the statuses we return counts for by including the
533 533
      *                                 stati you want counts for as values in the array.  An empty array returns counts
534 534
      *                                 for all valid stati.
535 535
      * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
Please login to merge, or discard this patch.
Indentation   +655 added lines, -655 removed lines patch added patch discarded remove patch
@@ -9,659 +9,659 @@
 block discarded – undo
9 9
 class EEM_Datetime extends EEM_Soft_Delete_Base
10 10
 {
11 11
 
12
-    /**
13
-     * @var EEM_Datetime $_instance
14
-     */
15
-    protected static $_instance;
16
-
17
-
18
-    /**
19
-     * private constructor to prevent direct creation
20
-     *
21
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
-     *                         (and any incoming timezone data that gets saved).
23
-     *                         Note this just sends the timezone info to the date time model field objects.
24
-     *                         Default is NULL
25
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
-     * @throws EE_Error
27
-     * @throws InvalidArgumentException
28
-     * @throws InvalidArgumentException
29
-     */
30
-    protected function __construct($timezone)
31
-    {
32
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
-        $this->_tables                 = array(
35
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
-        );
37
-        $this->_fields                 = array(
38
-            'Datetime' => array(
39
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
-                    'DTT_ID',
41
-                    esc_html__('Datetime ID', 'event_espresso')
42
-                ),
43
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
-                    'EVT_ID',
45
-                    esc_html__('Event ID', 'event_espresso'),
46
-                    false,
47
-                    0,
48
-                    'Event'
49
-                ),
50
-                'DTT_name'        => new EE_Plain_Text_Field(
51
-                    'DTT_name',
52
-                    esc_html__('Datetime Name', 'event_espresso'),
53
-                    false,
54
-                    ''
55
-                ),
56
-                'DTT_description' => new EE_Post_Content_Field(
57
-                    'DTT_description',
58
-                    esc_html__('Description for Datetime', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'DTT_EVT_start'   => new EE_Datetime_Field(
63
-                    'DTT_EVT_start',
64
-                    esc_html__('Start time/date of Event', 'event_espresso'),
65
-                    false,
66
-                    EE_Datetime_Field::now,
67
-                    $timezone
68
-                ),
69
-                'DTT_EVT_end'     => new EE_Datetime_Field(
70
-                    'DTT_EVT_end',
71
-                    esc_html__('End time/date of Event', 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now,
74
-                    $timezone
75
-                ),
76
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
-                    'DTT_reg_limit',
78
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
79
-                    true,
80
-                    EE_INF
81
-                ),
82
-                'DTT_sold'        => new EE_Integer_Field(
83
-                    'DTT_sold',
84
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
-                    true,
86
-                    0
87
-                ),
88
-                'DTT_reserved'    => new EE_Integer_Field(
89
-                    'DTT_reserved',
90
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
-                    false,
92
-                    0
93
-                ),
94
-                'DTT_is_primary'  => new EE_Boolean_Field(
95
-                    'DTT_is_primary',
96
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
-                    false,
98
-                    false
99
-                ),
100
-                'DTT_order'       => new EE_Integer_Field(
101
-                    'DTT_order',
102
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
-                    false,
104
-                    0
105
-                ),
106
-                'DTT_parent'      => new EE_Integer_Field(
107
-                    'DTT_parent',
108
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
-                    true,
110
-                    0
111
-                ),
112
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
-                    'DTT_deleted',
114
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
-                    false,
116
-                    false
117
-                ),
118
-            ),
119
-        );
120
-        $this->_model_relations        = array(
121
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
-            'Event'   => new EE_Belongs_To_Relation(),
123
-            'Checkin' => new EE_Has_Many_Relation(),
124
-        );
125
-        $this->_model_chain_to_wp_user = 'Event';
126
-        // this model is generally available for reading
127
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
128
-            'Event'
129
-        );
130
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
131
-            'Event'
132
-        );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
134
-            'Event'
135
-        );
136
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
137
-            'Event',
138
-            EEM_Base::caps_edit
139
-        );
140
-        parent::__construct($timezone);
141
-    }
142
-
143
-
144
-    /**
145
-     * create new blank datetime
146
-     *
147
-     * @access public
148
-     * @return EE_Datetime[] array on success, FALSE on fail
149
-     * @throws EE_Error
150
-     */
151
-    public function create_new_blank_datetime()
152
-    {
153
-        // makes sure timezone is always set.
154
-        $timezone_string = $this->get_timezone();
155
-        $blank_datetime  = EE_Datetime::new_instance(
156
-            array(
157
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
158
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
159
-                'DTT_order'     => 1,
160
-                'DTT_reg_limit' => EE_INF,
161
-            ),
162
-            $timezone_string
163
-        );
164
-        $blank_datetime->set_start_time(
165
-            $this->convert_datetime_for_query(
166
-                'DTT_EVT_start',
167
-                '8am',
168
-                'ga',
169
-                $timezone_string
170
-            )
171
-        );
172
-        $blank_datetime->set_end_time(
173
-            $this->convert_datetime_for_query(
174
-                'DTT_EVT_end',
175
-                '5pm',
176
-                'ga',
177
-                $timezone_string
178
-            )
179
-        );
180
-        return array($blank_datetime);
181
-    }
182
-
183
-
184
-    /**
185
-     * get event start date from db
186
-     *
187
-     * @access public
188
-     * @param  int $EVT_ID
189
-     * @return EE_Datetime[] array on success, FALSE on fail
190
-     * @throws EE_Error
191
-     */
192
-    public function get_all_event_dates($EVT_ID = 0)
193
-    {
194
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
195
-            return $this->create_new_blank_datetime();
196
-        }
197
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
198
-        if (empty($results)) {
199
-            return $this->create_new_blank_datetime();
200
-        }
201
-        return $results;
202
-    }
203
-
204
-
205
-    /**
206
-     * get all datetimes attached to an event ordered by the DTT_order field
207
-     *
208
-     * @public
209
-     * @param  int    $EVT_ID     event id
210
-     * @param boolean $include_expired
211
-     * @param boolean $include_deleted
212
-     * @param  int    $limit      If included then limit the count of results by
213
-     *                            the given number
214
-     * @return EE_Datetime[]
215
-     * @throws EE_Error
216
-     */
217
-    public function get_datetimes_for_event_ordered_by_DTT_order(
218
-        $EVT_ID,
219
-        $include_expired = true,
220
-        $include_deleted = true,
221
-        $limit = null
222
-    ) {
223
-        // sanitize EVT_ID
224
-        $EVT_ID         = absint($EVT_ID);
225
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
226
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
227
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
228
-        $query_params = ! empty($limit)
229
-            ? array(
230
-                $where_params,
231
-                'limit'                    => $limit,
232
-                'order_by'                 => array('DTT_order' => 'ASC'),
233
-                'default_where_conditions' => 'none',
234
-            )
235
-            : array(
236
-                $where_params,
237
-                'order_by'                 => array('DTT_order' => 'ASC'),
238
-                'default_where_conditions' => 'none',
239
-            );
240
-        if (! $include_expired) {
241
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
242
-        }
243
-        if ($include_deleted) {
244
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
245
-        }
246
-        /** @var EE_Datetime[] $result */
247
-        $result = $this->get_all($query_params);
248
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
249
-        return $result;
250
-    }
251
-
252
-
253
-    /**
254
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
255
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
256
-     * and then the earlier datetimes are the most important.
257
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
258
-     *
259
-     * @param int $EVT_ID
260
-     * @param int $limit
261
-     * @return EE_Datetime[]|EE_Base_Class[]
262
-     * @throws EE_Error
263
-     */
264
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
265
-    {
266
-        return $this->get_all(
267
-            array(
268
-                array('Event.EVT_ID' => $EVT_ID),
269
-                'limit'                    => $limit,
270
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
271
-                'default_where_conditions' => 'none',
272
-            )
273
-        );
274
-    }
275
-
276
-
277
-    /**
278
-     * @param int     $EVT_ID
279
-     * @param boolean $include_expired
280
-     * @param boolean $include_deleted
281
-     * @return EE_Datetime
282
-     * @throws EE_Error
283
-     */
284
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
285
-    {
286
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
287
-            $EVT_ID,
288
-            $include_expired,
289
-            $include_deleted,
290
-            1
291
-        );
292
-        if ($results) {
293
-            return array_shift($results);
294
-        }
295
-        return null;
296
-    }
297
-
298
-
299
-    /**
300
-     * Gets the 'primary' datetime for an event.
301
-     *
302
-     * @param int  $EVT_ID
303
-     * @param bool $try_to_exclude_expired
304
-     * @param bool $try_to_exclude_deleted
305
-     * @return \EE_Datetime
306
-     * @throws EE_Error
307
-     */
308
-    public function get_primary_datetime_for_event(
309
-        $EVT_ID,
310
-        $try_to_exclude_expired = true,
311
-        $try_to_exclude_deleted = true
312
-    ) {
313
-        if ($try_to_exclude_expired) {
314
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
315
-            if ($non_expired) {
316
-                return $non_expired;
317
-            }
318
-        }
319
-        if ($try_to_exclude_deleted) {
320
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
321
-            if ($expired_even) {
322
-                return $expired_even;
323
-            }
324
-        }
325
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
326
-    }
327
-
328
-
329
-    /**
330
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
331
-     * only by start date
332
-     *
333
-     * @param int     $EVT_ID
334
-     * @param boolean $include_expired
335
-     * @param boolean $include_deleted
336
-     * @param int     $limit
337
-     * @return EE_Datetime[]
338
-     * @throws EE_Error
339
-     */
340
-    public function get_datetimes_for_event_ordered_by_start_time(
341
-        $EVT_ID,
342
-        $include_expired = true,
343
-        $include_deleted = true,
344
-        $limit = null
345
-    ) {
346
-        // sanitize EVT_ID
347
-        $EVT_ID         = absint($EVT_ID);
348
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
349
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
350
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
351
-        if (! $include_expired) {
352
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
353
-        }
354
-        if ($include_deleted) {
355
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
356
-        }
357
-        if ($limit) {
358
-            $query_params['limit'] = $limit;
359
-        }
360
-        /** @var EE_Datetime[] $result */
361
-        $result = $this->get_all($query_params);
362
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
363
-        return $result;
364
-    }
365
-
366
-
367
-    /**
368
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
369
-     * only by start date
370
-     *
371
-     * @param int     $TKT_ID
372
-     * @param boolean $include_expired
373
-     * @param boolean $include_deleted
374
-     * @param int     $limit
375
-     * @return EE_Datetime[]
376
-     * @throws EE_Error
377
-     */
378
-    public function get_datetimes_for_ticket_ordered_by_start_time(
379
-        $TKT_ID,
380
-        $include_expired = true,
381
-        $include_deleted = true,
382
-        $limit = null
383
-    ) {
384
-        // sanitize TKT_ID
385
-        $TKT_ID         = absint($TKT_ID);
386
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
387
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
388
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
389
-        if (! $include_expired) {
390
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
391
-        }
392
-        if ($include_deleted) {
393
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
394
-        }
395
-        if ($limit) {
396
-            $query_params['limit'] = $limit;
397
-        }
398
-        /** @var EE_Datetime[] $result */
399
-        $result = $this->get_all($query_params);
400
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
401
-        return $result;
402
-    }
403
-
404
-
405
-    /**
406
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
407
-     * datetimes.
408
-     *
409
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
410
-     * @param  boolean  $include_expired whether to include expired datetimes or not
411
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
412
-     * @param  int|null $limit           if null, no limit, if int then limit results by
413
-     *                                   that number
414
-     * @return EE_Datetime[]
415
-     * @throws EE_Error
416
-     */
417
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
418
-        $TKT_ID,
419
-        $include_expired = true,
420
-        $include_deleted = true,
421
-        $limit = null
422
-    ) {
423
-        // sanitize id.
424
-        $TKT_ID         = absint($TKT_ID);
425
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
426
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
427
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
428
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
429
-        if (! $include_expired) {
430
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
431
-        }
432
-        if ($include_deleted) {
433
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
434
-        }
435
-        if ($limit) {
436
-            $query_params['limit'] = $limit;
437
-        }
438
-        /** @var EE_Datetime[] $result */
439
-        $result = $this->get_all($query_params);
440
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
441
-        return $result;
442
-    }
443
-
444
-
445
-    /**
446
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
447
-     * reason it doesn't exist, we consider the earliest event the most important)
448
-     *
449
-     * @param int $EVT_ID
450
-     * @return EE_Datetime
451
-     * @throws EE_Error
452
-     */
453
-    public function get_most_important_datetime_for_event($EVT_ID)
454
-    {
455
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
456
-        if ($results) {
457
-            return array_shift($results);
458
-        }
459
-        return null;
460
-    }
461
-
462
-
463
-    /**
464
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
465
-     * grouped by month and year.
466
-     *
467
-     * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
468
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
469
-     *                                   Can be:
470
-     *                                   - '' = no filter
471
-     *                                   - upcoming = Published events with at least one upcoming datetime.
472
-     *                                   - expired = Events with all datetimes expired.
473
-     *                                   - active = Events that are published and have at least one datetime that
474
-     *                                   starts before now and ends after now.
475
-     *                                   - inactive = Events that are either not published.
476
-     * @return EE_Base_Class[]
477
-     * @throws EE_Error
478
-     * @throws InvalidArgumentException
479
-     * @throws InvalidArgumentException
480
-     */
481
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
482
-    {
483
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
484
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
485
-        switch ($evt_active_status) {
486
-            case 'upcoming':
487
-                $where_params['Event.status'] = 'publish';
488
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
489
-                if (isset($where_params['DTT_EVT_start'])) {
490
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
491
-                }
492
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
493
-                break;
494
-            case 'expired':
495
-                if (isset($where_params['Event.status'])) {
496
-                    unset($where_params['Event.status']);
497
-                }
498
-                // get events to exclude
499
-                $exclude_query[0] = array_merge(
500
-                    $where_params,
501
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
502
-                );
503
-                // first get all events that have datetimes where its not expired.
504
-                $event_ids = $this->_get_all_wpdb_results(
505
-                    $exclude_query,
506
-                    OBJECT_K,
507
-                    'Datetime.EVT_ID'
508
-                );
509
-                $event_ids = array_keys($event_ids);
510
-                if (isset($where_params['DTT_EVT_end'])) {
511
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
512
-                }
513
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
514
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
515
-                break;
516
-            case 'active':
517
-                $where_params['Event.status'] = 'publish';
518
-                if (isset($where_params['DTT_EVT_start'])) {
519
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
520
-                }
521
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
522
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
523
-                }
524
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
525
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
526
-                break;
527
-            case 'inactive':
528
-                if (isset($where_params['Event.status'])) {
529
-                    unset($where_params['Event.status']);
530
-                }
531
-                if (isset($where_params['OR'])) {
532
-                    $where_params['AND']['OR'] = $where_params['OR'];
533
-                }
534
-                if (isset($where_params['DTT_EVT_end'])) {
535
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
536
-                    unset($where_params['DTT_EVT_end']);
537
-                }
538
-                if (isset($where_params['DTT_EVT_start'])) {
539
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
540
-                    unset($where_params['DTT_EVT_start']);
541
-                }
542
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
543
-                break;
544
-        }
545
-        $query_params[0]          = $where_params;
546
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
547
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
548
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
549
-            $this->get_timezone(),
550
-            'DTT_EVT_start'
551
-        );
552
-        $columns_to_select        = array(
553
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
554
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
555
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
556
-        );
557
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
558
-    }
559
-
560
-
561
-    /**
562
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
563
-     * for the tickets for each datetime)
564
-     *
565
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
566
-     * @throws EE_Error
567
-     */
568
-    public function update_sold($datetimes)
569
-    {
570
-        EE_Error::doing_it_wrong(
571
-            __FUNCTION__,
572
-            esc_html__(
573
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
574
-                'event_espresso'
575
-            ),
576
-            '4.9.32.rc.005'
577
-        );
578
-        foreach ($datetimes as $datetime) {
579
-            $datetime->update_sold();
580
-        }
581
-    }
582
-
583
-
584
-    /**
585
-     *    Gets the total number of tickets available at a particular datetime
586
-     *    (does NOT take into account the datetime's spaces available)
587
-     *
588
-     * @param int   $DTT_ID
589
-     * @param array $query_params
590
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
591
-     *             tickets attached to datetime then FALSE is returned.
592
-     */
593
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
594
-    {
595
-        $datetime = $this->get_one_by_ID($DTT_ID);
596
-        if ($datetime instanceof EE_Datetime) {
597
-            return $datetime->tickets_remaining($query_params);
598
-        }
599
-        return 0;
600
-    }
601
-
602
-
603
-    /**
604
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
605
-     *
606
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
607
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
608
-     *                                 for all valid stati.
609
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
610
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
611
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
612
-     * @throws EE_Error
613
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
614
-     *                                 EE_Datetime::expired
615
-     */
616
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
617
-    {
618
-        // only accept where conditions for this query.
619
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
620
-        $status_query_args = array(
621
-            EE_Datetime::active   => array_merge(
622
-                $_where,
623
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
624
-            ),
625
-            EE_Datetime::upcoming => array_merge(
626
-                $_where,
627
-                array('DTT_EVT_start' => array('>', time()))
628
-            ),
629
-            EE_Datetime::expired  => array_merge(
630
-                $_where,
631
-                array('DTT_EVT_end' => array('<', time()))
632
-            ),
633
-        );
634
-        if (! empty($stati_to_include)) {
635
-            foreach (array_keys($status_query_args) as $status) {
636
-                if (! in_array($status, $stati_to_include, true)) {
637
-                    unset($status_query_args[ $status ]);
638
-                }
639
-            }
640
-        }
641
-        // loop through and query counts for each stati.
642
-        $status_query_results = array();
643
-        foreach ($status_query_args as $status => $status_where_conditions) {
644
-            $status_query_results[ $status ] = EEM_Datetime::count(
645
-                array($status_where_conditions),
646
-                'DTT_ID',
647
-                true
648
-            );
649
-        }
650
-        return $status_query_results;
651
-    }
652
-
653
-
654
-    /**
655
-     * Returns the specific count for a given Datetime status matching any given query_params.
656
-     *
657
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
658
-     * @param array  $query_params
659
-     * @return int
660
-     * @throws EE_Error
661
-     */
662
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
663
-    {
664
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
665
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
666
-    }
12
+	/**
13
+	 * @var EEM_Datetime $_instance
14
+	 */
15
+	protected static $_instance;
16
+
17
+
18
+	/**
19
+	 * private constructor to prevent direct creation
20
+	 *
21
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
+	 *                         (and any incoming timezone data that gets saved).
23
+	 *                         Note this just sends the timezone info to the date time model field objects.
24
+	 *                         Default is NULL
25
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
+	 * @throws EE_Error
27
+	 * @throws InvalidArgumentException
28
+	 * @throws InvalidArgumentException
29
+	 */
30
+	protected function __construct($timezone)
31
+	{
32
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
+		$this->_tables                 = array(
35
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
+		);
37
+		$this->_fields                 = array(
38
+			'Datetime' => array(
39
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
+					'DTT_ID',
41
+					esc_html__('Datetime ID', 'event_espresso')
42
+				),
43
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
+					'EVT_ID',
45
+					esc_html__('Event ID', 'event_espresso'),
46
+					false,
47
+					0,
48
+					'Event'
49
+				),
50
+				'DTT_name'        => new EE_Plain_Text_Field(
51
+					'DTT_name',
52
+					esc_html__('Datetime Name', 'event_espresso'),
53
+					false,
54
+					''
55
+				),
56
+				'DTT_description' => new EE_Post_Content_Field(
57
+					'DTT_description',
58
+					esc_html__('Description for Datetime', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'DTT_EVT_start'   => new EE_Datetime_Field(
63
+					'DTT_EVT_start',
64
+					esc_html__('Start time/date of Event', 'event_espresso'),
65
+					false,
66
+					EE_Datetime_Field::now,
67
+					$timezone
68
+				),
69
+				'DTT_EVT_end'     => new EE_Datetime_Field(
70
+					'DTT_EVT_end',
71
+					esc_html__('End time/date of Event', 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now,
74
+					$timezone
75
+				),
76
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
+					'DTT_reg_limit',
78
+					esc_html__('Registration Limit for this time', 'event_espresso'),
79
+					true,
80
+					EE_INF
81
+				),
82
+				'DTT_sold'        => new EE_Integer_Field(
83
+					'DTT_sold',
84
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
+					true,
86
+					0
87
+				),
88
+				'DTT_reserved'    => new EE_Integer_Field(
89
+					'DTT_reserved',
90
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
+					false,
92
+					0
93
+				),
94
+				'DTT_is_primary'  => new EE_Boolean_Field(
95
+					'DTT_is_primary',
96
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
+					false,
98
+					false
99
+				),
100
+				'DTT_order'       => new EE_Integer_Field(
101
+					'DTT_order',
102
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
+					false,
104
+					0
105
+				),
106
+				'DTT_parent'      => new EE_Integer_Field(
107
+					'DTT_parent',
108
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
+					true,
110
+					0
111
+				),
112
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
+					'DTT_deleted',
114
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
+					false,
116
+					false
117
+				),
118
+			),
119
+		);
120
+		$this->_model_relations        = array(
121
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
+			'Event'   => new EE_Belongs_To_Relation(),
123
+			'Checkin' => new EE_Has_Many_Relation(),
124
+		);
125
+		$this->_model_chain_to_wp_user = 'Event';
126
+		// this model is generally available for reading
127
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
128
+			'Event'
129
+		);
130
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
131
+			'Event'
132
+		);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
134
+			'Event'
135
+		);
136
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
137
+			'Event',
138
+			EEM_Base::caps_edit
139
+		);
140
+		parent::__construct($timezone);
141
+	}
142
+
143
+
144
+	/**
145
+	 * create new blank datetime
146
+	 *
147
+	 * @access public
148
+	 * @return EE_Datetime[] array on success, FALSE on fail
149
+	 * @throws EE_Error
150
+	 */
151
+	public function create_new_blank_datetime()
152
+	{
153
+		// makes sure timezone is always set.
154
+		$timezone_string = $this->get_timezone();
155
+		$blank_datetime  = EE_Datetime::new_instance(
156
+			array(
157
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
158
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
159
+				'DTT_order'     => 1,
160
+				'DTT_reg_limit' => EE_INF,
161
+			),
162
+			$timezone_string
163
+		);
164
+		$blank_datetime->set_start_time(
165
+			$this->convert_datetime_for_query(
166
+				'DTT_EVT_start',
167
+				'8am',
168
+				'ga',
169
+				$timezone_string
170
+			)
171
+		);
172
+		$blank_datetime->set_end_time(
173
+			$this->convert_datetime_for_query(
174
+				'DTT_EVT_end',
175
+				'5pm',
176
+				'ga',
177
+				$timezone_string
178
+			)
179
+		);
180
+		return array($blank_datetime);
181
+	}
182
+
183
+
184
+	/**
185
+	 * get event start date from db
186
+	 *
187
+	 * @access public
188
+	 * @param  int $EVT_ID
189
+	 * @return EE_Datetime[] array on success, FALSE on fail
190
+	 * @throws EE_Error
191
+	 */
192
+	public function get_all_event_dates($EVT_ID = 0)
193
+	{
194
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
195
+			return $this->create_new_blank_datetime();
196
+		}
197
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
198
+		if (empty($results)) {
199
+			return $this->create_new_blank_datetime();
200
+		}
201
+		return $results;
202
+	}
203
+
204
+
205
+	/**
206
+	 * get all datetimes attached to an event ordered by the DTT_order field
207
+	 *
208
+	 * @public
209
+	 * @param  int    $EVT_ID     event id
210
+	 * @param boolean $include_expired
211
+	 * @param boolean $include_deleted
212
+	 * @param  int    $limit      If included then limit the count of results by
213
+	 *                            the given number
214
+	 * @return EE_Datetime[]
215
+	 * @throws EE_Error
216
+	 */
217
+	public function get_datetimes_for_event_ordered_by_DTT_order(
218
+		$EVT_ID,
219
+		$include_expired = true,
220
+		$include_deleted = true,
221
+		$limit = null
222
+	) {
223
+		// sanitize EVT_ID
224
+		$EVT_ID         = absint($EVT_ID);
225
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
226
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
227
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
228
+		$query_params = ! empty($limit)
229
+			? array(
230
+				$where_params,
231
+				'limit'                    => $limit,
232
+				'order_by'                 => array('DTT_order' => 'ASC'),
233
+				'default_where_conditions' => 'none',
234
+			)
235
+			: array(
236
+				$where_params,
237
+				'order_by'                 => array('DTT_order' => 'ASC'),
238
+				'default_where_conditions' => 'none',
239
+			);
240
+		if (! $include_expired) {
241
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
242
+		}
243
+		if ($include_deleted) {
244
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
245
+		}
246
+		/** @var EE_Datetime[] $result */
247
+		$result = $this->get_all($query_params);
248
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
249
+		return $result;
250
+	}
251
+
252
+
253
+	/**
254
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
255
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
256
+	 * and then the earlier datetimes are the most important.
257
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
258
+	 *
259
+	 * @param int $EVT_ID
260
+	 * @param int $limit
261
+	 * @return EE_Datetime[]|EE_Base_Class[]
262
+	 * @throws EE_Error
263
+	 */
264
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
265
+	{
266
+		return $this->get_all(
267
+			array(
268
+				array('Event.EVT_ID' => $EVT_ID),
269
+				'limit'                    => $limit,
270
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
271
+				'default_where_conditions' => 'none',
272
+			)
273
+		);
274
+	}
275
+
276
+
277
+	/**
278
+	 * @param int     $EVT_ID
279
+	 * @param boolean $include_expired
280
+	 * @param boolean $include_deleted
281
+	 * @return EE_Datetime
282
+	 * @throws EE_Error
283
+	 */
284
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
285
+	{
286
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
287
+			$EVT_ID,
288
+			$include_expired,
289
+			$include_deleted,
290
+			1
291
+		);
292
+		if ($results) {
293
+			return array_shift($results);
294
+		}
295
+		return null;
296
+	}
297
+
298
+
299
+	/**
300
+	 * Gets the 'primary' datetime for an event.
301
+	 *
302
+	 * @param int  $EVT_ID
303
+	 * @param bool $try_to_exclude_expired
304
+	 * @param bool $try_to_exclude_deleted
305
+	 * @return \EE_Datetime
306
+	 * @throws EE_Error
307
+	 */
308
+	public function get_primary_datetime_for_event(
309
+		$EVT_ID,
310
+		$try_to_exclude_expired = true,
311
+		$try_to_exclude_deleted = true
312
+	) {
313
+		if ($try_to_exclude_expired) {
314
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
315
+			if ($non_expired) {
316
+				return $non_expired;
317
+			}
318
+		}
319
+		if ($try_to_exclude_deleted) {
320
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
321
+			if ($expired_even) {
322
+				return $expired_even;
323
+			}
324
+		}
325
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
331
+	 * only by start date
332
+	 *
333
+	 * @param int     $EVT_ID
334
+	 * @param boolean $include_expired
335
+	 * @param boolean $include_deleted
336
+	 * @param int     $limit
337
+	 * @return EE_Datetime[]
338
+	 * @throws EE_Error
339
+	 */
340
+	public function get_datetimes_for_event_ordered_by_start_time(
341
+		$EVT_ID,
342
+		$include_expired = true,
343
+		$include_deleted = true,
344
+		$limit = null
345
+	) {
346
+		// sanitize EVT_ID
347
+		$EVT_ID         = absint($EVT_ID);
348
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
349
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
350
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
351
+		if (! $include_expired) {
352
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
353
+		}
354
+		if ($include_deleted) {
355
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
356
+		}
357
+		if ($limit) {
358
+			$query_params['limit'] = $limit;
359
+		}
360
+		/** @var EE_Datetime[] $result */
361
+		$result = $this->get_all($query_params);
362
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
363
+		return $result;
364
+	}
365
+
366
+
367
+	/**
368
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
369
+	 * only by start date
370
+	 *
371
+	 * @param int     $TKT_ID
372
+	 * @param boolean $include_expired
373
+	 * @param boolean $include_deleted
374
+	 * @param int     $limit
375
+	 * @return EE_Datetime[]
376
+	 * @throws EE_Error
377
+	 */
378
+	public function get_datetimes_for_ticket_ordered_by_start_time(
379
+		$TKT_ID,
380
+		$include_expired = true,
381
+		$include_deleted = true,
382
+		$limit = null
383
+	) {
384
+		// sanitize TKT_ID
385
+		$TKT_ID         = absint($TKT_ID);
386
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
387
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
388
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
389
+		if (! $include_expired) {
390
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
391
+		}
392
+		if ($include_deleted) {
393
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
394
+		}
395
+		if ($limit) {
396
+			$query_params['limit'] = $limit;
397
+		}
398
+		/** @var EE_Datetime[] $result */
399
+		$result = $this->get_all($query_params);
400
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
401
+		return $result;
402
+	}
403
+
404
+
405
+	/**
406
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
407
+	 * datetimes.
408
+	 *
409
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
410
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
411
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
412
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
413
+	 *                                   that number
414
+	 * @return EE_Datetime[]
415
+	 * @throws EE_Error
416
+	 */
417
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
418
+		$TKT_ID,
419
+		$include_expired = true,
420
+		$include_deleted = true,
421
+		$limit = null
422
+	) {
423
+		// sanitize id.
424
+		$TKT_ID         = absint($TKT_ID);
425
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
426
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
427
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
428
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
429
+		if (! $include_expired) {
430
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
431
+		}
432
+		if ($include_deleted) {
433
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
434
+		}
435
+		if ($limit) {
436
+			$query_params['limit'] = $limit;
437
+		}
438
+		/** @var EE_Datetime[] $result */
439
+		$result = $this->get_all($query_params);
440
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
441
+		return $result;
442
+	}
443
+
444
+
445
+	/**
446
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
447
+	 * reason it doesn't exist, we consider the earliest event the most important)
448
+	 *
449
+	 * @param int $EVT_ID
450
+	 * @return EE_Datetime
451
+	 * @throws EE_Error
452
+	 */
453
+	public function get_most_important_datetime_for_event($EVT_ID)
454
+	{
455
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
456
+		if ($results) {
457
+			return array_shift($results);
458
+		}
459
+		return null;
460
+	}
461
+
462
+
463
+	/**
464
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
465
+	 * grouped by month and year.
466
+	 *
467
+	 * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
468
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
469
+	 *                                   Can be:
470
+	 *                                   - '' = no filter
471
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
472
+	 *                                   - expired = Events with all datetimes expired.
473
+	 *                                   - active = Events that are published and have at least one datetime that
474
+	 *                                   starts before now and ends after now.
475
+	 *                                   - inactive = Events that are either not published.
476
+	 * @return EE_Base_Class[]
477
+	 * @throws EE_Error
478
+	 * @throws InvalidArgumentException
479
+	 * @throws InvalidArgumentException
480
+	 */
481
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
482
+	{
483
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
484
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
485
+		switch ($evt_active_status) {
486
+			case 'upcoming':
487
+				$where_params['Event.status'] = 'publish';
488
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
489
+				if (isset($where_params['DTT_EVT_start'])) {
490
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
491
+				}
492
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
493
+				break;
494
+			case 'expired':
495
+				if (isset($where_params['Event.status'])) {
496
+					unset($where_params['Event.status']);
497
+				}
498
+				// get events to exclude
499
+				$exclude_query[0] = array_merge(
500
+					$where_params,
501
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
502
+				);
503
+				// first get all events that have datetimes where its not expired.
504
+				$event_ids = $this->_get_all_wpdb_results(
505
+					$exclude_query,
506
+					OBJECT_K,
507
+					'Datetime.EVT_ID'
508
+				);
509
+				$event_ids = array_keys($event_ids);
510
+				if (isset($where_params['DTT_EVT_end'])) {
511
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
512
+				}
513
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
514
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
515
+				break;
516
+			case 'active':
517
+				$where_params['Event.status'] = 'publish';
518
+				if (isset($where_params['DTT_EVT_start'])) {
519
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
520
+				}
521
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
522
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
523
+				}
524
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
525
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
526
+				break;
527
+			case 'inactive':
528
+				if (isset($where_params['Event.status'])) {
529
+					unset($where_params['Event.status']);
530
+				}
531
+				if (isset($where_params['OR'])) {
532
+					$where_params['AND']['OR'] = $where_params['OR'];
533
+				}
534
+				if (isset($where_params['DTT_EVT_end'])) {
535
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
536
+					unset($where_params['DTT_EVT_end']);
537
+				}
538
+				if (isset($where_params['DTT_EVT_start'])) {
539
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
540
+					unset($where_params['DTT_EVT_start']);
541
+				}
542
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
543
+				break;
544
+		}
545
+		$query_params[0]          = $where_params;
546
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
547
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
548
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
549
+			$this->get_timezone(),
550
+			'DTT_EVT_start'
551
+		);
552
+		$columns_to_select        = array(
553
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
554
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
555
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
556
+		);
557
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
558
+	}
559
+
560
+
561
+	/**
562
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
563
+	 * for the tickets for each datetime)
564
+	 *
565
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
566
+	 * @throws EE_Error
567
+	 */
568
+	public function update_sold($datetimes)
569
+	{
570
+		EE_Error::doing_it_wrong(
571
+			__FUNCTION__,
572
+			esc_html__(
573
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
574
+				'event_espresso'
575
+			),
576
+			'4.9.32.rc.005'
577
+		);
578
+		foreach ($datetimes as $datetime) {
579
+			$datetime->update_sold();
580
+		}
581
+	}
582
+
583
+
584
+	/**
585
+	 *    Gets the total number of tickets available at a particular datetime
586
+	 *    (does NOT take into account the datetime's spaces available)
587
+	 *
588
+	 * @param int   $DTT_ID
589
+	 * @param array $query_params
590
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
591
+	 *             tickets attached to datetime then FALSE is returned.
592
+	 */
593
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
594
+	{
595
+		$datetime = $this->get_one_by_ID($DTT_ID);
596
+		if ($datetime instanceof EE_Datetime) {
597
+			return $datetime->tickets_remaining($query_params);
598
+		}
599
+		return 0;
600
+	}
601
+
602
+
603
+	/**
604
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
605
+	 *
606
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
607
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
608
+	 *                                 for all valid stati.
609
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
610
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
611
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
612
+	 * @throws EE_Error
613
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
614
+	 *                                 EE_Datetime::expired
615
+	 */
616
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
617
+	{
618
+		// only accept where conditions for this query.
619
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
620
+		$status_query_args = array(
621
+			EE_Datetime::active   => array_merge(
622
+				$_where,
623
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
624
+			),
625
+			EE_Datetime::upcoming => array_merge(
626
+				$_where,
627
+				array('DTT_EVT_start' => array('>', time()))
628
+			),
629
+			EE_Datetime::expired  => array_merge(
630
+				$_where,
631
+				array('DTT_EVT_end' => array('<', time()))
632
+			),
633
+		);
634
+		if (! empty($stati_to_include)) {
635
+			foreach (array_keys($status_query_args) as $status) {
636
+				if (! in_array($status, $stati_to_include, true)) {
637
+					unset($status_query_args[ $status ]);
638
+				}
639
+			}
640
+		}
641
+		// loop through and query counts for each stati.
642
+		$status_query_results = array();
643
+		foreach ($status_query_args as $status => $status_where_conditions) {
644
+			$status_query_results[ $status ] = EEM_Datetime::count(
645
+				array($status_where_conditions),
646
+				'DTT_ID',
647
+				true
648
+			);
649
+		}
650
+		return $status_query_results;
651
+	}
652
+
653
+
654
+	/**
655
+	 * Returns the specific count for a given Datetime status matching any given query_params.
656
+	 *
657
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
658
+	 * @param array  $query_params
659
+	 * @return int
660
+	 * @throws EE_Error
661
+	 */
662
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
663
+	{
664
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
665
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
666
+	}
667 667
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -117,23 +117,23 @@  discard block
 block discarded – undo
117 117
                 ),
118 118
             ),
119 119
         );
120
-        $this->_model_relations        = array(
120
+        $this->_model_relations = array(
121 121
             'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122 122
             'Event'   => new EE_Belongs_To_Relation(),
123 123
             'Checkin' => new EE_Has_Many_Relation(),
124 124
         );
125 125
         $this->_model_chain_to_wp_user = 'Event';
126 126
         // this model is generally available for reading
127
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
127
+        $this->_cap_restriction_generators[EEM_Base::caps_read]       = new EE_Restriction_Generator_Event_Related_Public(
128 128
             'Event'
129 129
         );
130
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
130
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected(
131 131
             'Event'
132 132
         );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
133
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]       = new EE_Restriction_Generator_Event_Related_Protected(
134 134
             'Event'
135 135
         );
136
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
136
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]     = new EE_Restriction_Generator_Event_Related_Protected(
137 137
             'Event',
138 138
             EEM_Base::caps_edit
139 139
         );
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
      */
192 192
     public function get_all_event_dates($EVT_ID = 0)
193 193
     {
194
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
194
+        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
195 195
             return $this->create_new_blank_datetime();
196 196
         }
197 197
         $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
                 'order_by'                 => array('DTT_order' => 'ASC'),
238 238
                 'default_where_conditions' => 'none',
239 239
             );
240
-        if (! $include_expired) {
240
+        if ( ! $include_expired) {
241 241
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
242 242
         }
243 243
         if ($include_deleted) {
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
349 349
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
350 350
         $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
351
-        if (! $include_expired) {
351
+        if ( ! $include_expired) {
352 352
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
353 353
         }
354 354
         if ($include_deleted) {
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
         $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
387 387
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
388 388
         $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
389
-        if (! $include_expired) {
389
+        if ( ! $include_expired) {
390 390
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
391 391
         }
392 392
         if ($include_deleted) {
@@ -426,7 +426,7 @@  discard block
 block discarded – undo
426 426
         $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
427 427
         $where_params = array('Ticket.TKT_ID' => $TKT_ID);
428 428
         $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
429
-        if (! $include_expired) {
429
+        if ( ! $include_expired) {
430 430
             $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
431 431
         }
432 432
         if ($include_deleted) {
@@ -549,10 +549,10 @@  discard block
 block discarded – undo
549 549
             $this->get_timezone(),
550 550
             'DTT_EVT_start'
551 551
         );
552
-        $columns_to_select        = array(
553
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
554
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
555
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
552
+        $columns_to_select = array(
553
+            'dtt_year'      => array('YEAR('.$query_interval.')', '%s'),
554
+            'dtt_month'     => array('MONTHNAME('.$query_interval.')', '%s'),
555
+            'dtt_month_num' => array('MONTH('.$query_interval.')', '%s'),
556 556
         );
557 557
         return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
558 558
     }
@@ -631,17 +631,17 @@  discard block
 block discarded – undo
631 631
                 array('DTT_EVT_end' => array('<', time()))
632 632
             ),
633 633
         );
634
-        if (! empty($stati_to_include)) {
634
+        if ( ! empty($stati_to_include)) {
635 635
             foreach (array_keys($status_query_args) as $status) {
636
-                if (! in_array($status, $stati_to_include, true)) {
637
-                    unset($status_query_args[ $status ]);
636
+                if ( ! in_array($status, $stati_to_include, true)) {
637
+                    unset($status_query_args[$status]);
638 638
                 }
639 639
             }
640 640
         }
641 641
         // loop through and query counts for each stati.
642 642
         $status_query_results = array();
643 643
         foreach ($status_query_args as $status => $status_where_conditions) {
644
-            $status_query_results[ $status ] = EEM_Datetime::count(
644
+            $status_query_results[$status] = EEM_Datetime::count(
645 645
                 array($status_where_conditions),
646 646
                 'DTT_ID',
647 647
                 true
@@ -662,6 +662,6 @@  discard block
 block discarded – undo
662 662
     public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
663 663
     {
664 664
         $count = $this->get_datetime_counts_by_status(array($status), $query_params);
665
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
665
+        return ! empty($count[$status]) ? $count[$status] : 0;
666 666
     }
667 667
 }
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/content-espresso_events-datetimes.php 1 patch
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -1,15 +1,15 @@
 block discarded – undo
1 1
 <?php
2 2
 //echo '<br/><h6 style="color:#2EA2CC;">'. __FILE__ . ' &nbsp; <span style="font-weight:normal;color:#E76700"> Line #: ' . __LINE__ . '</span></h6>';
3 3
 
4
-if ( is_single() || ( is_archive() && espresso_display_datetimes_in_event_list() ) ) :
4
+if (is_single() || (is_archive() && espresso_display_datetimes_in_event_list())) :
5 5
 global $post;
6
-do_action( 'AHEE_event_details_before_event_date', $post );
6
+do_action('AHEE_event_details_before_event_date', $post);
7 7
 ?>
8 8
 	<div class="event-datetimes">
9
-		<?php espresso_list_of_event_dates( $post->ID );?>
9
+		<?php espresso_list_of_event_dates($post->ID); ?>
10 10
 	</div>
11 11
 	<!-- .event-datetimes -->
12 12
 <?php
13
-do_action( 'AHEE_event_details_after_event_date', $post );
13
+do_action('AHEE_event_details_after_event_date', $post);
14 14
 endif;
15 15
 ?>
16 16
\ No newline at end of file
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1247,7 +1247,7 @@
 block discarded – undo
1247 1247
     /**
1248 1248
      * Sets up the limit for the registrations query.
1249 1249
      *
1250
-     * @param $per_page
1250
+     * @param integer $per_page
1251 1251
      * @return array
1252 1252
      */
1253 1253
     protected function _get_limit($per_page)
Please login to merge, or discard this patch.
Indentation   +3813 added lines, -3813 removed lines patch added patch discarded remove patch
@@ -19,2388 +19,2388 @@  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  EEM_Base::get_all()
1168
-         */
1169
-        $query_params['group_by'] = '';
1170
-
1171
-        return $count
1172
-            ? EEM_Registration::instance()->count($query_params)
1173
-            /** @type EE_Registration[] */
1174
-            : EEM_Registration::instance()->get_all($query_params);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1180
-     * Note: this listens to values on the request for some of the query parameters.
1181
-     *
1182
-     * @param array $request
1183
-     * @param int   $per_page
1184
-     * @param bool  $count
1185
-     * @return array
1186
-     * @throws EE_Error
1187
-     */
1188
-    protected function _get_registration_query_parameters(
1189
-        $request = array(),
1190
-        $per_page = 10,
1191
-        $count = false
1192
-    ) {
1193
-
1194
-        $query_params = array(
1195
-            0                          => $this->_get_where_conditions_for_registrations_query(
1196
-                $request
1197
-            ),
1198
-            'caps'                     => EEM_Registration::caps_read_admin,
1199
-            'default_where_conditions' => 'this_model_only',
1200
-        );
1201
-        if (! $count) {
1202
-            $query_params = array_merge(
1203
-                $query_params,
1204
-                $this->_get_orderby_for_registrations_query(),
1205
-                $this->_get_limit($per_page)
1206
-            );
1207
-        }
1208
-
1209
-        return $query_params;
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1215
-     *
1216
-     * @param array $request usually the same as $this->_req_data but not necessarily
1217
-     * @return array
1218
-     */
1219
-    protected function addAttendeeIdToWhereConditions(array $request)
1220
-    {
1221
-        $where = array();
1222
-        if (! empty($request['ATT_ID'])) {
1223
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1224
-        }
1225
-        return $where;
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1231
-     *
1232
-     * @param array $request usually the same as $this->_req_data but not necessarily
1233
-     * @return array
1234
-     */
1235
-    protected function _add_event_id_to_where_conditions(array $request)
1236
-    {
1237
-        $where = array();
1238
-        if (! empty($request['event_id'])) {
1239
-            $where['EVT_ID'] = absint($request['event_id']);
1240
-        }
1241
-        return $where;
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1247
-     *
1248
-     * @param array $request usually the same as $this->_req_data but not necessarily
1249
-     * @return array
1250
-     */
1251
-    protected function _add_category_id_to_where_conditions(array $request)
1252
-    {
1253
-        $where = array();
1254
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1255
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1256
-        }
1257
-        return $where;
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1263
-     *
1264
-     * @param array $request usually the same as $this->_req_data but not necessarily
1265
-     * @return array
1266
-     */
1267
-    protected function _add_datetime_id_to_where_conditions(array $request)
1268
-    {
1269
-        $where = array();
1270
-        if (! empty($request['datetime_id'])) {
1271
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1272
-        }
1273
-        if (! empty($request['DTT_ID'])) {
1274
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1275
-        }
1276
-        return $where;
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Adds the correct registration status to the where conditions for the registrations query.
1282
-     *
1283
-     * @param array $request usually the same as $this->_req_data but not necessarily
1284
-     * @return array
1285
-     */
1286
-    protected function _add_registration_status_to_where_conditions(array $request)
1287
-    {
1288
-        $where = array();
1289
-        $view = EEH_Array::is_set($request, 'status', '');
1290
-        $registration_status = ! empty($request['_reg_status'])
1291
-            ? sanitize_text_field($request['_reg_status'])
1292
-            : '';
1293
-
1294
-        /*
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  EEM_Base::get_all()
1168
+		 */
1169
+		$query_params['group_by'] = '';
1170
+
1171
+		return $count
1172
+			? EEM_Registration::instance()->count($query_params)
1173
+			/** @type EE_Registration[] */
1174
+			: EEM_Registration::instance()->get_all($query_params);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1180
+	 * Note: this listens to values on the request for some of the query parameters.
1181
+	 *
1182
+	 * @param array $request
1183
+	 * @param int   $per_page
1184
+	 * @param bool  $count
1185
+	 * @return array
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	protected function _get_registration_query_parameters(
1189
+		$request = array(),
1190
+		$per_page = 10,
1191
+		$count = false
1192
+	) {
1193
+
1194
+		$query_params = array(
1195
+			0                          => $this->_get_where_conditions_for_registrations_query(
1196
+				$request
1197
+			),
1198
+			'caps'                     => EEM_Registration::caps_read_admin,
1199
+			'default_where_conditions' => 'this_model_only',
1200
+		);
1201
+		if (! $count) {
1202
+			$query_params = array_merge(
1203
+				$query_params,
1204
+				$this->_get_orderby_for_registrations_query(),
1205
+				$this->_get_limit($per_page)
1206
+			);
1207
+		}
1208
+
1209
+		return $query_params;
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1215
+	 *
1216
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1217
+	 * @return array
1218
+	 */
1219
+	protected function addAttendeeIdToWhereConditions(array $request)
1220
+	{
1221
+		$where = array();
1222
+		if (! empty($request['ATT_ID'])) {
1223
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1224
+		}
1225
+		return $where;
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1231
+	 *
1232
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1233
+	 * @return array
1234
+	 */
1235
+	protected function _add_event_id_to_where_conditions(array $request)
1236
+	{
1237
+		$where = array();
1238
+		if (! empty($request['event_id'])) {
1239
+			$where['EVT_ID'] = absint($request['event_id']);
1240
+		}
1241
+		return $where;
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1247
+	 *
1248
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1249
+	 * @return array
1250
+	 */
1251
+	protected function _add_category_id_to_where_conditions(array $request)
1252
+	{
1253
+		$where = array();
1254
+		if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1255
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1256
+		}
1257
+		return $where;
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1263
+	 *
1264
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1265
+	 * @return array
1266
+	 */
1267
+	protected function _add_datetime_id_to_where_conditions(array $request)
1268
+	{
1269
+		$where = array();
1270
+		if (! empty($request['datetime_id'])) {
1271
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1272
+		}
1273
+		if (! empty($request['DTT_ID'])) {
1274
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1275
+		}
1276
+		return $where;
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Adds the correct registration status to the where conditions for the registrations query.
1282
+	 *
1283
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1284
+	 * @return array
1285
+	 */
1286
+	protected function _add_registration_status_to_where_conditions(array $request)
1287
+	{
1288
+		$where = array();
1289
+		$view = EEH_Array::is_set($request, 'status', '');
1290
+		$registration_status = ! empty($request['_reg_status'])
1291
+			? sanitize_text_field($request['_reg_status'])
1292
+			: '';
1293
+
1294
+		/*
1295 1295
          * If filtering by registration status, then we show registrations matching that status.
1296 1296
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1297 1297
          * UNLESS viewing trashed registrations.
1298 1298
          */
1299
-        if (! empty($registration_status)) {
1300
-            $where['STS_ID'] = $registration_status;
1301
-        } else {
1302
-            // make sure we exclude incomplete registrations, but only if not trashed.
1303
-            if ($view === 'trash') {
1304
-                $where['REG_deleted'] = true;
1305
-            } elseif ($view === 'incomplete') {
1306
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1307
-            } else {
1308
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1309
-            }
1310
-        }
1311
-        return $where;
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Adds any provided date restraints to the where conditions for the registrations query.
1317
-     *
1318
-     * @param array $request usually the same as $this->_req_data but not necessarily
1319
-     * @return array
1320
-     * @throws EE_Error
1321
-     * @throws InvalidArgumentException
1322
-     * @throws InvalidDataTypeException
1323
-     * @throws InvalidInterfaceException
1324
-     */
1325
-    protected function _add_date_to_where_conditions(array $request)
1326
-    {
1327
-        $where = array();
1328
-        $view = EEH_Array::is_set($request, 'status', '');
1329
-        $month_range = ! empty($request['month_range'])
1330
-            ? sanitize_text_field($request['month_range'])
1331
-            : '';
1332
-        $retrieve_for_today = $view === 'today';
1333
-        $retrieve_for_this_month = $view === 'month';
1334
-
1335
-        if ($retrieve_for_today) {
1336
-            $now = date('Y-m-d', current_time('timestamp'));
1337
-            $where['REG_date'] = array(
1338
-                'BETWEEN',
1339
-                array(
1340
-                    EEM_Registration::instance()->convert_datetime_for_query(
1341
-                        'REG_date',
1342
-                        $now . ' 00:00:00',
1343
-                        'Y-m-d H:i:s'
1344
-                    ),
1345
-                    EEM_Registration::instance()->convert_datetime_for_query(
1346
-                        'REG_date',
1347
-                        $now . ' 23:59:59',
1348
-                        'Y-m-d H:i:s'
1349
-                    ),
1350
-                ),
1351
-            );
1352
-        } elseif ($retrieve_for_this_month) {
1353
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1354
-            $days_this_month = date('t', current_time('timestamp'));
1355
-            $where['REG_date'] = array(
1356
-                'BETWEEN',
1357
-                array(
1358
-                    EEM_Registration::instance()->convert_datetime_for_query(
1359
-                        'REG_date',
1360
-                        $current_year_and_month . '-01 00:00:00',
1361
-                        'Y-m-d H:i:s'
1362
-                    ),
1363
-                    EEM_Registration::instance()->convert_datetime_for_query(
1364
-                        'REG_date',
1365
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1366
-                        'Y-m-d H:i:s'
1367
-                    ),
1368
-                ),
1369
-            );
1370
-        } elseif ($month_range) {
1371
-            $pieces = explode(' ', $month_range, 3);
1372
-            $month_requested = ! empty($pieces[0])
1373
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1374
-                : '';
1375
-            $year_requested = ! empty($pieces[1])
1376
-                ? $pieces[1]
1377
-                : '';
1378
-            // if there is not a month or year then we can't go further
1379
-            if ($month_requested && $year_requested) {
1380
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1381
-                $where['REG_date'] = array(
1382
-                    'BETWEEN',
1383
-                    array(
1384
-                        EEM_Registration::instance()->convert_datetime_for_query(
1385
-                            'REG_date',
1386
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1387
-                            'Y-m-d H:i:s'
1388
-                        ),
1389
-                        EEM_Registration::instance()->convert_datetime_for_query(
1390
-                            'REG_date',
1391
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1392
-                            'Y-m-d H:i:s'
1393
-                        ),
1394
-                    ),
1395
-                );
1396
-            }
1397
-        }
1398
-        return $where;
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * Adds any provided search restraints to the where conditions for the registrations query
1404
-     *
1405
-     * @param array $request usually the same as $this->_req_data but not necessarily
1406
-     * @return array
1407
-     */
1408
-    protected function _add_search_to_where_conditions(array $request)
1409
-    {
1410
-        $where = array();
1411
-        if (! empty($request['s'])) {
1412
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1413
-            $where['OR*search_conditions'] = array(
1414
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1415
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1416
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1417
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1418
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1419
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1420
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1421
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1422
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1423
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1424
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1425
-                'REG_final_price'                         => array('LIKE', $search_string),
1426
-                'REG_code'                                => array('LIKE', $search_string),
1427
-                'REG_count'                               => array('LIKE', $search_string),
1428
-                'REG_group_size'                          => array('LIKE', $search_string),
1429
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1430
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1431
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1432
-            );
1433
-        }
1434
-        return $where;
1435
-    }
1436
-
1437
-
1438
-    /**
1439
-     * Sets up the where conditions for the registrations query.
1440
-     *
1441
-     * @param array $request
1442
-     * @return array
1443
-     * @throws EE_Error
1444
-     */
1445
-    protected function _get_where_conditions_for_registrations_query($request)
1446
-    {
1447
-        return apply_filters(
1448
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1449
-            array_merge(
1450
-                $this->addAttendeeIdToWhereConditions($request),
1451
-                $this->_add_event_id_to_where_conditions($request),
1452
-                $this->_add_category_id_to_where_conditions($request),
1453
-                $this->_add_datetime_id_to_where_conditions($request),
1454
-                $this->_add_registration_status_to_where_conditions($request),
1455
-                $this->_add_date_to_where_conditions($request),
1456
-                $this->_add_search_to_where_conditions($request)
1457
-            ),
1458
-            $request
1459
-        );
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Sets up the orderby for the registrations query.
1465
-     *
1466
-     * @return array
1467
-     */
1468
-    protected function _get_orderby_for_registrations_query()
1469
-    {
1470
-        $orderby_field = ! empty($this->_req_data['orderby'])
1471
-            ? sanitize_text_field($this->_req_data['orderby'])
1472
-            : '';
1473
-        switch ($orderby_field) {
1474
-            case '_REG_ID':
1475
-                $orderby = array('REG_ID');
1476
-                break;
1477
-            case '_Reg_status':
1478
-                $orderby = array('STS_ID');
1479
-                break;
1480
-            case 'ATT_fname':
1481
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1482
-                break;
1483
-            case 'ATT_lname':
1484
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1485
-                break;
1486
-            case 'event_name':
1487
-                $orderby = array('Event.EVT_name');
1488
-                break;
1489
-            case 'DTT_EVT_start':
1490
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1491
-                break;
1492
-            default: // 'REG_date'
1493
-                $orderby = array('REG_date');
1494
-        }
1495
-
1496
-        // order
1497
-        $order = ! empty($this->_req_data['order'])
1498
-            ? sanitize_text_field($this->_req_data['order'])
1499
-            : 'DESC';
1500
-        $orderby = array_combine(
1501
-            $orderby,
1502
-            array_fill(0, count($orderby), $order)
1503
-        );
1504
-        // because there are many registrations with the same date, define
1505
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
1506
-        if (empty($orderby['REG_ID'])) {
1507
-            $orderby['REG_ID'] = $order;
1508
-        }
1509
-        return array('order_by' => $orderby);
1510
-    }
1511
-
1512
-
1513
-    /**
1514
-     * Sets up the limit for the registrations query.
1515
-     *
1516
-     * @param $per_page
1517
-     * @return array
1518
-     */
1519
-    protected function _get_limit($per_page)
1520
-    {
1521
-        $current_page = ! empty($this->_req_data['paged'])
1522
-            ? absint($this->_req_data['paged'])
1523
-            : 1;
1524
-        $per_page = ! empty($this->_req_data['perpage'])
1525
-            ? $this->_req_data['perpage']
1526
-            : $per_page;
1527
-
1528
-        // -1 means return all results so get out if that's set.
1529
-        if ((int) $per_page === -1) {
1530
-            return array();
1531
-        }
1532
-        $per_page = absint($per_page);
1533
-        $offset = ($current_page - 1) * $per_page;
1534
-        return array('limit' => array($offset, $per_page));
1535
-    }
1536
-
1537
-
1538
-    public function get_registration_status_array()
1539
-    {
1540
-        return self::$_reg_status;
1541
-    }
1542
-
1543
-
1544
-
1545
-
1546
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1547
-    /**
1548
-     *        generates HTML for the View Registration Details Admin page
1549
-     *
1550
-     * @access protected
1551
-     * @return void
1552
-     * @throws DomainException
1553
-     * @throws EE_Error
1554
-     * @throws InvalidArgumentException
1555
-     * @throws InvalidDataTypeException
1556
-     * @throws InvalidInterfaceException
1557
-     * @throws EntityNotFoundException
1558
-     */
1559
-    protected function _registration_details()
1560
-    {
1561
-        $this->_template_args = array();
1562
-        $this->_set_registration_object();
1563
-        if (is_object($this->_registration)) {
1564
-            $transaction = $this->_registration->transaction()
1565
-                ? $this->_registration->transaction()
1566
-                : EE_Transaction::new_instance();
1567
-            $this->_session = $transaction->session_data();
1568
-            $event_id = $this->_registration->event_ID();
1569
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1570
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1571
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1572
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1573
-            $this->_template_args['grand_total'] = $transaction->total();
1574
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1575
-            // link back to overview
1576
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1577
-            $this->_template_args['registration'] = $this->_registration;
1578
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1579
-                array(
1580
-                    'action'   => 'default',
1581
-                    'event_id' => $event_id,
1582
-                ),
1583
-                REG_ADMIN_URL
1584
-            );
1585
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1586
-                array(
1587
-                    'action' => 'default',
1588
-                    'EVT_ID' => $event_id,
1589
-                    'page'   => 'espresso_transactions',
1590
-                ),
1591
-                admin_url('admin.php')
1592
-            );
1593
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1594
-                array(
1595
-                    'page'   => 'espresso_events',
1596
-                    'action' => 'edit',
1597
-                    'post'   => $event_id,
1598
-                ),
1599
-                admin_url('admin.php')
1600
-            );
1601
-            // next and previous links
1602
-            $next_reg = $this->_registration->next(
1603
-                null,
1604
-                array(),
1605
-                'REG_ID'
1606
-            );
1607
-            $this->_template_args['next_registration'] = $next_reg
1608
-                ? $this->_next_link(
1609
-                    EE_Admin_Page::add_query_args_and_nonce(
1610
-                        array(
1611
-                            'action'  => 'view_registration',
1612
-                            '_REG_ID' => $next_reg['REG_ID'],
1613
-                        ),
1614
-                        REG_ADMIN_URL
1615
-                    ),
1616
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1617
-                )
1618
-                : '';
1619
-            $previous_reg = $this->_registration->previous(
1620
-                null,
1621
-                array(),
1622
-                'REG_ID'
1623
-            );
1624
-            $this->_template_args['previous_registration'] = $previous_reg
1625
-                ? $this->_previous_link(
1626
-                    EE_Admin_Page::add_query_args_and_nonce(
1627
-                        array(
1628
-                            'action'  => 'view_registration',
1629
-                            '_REG_ID' => $previous_reg['REG_ID'],
1630
-                        ),
1631
-                        REG_ADMIN_URL
1632
-                    ),
1633
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1634
-                )
1635
-                : '';
1636
-            // grab header
1637
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1638
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1639
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1640
-                $template_path,
1641
-                $this->_template_args,
1642
-                true
1643
-            );
1644
-        } else {
1645
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1646
-        }
1647
-        // the details template wrapper
1648
-        $this->display_admin_page_with_sidebar();
1649
-    }
1650
-
1651
-
1652
-    protected function _registration_details_metaboxes()
1653
-    {
1654
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1655
-        $this->_set_registration_object();
1656
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1657
-        add_meta_box(
1658
-            'edit-reg-status-mbox',
1659
-            esc_html__('Registration Status', 'event_espresso'),
1660
-            array($this, 'set_reg_status_buttons_metabox'),
1661
-            $this->wp_page_slug,
1662
-            'normal',
1663
-            'high'
1664
-        );
1665
-        add_meta_box(
1666
-            'edit-reg-details-mbox',
1667
-            esc_html__('Registration Details', 'event_espresso'),
1668
-            array($this, '_reg_details_meta_box'),
1669
-            $this->wp_page_slug,
1670
-            'normal',
1671
-            'high'
1672
-        );
1673
-        if ($attendee instanceof EE_Attendee
1674
-            && EE_Registry::instance()->CAP->current_user_can(
1675
-                'ee_edit_registration',
1676
-                'edit-reg-questions-mbox',
1677
-                $this->_registration->ID()
1678
-            )
1679
-        ) {
1680
-            add_meta_box(
1681
-                'edit-reg-questions-mbox',
1682
-                esc_html__('Registration Form Answers', 'event_espresso'),
1683
-                array($this, '_reg_questions_meta_box'),
1684
-                $this->wp_page_slug,
1685
-                'normal',
1686
-                'high'
1687
-            );
1688
-        }
1689
-        add_meta_box(
1690
-            'edit-reg-registrant-mbox',
1691
-            esc_html__('Contact Details', 'event_espresso'),
1692
-            array($this, '_reg_registrant_side_meta_box'),
1693
-            $this->wp_page_slug,
1694
-            'side',
1695
-            'high'
1696
-        );
1697
-        if ($this->_registration->group_size() > 1) {
1698
-            add_meta_box(
1699
-                'edit-reg-attendees-mbox',
1700
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1701
-                array($this, '_reg_attendees_meta_box'),
1702
-                $this->wp_page_slug,
1703
-                'normal',
1704
-                'high'
1705
-            );
1706
-        }
1707
-    }
1708
-
1709
-
1710
-    /**
1711
-     * set_reg_status_buttons_metabox
1712
-     *
1713
-     * @access protected
1714
-     * @return string
1715
-     * @throws \EE_Error
1716
-     */
1717
-    public function set_reg_status_buttons_metabox()
1718
-    {
1719
-        $this->_set_registration_object();
1720
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1721
-        echo $change_reg_status_form->form_open(
1722
-            self::add_query_args_and_nonce(
1723
-                array(
1724
-                    'action' => 'change_reg_status',
1725
-                ),
1726
-                REG_ADMIN_URL
1727
-            )
1728
-        );
1729
-        echo $change_reg_status_form->get_html();
1730
-        echo $change_reg_status_form->form_close();
1731
-    }
1732
-
1733
-
1734
-    /**
1735
-     * @return EE_Form_Section_Proper
1736
-     * @throws EE_Error
1737
-     * @throws InvalidArgumentException
1738
-     * @throws InvalidDataTypeException
1739
-     * @throws InvalidInterfaceException
1740
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1741
-     */
1742
-    protected function _generate_reg_status_change_form()
1743
-    {
1744
-        return new EE_Form_Section_Proper(
1745
-            array(
1746
-                'name'            => 'reg_status_change_form',
1747
-                'html_id'         => 'reg-status-change-form',
1748
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1749
-                'subsections'     => array(
1750
-                    'return'             => new EE_Hidden_Input(
1751
-                        array(
1752
-                            'name'    => 'return',
1753
-                            'default' => 'view_registration',
1754
-                        )
1755
-                    ),
1756
-                    'REG_ID'             => new EE_Hidden_Input(
1757
-                        array(
1758
-                            'name'    => 'REG_ID',
1759
-                            'default' => $this->_registration->ID(),
1760
-                        )
1761
-                    ),
1762
-                    'current_status'     => new EE_Form_Section_HTML(
1763
-                        EEH_HTML::tr(
1764
-                            EEH_HTML::th(
1765
-                                EEH_HTML::label(
1766
-                                    EEH_HTML::strong(
1767
-                                        esc_html__('Current Registration Status', 'event_espresso')
1768
-                                    )
1769
-                                )
1770
-                            )
1771
-                            . EEH_HTML::td(
1772
-                                EEH_HTML::strong(
1773
-                                    $this->_registration->pretty_status(),
1774
-                                    '',
1775
-                                    'status-' . $this->_registration->status_ID(),
1776
-                                    'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1777
-                                )
1778
-                            )
1779
-                        )
1780
-                    ),
1781
-                    'reg_status'         => new EE_Select_Input(
1782
-                        $this->_get_reg_statuses(),
1783
-                        array(
1784
-                            'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1785
-                            'default'         => $this->_registration->status_ID(),
1786
-                        )
1787
-                    ),
1788
-                    'send_notifications' => new EE_Yes_No_Input(
1789
-                        array(
1790
-                            'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1791
-                            'default'         => false,
1792
-                            'html_help_text'  => esc_html__(
1793
-                                'If set to "Yes", then the related messages will be sent to the registrant.',
1794
-                                'event_espresso'
1795
-                            ),
1796
-                        )
1797
-                    ),
1798
-                    'submit'             => new EE_Submit_Input(
1799
-                        array(
1800
-                            'html_class'      => 'button-primary',
1801
-                            'html_label_text' => '&nbsp;',
1802
-                            'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1803
-                        )
1804
-                    ),
1805
-                ),
1806
-            )
1807
-        );
1808
-    }
1809
-
1810
-
1811
-    /**
1812
-     * Returns an array of all the buttons for the various statuses and switch status actions
1813
-     *
1814
-     * @return array
1815
-     * @throws EE_Error
1816
-     * @throws InvalidArgumentException
1817
-     * @throws InvalidDataTypeException
1818
-     * @throws InvalidInterfaceException
1819
-     * @throws EntityNotFoundException
1820
-     */
1821
-    protected function _get_reg_statuses()
1822
-    {
1823
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1824
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1825
-        // get current reg status
1826
-        $current_status = $this->_registration->status_ID();
1827
-        // is registration for free event? This will determine whether to display the pending payment option
1828
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1829
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1830
-        ) {
1831
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1832
-        }
1833
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1834
-    }
1835
-
1836
-
1837
-    /**
1838
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1839
-     *
1840
-     * @param bool $status REG status given for changing registrations to.
1841
-     * @param bool $notify Whether to send messages notifications or not.
1842
-     * @return array (array with reg_id(s) updated and whether update was successful.
1843
-     * @throws EE_Error
1844
-     * @throws InvalidArgumentException
1845
-     * @throws InvalidDataTypeException
1846
-     * @throws InvalidInterfaceException
1847
-     * @throws ReflectionException
1848
-     * @throws RuntimeException
1849
-     * @throws EntityNotFoundException
1850
-     */
1851
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1852
-    {
1853
-        if (isset($this->_req_data['reg_status_change_form'])) {
1854
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1855
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1856
-                : array();
1857
-        } else {
1858
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1859
-                ? (array) $this->_req_data['_REG_ID']
1860
-                : array();
1861
-        }
1862
-        // sanitize $REG_IDs
1863
-        $REG_IDs = array_map('absint', $REG_IDs);
1864
-        // and remove empty entries
1865
-        $REG_IDs = array_filter($REG_IDs);
1866
-
1867
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1868
-
1869
-        /**
1870
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1871
-         * Currently this value is used downstream by the _process_resend_registration method.
1872
-         *
1873
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1874
-         * @param bool                     $status           The status registrations were changed to.
1875
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1876
-         * @param Registrations_Admin_Page $admin_page_object
1877
-         */
1878
-        $this->_req_data['_REG_ID'] = apply_filters(
1879
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1880
-            $result['REG_ID'],
1881
-            $status,
1882
-            $result['success'],
1883
-            $this
1884
-        );
1885
-
1886
-        // notify?
1887
-        if ($notify
1888
-            && $result['success']
1889
-            && ! empty($this->_req_data['_REG_ID'])
1890
-            && EE_Registry::instance()->CAP->current_user_can(
1891
-                'ee_send_message',
1892
-                'espresso_registrations_resend_registration'
1893
-            )
1894
-        ) {
1895
-            $this->_process_resend_registration();
1896
-        }
1897
-        return $result;
1898
-    }
1899
-
1900
-
1901
-    /**
1902
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1903
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1904
-     *
1905
-     * @param array  $REG_IDs
1906
-     * @param string $status
1907
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1908
-     *                        slug sent with setting the registration status.
1909
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1910
-     * @throws EE_Error
1911
-     * @throws InvalidArgumentException
1912
-     * @throws InvalidDataTypeException
1913
-     * @throws InvalidInterfaceException
1914
-     * @throws ReflectionException
1915
-     * @throws RuntimeException
1916
-     * @throws EntityNotFoundException
1917
-     */
1918
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1919
-    {
1920
-        $success = false;
1921
-        // typecast $REG_IDs
1922
-        $REG_IDs = (array) $REG_IDs;
1923
-        if (! empty($REG_IDs)) {
1924
-            $success = true;
1925
-            // set default status if none is passed
1926
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1927
-            $status_context = $notify
1928
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1929
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1930
-            // loop through REG_ID's and change status
1931
-            foreach ($REG_IDs as $REG_ID) {
1932
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1933
-                if ($registration instanceof EE_Registration) {
1934
-                    $registration->set_status(
1935
-                        $status,
1936
-                        false,
1937
-                        new Context(
1938
-                            $status_context,
1939
-                            esc_html__(
1940
-                                'Manually triggered status change on a Registration Admin Page route.',
1941
-                                'event_espresso'
1942
-                            )
1943
-                        )
1944
-                    );
1945
-                    $result = $registration->save();
1946
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1947
-                    $success = $result !== false ? $success : false;
1948
-                }
1949
-            }
1950
-        }
1951
-
1952
-        // return $success and processed registrations
1953
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1954
-    }
1955
-
1956
-
1957
-    /**
1958
-     * Common logic for setting up success message and redirecting to appropriate route
1959
-     *
1960
-     * @param  string $STS_ID status id for the registration changed to
1961
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1962
-     * @return void
1963
-     * @throws EE_Error
1964
-     */
1965
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1966
-    {
1967
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1968
-            : array('success' => false);
1969
-        $success = isset($result['success']) && $result['success'];
1970
-        // setup success message
1971
-        if ($success) {
1972
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1973
-                $msg = sprintf(
1974
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1975
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1976
-                );
1977
-            } else {
1978
-                $msg = sprintf(
1979
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1980
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1981
-                );
1982
-            }
1983
-            EE_Error::add_success($msg);
1984
-        } else {
1985
-            EE_Error::add_error(
1986
-                esc_html__(
1987
-                    'Something went wrong, and the status was not changed',
1988
-                    'event_espresso'
1989
-                ),
1990
-                __FILE__,
1991
-                __LINE__,
1992
-                __FUNCTION__
1993
-            );
1994
-        }
1995
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1996
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1997
-        } else {
1998
-            $route = array('action' => 'default');
1999
-        }
2000
-        // unset nonces
2001
-        foreach ($this->_req_data as $ref => $value) {
2002
-            if (strpos($ref, 'nonce') !== false) {
2003
-                unset($this->_req_data[ $ref ]);
2004
-                continue;
2005
-            }
2006
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
2007
-            $this->_req_data[ $ref ] = $value;
2008
-        }
2009
-        // merge request vars so that the reloaded list table contains any existing filter query params
2010
-        $route = array_merge($this->_req_data, $route);
2011
-        $this->_redirect_after_action($success, '', '', $route, true);
2012
-    }
2013
-
2014
-
2015
-    /**
2016
-     * incoming reg status change from reg details page.
2017
-     *
2018
-     * @return void
2019
-     */
2020
-    protected function _change_reg_status()
2021
-    {
2022
-        $this->_req_data['return'] = 'view_registration';
2023
-        // set notify based on whether the send notifications toggle is set or not
2024
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2025
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2026
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2027
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2028
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2029
-            case EEM_Registration::status_id_approved:
2030
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2031
-                $this->approve_registration($notify);
2032
-                break;
2033
-            case EEM_Registration::status_id_pending_payment:
2034
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2035
-                $this->pending_registration($notify);
2036
-                break;
2037
-            case EEM_Registration::status_id_not_approved:
2038
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2039
-                $this->not_approve_registration($notify);
2040
-                break;
2041
-            case EEM_Registration::status_id_declined:
2042
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2043
-                $this->decline_registration($notify);
2044
-                break;
2045
-            case EEM_Registration::status_id_cancelled:
2046
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2047
-                $this->cancel_registration($notify);
2048
-                break;
2049
-            case EEM_Registration::status_id_wait_list:
2050
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2051
-                $this->wait_list_registration($notify);
2052
-                break;
2053
-            case EEM_Registration::status_id_incomplete:
2054
-            default:
2055
-                $result['success'] = false;
2056
-                unset($this->_req_data['return']);
2057
-                $this->_reg_status_change_return('', false);
2058
-                break;
2059
-        }
2060
-    }
2061
-
2062
-
2063
-    /**
2064
-     * Callback for bulk action routes.
2065
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2066
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2067
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2068
-     * when an action is happening on just a single registration).
2069
-     *
2070
-     * @param      $action
2071
-     * @param bool $notify
2072
-     */
2073
-    protected function bulk_action_on_registrations($action, $notify = false)
2074
-    {
2075
-        do_action(
2076
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2077
-            $this,
2078
-            $action,
2079
-            $notify
2080
-        );
2081
-        $method = $action . '_registration';
2082
-        if (method_exists($this, $method)) {
2083
-            $this->$method($notify);
2084
-        }
2085
-    }
2086
-
2087
-
2088
-    /**
2089
-     * approve_registration
2090
-     *
2091
-     * @access protected
2092
-     * @param bool $notify whether or not to notify the registrant about their approval.
2093
-     * @return void
2094
-     */
2095
-    protected function approve_registration($notify = false)
2096
-    {
2097
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2098
-    }
2099
-
2100
-
2101
-    /**
2102
-     *        decline_registration
2103
-     *
2104
-     * @access protected
2105
-     * @param bool $notify whether or not to notify the registrant about their status change.
2106
-     * @return void
2107
-     */
2108
-    protected function decline_registration($notify = false)
2109
-    {
2110
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2111
-    }
2112
-
2113
-
2114
-    /**
2115
-     *        cancel_registration
2116
-     *
2117
-     * @access protected
2118
-     * @param bool $notify whether or not to notify the registrant about their status change.
2119
-     * @return void
2120
-     */
2121
-    protected function cancel_registration($notify = false)
2122
-    {
2123
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2124
-    }
2125
-
2126
-
2127
-    /**
2128
-     *        not_approve_registration
2129
-     *
2130
-     * @access protected
2131
-     * @param bool $notify whether or not to notify the registrant about their status change.
2132
-     * @return void
2133
-     */
2134
-    protected function not_approve_registration($notify = false)
2135
-    {
2136
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2137
-    }
2138
-
2139
-
2140
-    /**
2141
-     *        decline_registration
2142
-     *
2143
-     * @access protected
2144
-     * @param bool $notify whether or not to notify the registrant about their status change.
2145
-     * @return void
2146
-     */
2147
-    protected function pending_registration($notify = false)
2148
-    {
2149
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2150
-    }
2151
-
2152
-
2153
-    /**
2154
-     * waitlist_registration
2155
-     *
2156
-     * @access protected
2157
-     * @param bool $notify whether or not to notify the registrant about their status change.
2158
-     * @return void
2159
-     */
2160
-    protected function wait_list_registration($notify = false)
2161
-    {
2162
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2163
-    }
2164
-
2165
-
2166
-    /**
2167
-     *        generates HTML for the Registration main meta box
2168
-     *
2169
-     * @access public
2170
-     * @return void
2171
-     * @throws DomainException
2172
-     * @throws EE_Error
2173
-     * @throws InvalidArgumentException
2174
-     * @throws InvalidDataTypeException
2175
-     * @throws InvalidInterfaceException
2176
-     * @throws ReflectionException
2177
-     * @throws EntityNotFoundException
2178
-     */
2179
-    public function _reg_details_meta_box()
2180
-    {
2181
-        EEH_Autoloader::register_line_item_display_autoloaders();
2182
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2183
-        EE_Registry::instance()->load_helper('Line_Item');
2184
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2185
-            : EE_Transaction::new_instance();
2186
-        $this->_session = $transaction->session_data();
2187
-        $filters = new EE_Line_Item_Filter_Collection();
2188
-        // $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2189
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2190
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2191
-            $filters,
2192
-            $transaction->total_line_item()
2193
-        );
2194
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2195
-        $line_item_display = new EE_Line_Item_Display(
2196
-            'reg_admin_table',
2197
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2198
-        );
2199
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2200
-            $filtered_line_item_tree,
2201
-            array('EE_Registration' => $this->_registration)
2202
-        );
2203
-        $attendee = $this->_registration->attendee();
2204
-        if (EE_Registry::instance()->CAP->current_user_can(
2205
-            'ee_read_transaction',
2206
-            'espresso_transactions_view_transaction'
2207
-        )) {
2208
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2209
-                EE_Admin_Page::add_query_args_and_nonce(
2210
-                    array(
2211
-                        'action' => 'view_transaction',
2212
-                        'TXN_ID' => $transaction->ID(),
2213
-                    ),
2214
-                    TXN_ADMIN_URL
2215
-                ),
2216
-                esc_html__(' View Transaction', 'event_espresso'),
2217
-                'button secondary-button right',
2218
-                'dashicons dashicons-cart'
2219
-            );
2220
-        } else {
2221
-            $this->_template_args['view_transaction_button'] = '';
2222
-        }
2223
-        if ($attendee instanceof EE_Attendee
2224
-            && EE_Registry::instance()->CAP->current_user_can(
2225
-                'ee_send_message',
2226
-                'espresso_registrations_resend_registration'
2227
-            )
2228
-        ) {
2229
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2230
-                EE_Admin_Page::add_query_args_and_nonce(
2231
-                    array(
2232
-                        'action'      => 'resend_registration',
2233
-                        '_REG_ID'     => $this->_registration->ID(),
2234
-                        'redirect_to' => 'view_registration',
2235
-                    ),
2236
-                    REG_ADMIN_URL
2237
-                ),
2238
-                esc_html__(' Resend Registration', 'event_espresso'),
2239
-                'button secondary-button right',
2240
-                'dashicons dashicons-email-alt'
2241
-            );
2242
-        } else {
2243
-            $this->_template_args['resend_registration_button'] = '';
2244
-        }
2245
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2246
-        $payment = $transaction->get_first_related('Payment');
2247
-        $payment = ! $payment instanceof EE_Payment
2248
-            ? EE_Payment::new_instance()
2249
-            : $payment;
2250
-        $payment_method = $payment->get_first_related('Payment_Method');
2251
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2252
-            ? EE_Payment_Method::new_instance()
2253
-            : $payment_method;
2254
-        $reg_details = array(
2255
-            'payment_method'       => $payment_method->name(),
2256
-            'response_msg'         => $payment->gateway_response(),
2257
-            'registration_id'      => $this->_registration->get('REG_code'),
2258
-            'registration_session' => $this->_registration->session_ID(),
2259
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2260
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2261
-        );
2262
-        if (isset($reg_details['registration_id'])) {
2263
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2264
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2265
-                'Registration ID',
2266
-                'event_espresso'
2267
-            );
2268
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2269
-        }
2270
-        if (isset($reg_details['payment_method'])) {
2271
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2272
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2273
-                'Most Recent Payment Method',
2274
-                'event_espresso'
2275
-            );
2276
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2277
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2278
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2279
-                'Payment method response',
2280
-                'event_espresso'
2281
-            );
2282
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2283
-        }
2284
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2285
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2286
-            'Registration Session',
2287
-            'event_espresso'
2288
-        );
2289
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2290
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2291
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2292
-            'Registration placed from IP',
2293
-            'event_espresso'
2294
-        );
2295
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2296
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2297
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2298
-            'Registrant User Agent',
2299
-            'event_espresso'
2300
-        );
2301
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2302
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2303
-            array(
2304
-                'action'   => 'default',
2305
-                'event_id' => $this->_registration->event_ID(),
2306
-            ),
2307
-            REG_ADMIN_URL
2308
-        );
2309
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2310
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2311
-        $template_path =
2312
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2313
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2314
-    }
2315
-
2316
-
2317
-    /**
2318
-     * generates HTML for the Registration Questions meta box.
2319
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2320
-     * otherwise uses new forms system
2321
-     *
2322
-     * @access public
2323
-     * @return void
2324
-     * @throws DomainException
2325
-     * @throws EE_Error
2326
-     */
2327
-    public function _reg_questions_meta_box()
2328
-    {
2329
-        // allow someone to override this method entirely
2330
-        if (apply_filters(
2331
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2332
-            true,
2333
-            $this,
2334
-            $this->_registration
2335
-        )) {
2336
-            $form = $this->_get_reg_custom_questions_form(
2337
-                $this->_registration->ID()
2338
-            );
2339
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2340
-                ? $form->get_html_and_js()
2341
-                : '';
2342
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2343
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2344
-            $template_path =
2345
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2346
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2347
-        }
2348
-    }
2349
-
2350
-
2351
-    /**
2352
-     * form_before_question_group
2353
-     *
2354
-     * @deprecated    as of 4.8.32.rc.000
2355
-     * @access        public
2356
-     * @param        string $output
2357
-     * @return        string
2358
-     */
2359
-    public function form_before_question_group($output)
2360
-    {
2361
-        EE_Error::doing_it_wrong(
2362
-            __CLASS__ . '::' . __FUNCTION__,
2363
-            esc_html__(
2364
-                '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.',
2365
-                'event_espresso'
2366
-            ),
2367
-            '4.8.32.rc.000'
2368
-        );
2369
-        return '
1299
+		if (! empty($registration_status)) {
1300
+			$where['STS_ID'] = $registration_status;
1301
+		} else {
1302
+			// make sure we exclude incomplete registrations, but only if not trashed.
1303
+			if ($view === 'trash') {
1304
+				$where['REG_deleted'] = true;
1305
+			} elseif ($view === 'incomplete') {
1306
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1307
+			} else {
1308
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1309
+			}
1310
+		}
1311
+		return $where;
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1317
+	 *
1318
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1319
+	 * @return array
1320
+	 * @throws EE_Error
1321
+	 * @throws InvalidArgumentException
1322
+	 * @throws InvalidDataTypeException
1323
+	 * @throws InvalidInterfaceException
1324
+	 */
1325
+	protected function _add_date_to_where_conditions(array $request)
1326
+	{
1327
+		$where = array();
1328
+		$view = EEH_Array::is_set($request, 'status', '');
1329
+		$month_range = ! empty($request['month_range'])
1330
+			? sanitize_text_field($request['month_range'])
1331
+			: '';
1332
+		$retrieve_for_today = $view === 'today';
1333
+		$retrieve_for_this_month = $view === 'month';
1334
+
1335
+		if ($retrieve_for_today) {
1336
+			$now = date('Y-m-d', current_time('timestamp'));
1337
+			$where['REG_date'] = array(
1338
+				'BETWEEN',
1339
+				array(
1340
+					EEM_Registration::instance()->convert_datetime_for_query(
1341
+						'REG_date',
1342
+						$now . ' 00:00:00',
1343
+						'Y-m-d H:i:s'
1344
+					),
1345
+					EEM_Registration::instance()->convert_datetime_for_query(
1346
+						'REG_date',
1347
+						$now . ' 23:59:59',
1348
+						'Y-m-d H:i:s'
1349
+					),
1350
+				),
1351
+			);
1352
+		} elseif ($retrieve_for_this_month) {
1353
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1354
+			$days_this_month = date('t', current_time('timestamp'));
1355
+			$where['REG_date'] = array(
1356
+				'BETWEEN',
1357
+				array(
1358
+					EEM_Registration::instance()->convert_datetime_for_query(
1359
+						'REG_date',
1360
+						$current_year_and_month . '-01 00:00:00',
1361
+						'Y-m-d H:i:s'
1362
+					),
1363
+					EEM_Registration::instance()->convert_datetime_for_query(
1364
+						'REG_date',
1365
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1366
+						'Y-m-d H:i:s'
1367
+					),
1368
+				),
1369
+			);
1370
+		} elseif ($month_range) {
1371
+			$pieces = explode(' ', $month_range, 3);
1372
+			$month_requested = ! empty($pieces[0])
1373
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1374
+				: '';
1375
+			$year_requested = ! empty($pieces[1])
1376
+				? $pieces[1]
1377
+				: '';
1378
+			// if there is not a month or year then we can't go further
1379
+			if ($month_requested && $year_requested) {
1380
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1381
+				$where['REG_date'] = array(
1382
+					'BETWEEN',
1383
+					array(
1384
+						EEM_Registration::instance()->convert_datetime_for_query(
1385
+							'REG_date',
1386
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1387
+							'Y-m-d H:i:s'
1388
+						),
1389
+						EEM_Registration::instance()->convert_datetime_for_query(
1390
+							'REG_date',
1391
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1392
+							'Y-m-d H:i:s'
1393
+						),
1394
+					),
1395
+				);
1396
+			}
1397
+		}
1398
+		return $where;
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * Adds any provided search restraints to the where conditions for the registrations query
1404
+	 *
1405
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1406
+	 * @return array
1407
+	 */
1408
+	protected function _add_search_to_where_conditions(array $request)
1409
+	{
1410
+		$where = array();
1411
+		if (! empty($request['s'])) {
1412
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1413
+			$where['OR*search_conditions'] = array(
1414
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1415
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1416
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1417
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1418
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1419
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1420
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1421
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1422
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1423
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1424
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1425
+				'REG_final_price'                         => array('LIKE', $search_string),
1426
+				'REG_code'                                => array('LIKE', $search_string),
1427
+				'REG_count'                               => array('LIKE', $search_string),
1428
+				'REG_group_size'                          => array('LIKE', $search_string),
1429
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1430
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1431
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1432
+			);
1433
+		}
1434
+		return $where;
1435
+	}
1436
+
1437
+
1438
+	/**
1439
+	 * Sets up the where conditions for the registrations query.
1440
+	 *
1441
+	 * @param array $request
1442
+	 * @return array
1443
+	 * @throws EE_Error
1444
+	 */
1445
+	protected function _get_where_conditions_for_registrations_query($request)
1446
+	{
1447
+		return apply_filters(
1448
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1449
+			array_merge(
1450
+				$this->addAttendeeIdToWhereConditions($request),
1451
+				$this->_add_event_id_to_where_conditions($request),
1452
+				$this->_add_category_id_to_where_conditions($request),
1453
+				$this->_add_datetime_id_to_where_conditions($request),
1454
+				$this->_add_registration_status_to_where_conditions($request),
1455
+				$this->_add_date_to_where_conditions($request),
1456
+				$this->_add_search_to_where_conditions($request)
1457
+			),
1458
+			$request
1459
+		);
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Sets up the orderby for the registrations query.
1465
+	 *
1466
+	 * @return array
1467
+	 */
1468
+	protected function _get_orderby_for_registrations_query()
1469
+	{
1470
+		$orderby_field = ! empty($this->_req_data['orderby'])
1471
+			? sanitize_text_field($this->_req_data['orderby'])
1472
+			: '';
1473
+		switch ($orderby_field) {
1474
+			case '_REG_ID':
1475
+				$orderby = array('REG_ID');
1476
+				break;
1477
+			case '_Reg_status':
1478
+				$orderby = array('STS_ID');
1479
+				break;
1480
+			case 'ATT_fname':
1481
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1482
+				break;
1483
+			case 'ATT_lname':
1484
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1485
+				break;
1486
+			case 'event_name':
1487
+				$orderby = array('Event.EVT_name');
1488
+				break;
1489
+			case 'DTT_EVT_start':
1490
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1491
+				break;
1492
+			default: // 'REG_date'
1493
+				$orderby = array('REG_date');
1494
+		}
1495
+
1496
+		// order
1497
+		$order = ! empty($this->_req_data['order'])
1498
+			? sanitize_text_field($this->_req_data['order'])
1499
+			: 'DESC';
1500
+		$orderby = array_combine(
1501
+			$orderby,
1502
+			array_fill(0, count($orderby), $order)
1503
+		);
1504
+		// because there are many registrations with the same date, define
1505
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
1506
+		if (empty($orderby['REG_ID'])) {
1507
+			$orderby['REG_ID'] = $order;
1508
+		}
1509
+		return array('order_by' => $orderby);
1510
+	}
1511
+
1512
+
1513
+	/**
1514
+	 * Sets up the limit for the registrations query.
1515
+	 *
1516
+	 * @param $per_page
1517
+	 * @return array
1518
+	 */
1519
+	protected function _get_limit($per_page)
1520
+	{
1521
+		$current_page = ! empty($this->_req_data['paged'])
1522
+			? absint($this->_req_data['paged'])
1523
+			: 1;
1524
+		$per_page = ! empty($this->_req_data['perpage'])
1525
+			? $this->_req_data['perpage']
1526
+			: $per_page;
1527
+
1528
+		// -1 means return all results so get out if that's set.
1529
+		if ((int) $per_page === -1) {
1530
+			return array();
1531
+		}
1532
+		$per_page = absint($per_page);
1533
+		$offset = ($current_page - 1) * $per_page;
1534
+		return array('limit' => array($offset, $per_page));
1535
+	}
1536
+
1537
+
1538
+	public function get_registration_status_array()
1539
+	{
1540
+		return self::$_reg_status;
1541
+	}
1542
+
1543
+
1544
+
1545
+
1546
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1547
+	/**
1548
+	 *        generates HTML for the View Registration Details Admin page
1549
+	 *
1550
+	 * @access protected
1551
+	 * @return void
1552
+	 * @throws DomainException
1553
+	 * @throws EE_Error
1554
+	 * @throws InvalidArgumentException
1555
+	 * @throws InvalidDataTypeException
1556
+	 * @throws InvalidInterfaceException
1557
+	 * @throws EntityNotFoundException
1558
+	 */
1559
+	protected function _registration_details()
1560
+	{
1561
+		$this->_template_args = array();
1562
+		$this->_set_registration_object();
1563
+		if (is_object($this->_registration)) {
1564
+			$transaction = $this->_registration->transaction()
1565
+				? $this->_registration->transaction()
1566
+				: EE_Transaction::new_instance();
1567
+			$this->_session = $transaction->session_data();
1568
+			$event_id = $this->_registration->event_ID();
1569
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1570
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1571
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1572
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1573
+			$this->_template_args['grand_total'] = $transaction->total();
1574
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1575
+			// link back to overview
1576
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1577
+			$this->_template_args['registration'] = $this->_registration;
1578
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1579
+				array(
1580
+					'action'   => 'default',
1581
+					'event_id' => $event_id,
1582
+				),
1583
+				REG_ADMIN_URL
1584
+			);
1585
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1586
+				array(
1587
+					'action' => 'default',
1588
+					'EVT_ID' => $event_id,
1589
+					'page'   => 'espresso_transactions',
1590
+				),
1591
+				admin_url('admin.php')
1592
+			);
1593
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1594
+				array(
1595
+					'page'   => 'espresso_events',
1596
+					'action' => 'edit',
1597
+					'post'   => $event_id,
1598
+				),
1599
+				admin_url('admin.php')
1600
+			);
1601
+			// next and previous links
1602
+			$next_reg = $this->_registration->next(
1603
+				null,
1604
+				array(),
1605
+				'REG_ID'
1606
+			);
1607
+			$this->_template_args['next_registration'] = $next_reg
1608
+				? $this->_next_link(
1609
+					EE_Admin_Page::add_query_args_and_nonce(
1610
+						array(
1611
+							'action'  => 'view_registration',
1612
+							'_REG_ID' => $next_reg['REG_ID'],
1613
+						),
1614
+						REG_ADMIN_URL
1615
+					),
1616
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1617
+				)
1618
+				: '';
1619
+			$previous_reg = $this->_registration->previous(
1620
+				null,
1621
+				array(),
1622
+				'REG_ID'
1623
+			);
1624
+			$this->_template_args['previous_registration'] = $previous_reg
1625
+				? $this->_previous_link(
1626
+					EE_Admin_Page::add_query_args_and_nonce(
1627
+						array(
1628
+							'action'  => 'view_registration',
1629
+							'_REG_ID' => $previous_reg['REG_ID'],
1630
+						),
1631
+						REG_ADMIN_URL
1632
+					),
1633
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1634
+				)
1635
+				: '';
1636
+			// grab header
1637
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1638
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1639
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1640
+				$template_path,
1641
+				$this->_template_args,
1642
+				true
1643
+			);
1644
+		} else {
1645
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1646
+		}
1647
+		// the details template wrapper
1648
+		$this->display_admin_page_with_sidebar();
1649
+	}
1650
+
1651
+
1652
+	protected function _registration_details_metaboxes()
1653
+	{
1654
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1655
+		$this->_set_registration_object();
1656
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1657
+		add_meta_box(
1658
+			'edit-reg-status-mbox',
1659
+			esc_html__('Registration Status', 'event_espresso'),
1660
+			array($this, 'set_reg_status_buttons_metabox'),
1661
+			$this->wp_page_slug,
1662
+			'normal',
1663
+			'high'
1664
+		);
1665
+		add_meta_box(
1666
+			'edit-reg-details-mbox',
1667
+			esc_html__('Registration Details', 'event_espresso'),
1668
+			array($this, '_reg_details_meta_box'),
1669
+			$this->wp_page_slug,
1670
+			'normal',
1671
+			'high'
1672
+		);
1673
+		if ($attendee instanceof EE_Attendee
1674
+			&& EE_Registry::instance()->CAP->current_user_can(
1675
+				'ee_edit_registration',
1676
+				'edit-reg-questions-mbox',
1677
+				$this->_registration->ID()
1678
+			)
1679
+		) {
1680
+			add_meta_box(
1681
+				'edit-reg-questions-mbox',
1682
+				esc_html__('Registration Form Answers', 'event_espresso'),
1683
+				array($this, '_reg_questions_meta_box'),
1684
+				$this->wp_page_slug,
1685
+				'normal',
1686
+				'high'
1687
+			);
1688
+		}
1689
+		add_meta_box(
1690
+			'edit-reg-registrant-mbox',
1691
+			esc_html__('Contact Details', 'event_espresso'),
1692
+			array($this, '_reg_registrant_side_meta_box'),
1693
+			$this->wp_page_slug,
1694
+			'side',
1695
+			'high'
1696
+		);
1697
+		if ($this->_registration->group_size() > 1) {
1698
+			add_meta_box(
1699
+				'edit-reg-attendees-mbox',
1700
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1701
+				array($this, '_reg_attendees_meta_box'),
1702
+				$this->wp_page_slug,
1703
+				'normal',
1704
+				'high'
1705
+			);
1706
+		}
1707
+	}
1708
+
1709
+
1710
+	/**
1711
+	 * set_reg_status_buttons_metabox
1712
+	 *
1713
+	 * @access protected
1714
+	 * @return string
1715
+	 * @throws \EE_Error
1716
+	 */
1717
+	public function set_reg_status_buttons_metabox()
1718
+	{
1719
+		$this->_set_registration_object();
1720
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1721
+		echo $change_reg_status_form->form_open(
1722
+			self::add_query_args_and_nonce(
1723
+				array(
1724
+					'action' => 'change_reg_status',
1725
+				),
1726
+				REG_ADMIN_URL
1727
+			)
1728
+		);
1729
+		echo $change_reg_status_form->get_html();
1730
+		echo $change_reg_status_form->form_close();
1731
+	}
1732
+
1733
+
1734
+	/**
1735
+	 * @return EE_Form_Section_Proper
1736
+	 * @throws EE_Error
1737
+	 * @throws InvalidArgumentException
1738
+	 * @throws InvalidDataTypeException
1739
+	 * @throws InvalidInterfaceException
1740
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1741
+	 */
1742
+	protected function _generate_reg_status_change_form()
1743
+	{
1744
+		return new EE_Form_Section_Proper(
1745
+			array(
1746
+				'name'            => 'reg_status_change_form',
1747
+				'html_id'         => 'reg-status-change-form',
1748
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1749
+				'subsections'     => array(
1750
+					'return'             => new EE_Hidden_Input(
1751
+						array(
1752
+							'name'    => 'return',
1753
+							'default' => 'view_registration',
1754
+						)
1755
+					),
1756
+					'REG_ID'             => new EE_Hidden_Input(
1757
+						array(
1758
+							'name'    => 'REG_ID',
1759
+							'default' => $this->_registration->ID(),
1760
+						)
1761
+					),
1762
+					'current_status'     => new EE_Form_Section_HTML(
1763
+						EEH_HTML::tr(
1764
+							EEH_HTML::th(
1765
+								EEH_HTML::label(
1766
+									EEH_HTML::strong(
1767
+										esc_html__('Current Registration Status', 'event_espresso')
1768
+									)
1769
+								)
1770
+							)
1771
+							. EEH_HTML::td(
1772
+								EEH_HTML::strong(
1773
+									$this->_registration->pretty_status(),
1774
+									'',
1775
+									'status-' . $this->_registration->status_ID(),
1776
+									'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1777
+								)
1778
+							)
1779
+						)
1780
+					),
1781
+					'reg_status'         => new EE_Select_Input(
1782
+						$this->_get_reg_statuses(),
1783
+						array(
1784
+							'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1785
+							'default'         => $this->_registration->status_ID(),
1786
+						)
1787
+					),
1788
+					'send_notifications' => new EE_Yes_No_Input(
1789
+						array(
1790
+							'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1791
+							'default'         => false,
1792
+							'html_help_text'  => esc_html__(
1793
+								'If set to "Yes", then the related messages will be sent to the registrant.',
1794
+								'event_espresso'
1795
+							),
1796
+						)
1797
+					),
1798
+					'submit'             => new EE_Submit_Input(
1799
+						array(
1800
+							'html_class'      => 'button-primary',
1801
+							'html_label_text' => '&nbsp;',
1802
+							'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1803
+						)
1804
+					),
1805
+				),
1806
+			)
1807
+		);
1808
+	}
1809
+
1810
+
1811
+	/**
1812
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1813
+	 *
1814
+	 * @return array
1815
+	 * @throws EE_Error
1816
+	 * @throws InvalidArgumentException
1817
+	 * @throws InvalidDataTypeException
1818
+	 * @throws InvalidInterfaceException
1819
+	 * @throws EntityNotFoundException
1820
+	 */
1821
+	protected function _get_reg_statuses()
1822
+	{
1823
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1824
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1825
+		// get current reg status
1826
+		$current_status = $this->_registration->status_ID();
1827
+		// is registration for free event? This will determine whether to display the pending payment option
1828
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1829
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1830
+		) {
1831
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1832
+		}
1833
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1834
+	}
1835
+
1836
+
1837
+	/**
1838
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1839
+	 *
1840
+	 * @param bool $status REG status given for changing registrations to.
1841
+	 * @param bool $notify Whether to send messages notifications or not.
1842
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1843
+	 * @throws EE_Error
1844
+	 * @throws InvalidArgumentException
1845
+	 * @throws InvalidDataTypeException
1846
+	 * @throws InvalidInterfaceException
1847
+	 * @throws ReflectionException
1848
+	 * @throws RuntimeException
1849
+	 * @throws EntityNotFoundException
1850
+	 */
1851
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1852
+	{
1853
+		if (isset($this->_req_data['reg_status_change_form'])) {
1854
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1855
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1856
+				: array();
1857
+		} else {
1858
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1859
+				? (array) $this->_req_data['_REG_ID']
1860
+				: array();
1861
+		}
1862
+		// sanitize $REG_IDs
1863
+		$REG_IDs = array_map('absint', $REG_IDs);
1864
+		// and remove empty entries
1865
+		$REG_IDs = array_filter($REG_IDs);
1866
+
1867
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1868
+
1869
+		/**
1870
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1871
+		 * Currently this value is used downstream by the _process_resend_registration method.
1872
+		 *
1873
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1874
+		 * @param bool                     $status           The status registrations were changed to.
1875
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1876
+		 * @param Registrations_Admin_Page $admin_page_object
1877
+		 */
1878
+		$this->_req_data['_REG_ID'] = apply_filters(
1879
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1880
+			$result['REG_ID'],
1881
+			$status,
1882
+			$result['success'],
1883
+			$this
1884
+		);
1885
+
1886
+		// notify?
1887
+		if ($notify
1888
+			&& $result['success']
1889
+			&& ! empty($this->_req_data['_REG_ID'])
1890
+			&& EE_Registry::instance()->CAP->current_user_can(
1891
+				'ee_send_message',
1892
+				'espresso_registrations_resend_registration'
1893
+			)
1894
+		) {
1895
+			$this->_process_resend_registration();
1896
+		}
1897
+		return $result;
1898
+	}
1899
+
1900
+
1901
+	/**
1902
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1903
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1904
+	 *
1905
+	 * @param array  $REG_IDs
1906
+	 * @param string $status
1907
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1908
+	 *                        slug sent with setting the registration status.
1909
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1910
+	 * @throws EE_Error
1911
+	 * @throws InvalidArgumentException
1912
+	 * @throws InvalidDataTypeException
1913
+	 * @throws InvalidInterfaceException
1914
+	 * @throws ReflectionException
1915
+	 * @throws RuntimeException
1916
+	 * @throws EntityNotFoundException
1917
+	 */
1918
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1919
+	{
1920
+		$success = false;
1921
+		// typecast $REG_IDs
1922
+		$REG_IDs = (array) $REG_IDs;
1923
+		if (! empty($REG_IDs)) {
1924
+			$success = true;
1925
+			// set default status if none is passed
1926
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1927
+			$status_context = $notify
1928
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1929
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1930
+			// loop through REG_ID's and change status
1931
+			foreach ($REG_IDs as $REG_ID) {
1932
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1933
+				if ($registration instanceof EE_Registration) {
1934
+					$registration->set_status(
1935
+						$status,
1936
+						false,
1937
+						new Context(
1938
+							$status_context,
1939
+							esc_html__(
1940
+								'Manually triggered status change on a Registration Admin Page route.',
1941
+								'event_espresso'
1942
+							)
1943
+						)
1944
+					);
1945
+					$result = $registration->save();
1946
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1947
+					$success = $result !== false ? $success : false;
1948
+				}
1949
+			}
1950
+		}
1951
+
1952
+		// return $success and processed registrations
1953
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1954
+	}
1955
+
1956
+
1957
+	/**
1958
+	 * Common logic for setting up success message and redirecting to appropriate route
1959
+	 *
1960
+	 * @param  string $STS_ID status id for the registration changed to
1961
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1962
+	 * @return void
1963
+	 * @throws EE_Error
1964
+	 */
1965
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1966
+	{
1967
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1968
+			: array('success' => false);
1969
+		$success = isset($result['success']) && $result['success'];
1970
+		// setup success message
1971
+		if ($success) {
1972
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1973
+				$msg = sprintf(
1974
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1975
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1976
+				);
1977
+			} else {
1978
+				$msg = sprintf(
1979
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1980
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1981
+				);
1982
+			}
1983
+			EE_Error::add_success($msg);
1984
+		} else {
1985
+			EE_Error::add_error(
1986
+				esc_html__(
1987
+					'Something went wrong, and the status was not changed',
1988
+					'event_espresso'
1989
+				),
1990
+				__FILE__,
1991
+				__LINE__,
1992
+				__FUNCTION__
1993
+			);
1994
+		}
1995
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
1996
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1997
+		} else {
1998
+			$route = array('action' => 'default');
1999
+		}
2000
+		// unset nonces
2001
+		foreach ($this->_req_data as $ref => $value) {
2002
+			if (strpos($ref, 'nonce') !== false) {
2003
+				unset($this->_req_data[ $ref ]);
2004
+				continue;
2005
+			}
2006
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
2007
+			$this->_req_data[ $ref ] = $value;
2008
+		}
2009
+		// merge request vars so that the reloaded list table contains any existing filter query params
2010
+		$route = array_merge($this->_req_data, $route);
2011
+		$this->_redirect_after_action($success, '', '', $route, true);
2012
+	}
2013
+
2014
+
2015
+	/**
2016
+	 * incoming reg status change from reg details page.
2017
+	 *
2018
+	 * @return void
2019
+	 */
2020
+	protected function _change_reg_status()
2021
+	{
2022
+		$this->_req_data['return'] = 'view_registration';
2023
+		// set notify based on whether the send notifications toggle is set or not
2024
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2025
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2026
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2027
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2028
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2029
+			case EEM_Registration::status_id_approved:
2030
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2031
+				$this->approve_registration($notify);
2032
+				break;
2033
+			case EEM_Registration::status_id_pending_payment:
2034
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2035
+				$this->pending_registration($notify);
2036
+				break;
2037
+			case EEM_Registration::status_id_not_approved:
2038
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2039
+				$this->not_approve_registration($notify);
2040
+				break;
2041
+			case EEM_Registration::status_id_declined:
2042
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2043
+				$this->decline_registration($notify);
2044
+				break;
2045
+			case EEM_Registration::status_id_cancelled:
2046
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2047
+				$this->cancel_registration($notify);
2048
+				break;
2049
+			case EEM_Registration::status_id_wait_list:
2050
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2051
+				$this->wait_list_registration($notify);
2052
+				break;
2053
+			case EEM_Registration::status_id_incomplete:
2054
+			default:
2055
+				$result['success'] = false;
2056
+				unset($this->_req_data['return']);
2057
+				$this->_reg_status_change_return('', false);
2058
+				break;
2059
+		}
2060
+	}
2061
+
2062
+
2063
+	/**
2064
+	 * Callback for bulk action routes.
2065
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2066
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2067
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2068
+	 * when an action is happening on just a single registration).
2069
+	 *
2070
+	 * @param      $action
2071
+	 * @param bool $notify
2072
+	 */
2073
+	protected function bulk_action_on_registrations($action, $notify = false)
2074
+	{
2075
+		do_action(
2076
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2077
+			$this,
2078
+			$action,
2079
+			$notify
2080
+		);
2081
+		$method = $action . '_registration';
2082
+		if (method_exists($this, $method)) {
2083
+			$this->$method($notify);
2084
+		}
2085
+	}
2086
+
2087
+
2088
+	/**
2089
+	 * approve_registration
2090
+	 *
2091
+	 * @access protected
2092
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2093
+	 * @return void
2094
+	 */
2095
+	protected function approve_registration($notify = false)
2096
+	{
2097
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2098
+	}
2099
+
2100
+
2101
+	/**
2102
+	 *        decline_registration
2103
+	 *
2104
+	 * @access protected
2105
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2106
+	 * @return void
2107
+	 */
2108
+	protected function decline_registration($notify = false)
2109
+	{
2110
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2111
+	}
2112
+
2113
+
2114
+	/**
2115
+	 *        cancel_registration
2116
+	 *
2117
+	 * @access protected
2118
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2119
+	 * @return void
2120
+	 */
2121
+	protected function cancel_registration($notify = false)
2122
+	{
2123
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2124
+	}
2125
+
2126
+
2127
+	/**
2128
+	 *        not_approve_registration
2129
+	 *
2130
+	 * @access protected
2131
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2132
+	 * @return void
2133
+	 */
2134
+	protected function not_approve_registration($notify = false)
2135
+	{
2136
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2137
+	}
2138
+
2139
+
2140
+	/**
2141
+	 *        decline_registration
2142
+	 *
2143
+	 * @access protected
2144
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2145
+	 * @return void
2146
+	 */
2147
+	protected function pending_registration($notify = false)
2148
+	{
2149
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2150
+	}
2151
+
2152
+
2153
+	/**
2154
+	 * waitlist_registration
2155
+	 *
2156
+	 * @access protected
2157
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2158
+	 * @return void
2159
+	 */
2160
+	protected function wait_list_registration($notify = false)
2161
+	{
2162
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2163
+	}
2164
+
2165
+
2166
+	/**
2167
+	 *        generates HTML for the Registration main meta box
2168
+	 *
2169
+	 * @access public
2170
+	 * @return void
2171
+	 * @throws DomainException
2172
+	 * @throws EE_Error
2173
+	 * @throws InvalidArgumentException
2174
+	 * @throws InvalidDataTypeException
2175
+	 * @throws InvalidInterfaceException
2176
+	 * @throws ReflectionException
2177
+	 * @throws EntityNotFoundException
2178
+	 */
2179
+	public function _reg_details_meta_box()
2180
+	{
2181
+		EEH_Autoloader::register_line_item_display_autoloaders();
2182
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2183
+		EE_Registry::instance()->load_helper('Line_Item');
2184
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2185
+			: EE_Transaction::new_instance();
2186
+		$this->_session = $transaction->session_data();
2187
+		$filters = new EE_Line_Item_Filter_Collection();
2188
+		// $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2189
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2190
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2191
+			$filters,
2192
+			$transaction->total_line_item()
2193
+		);
2194
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2195
+		$line_item_display = new EE_Line_Item_Display(
2196
+			'reg_admin_table',
2197
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2198
+		);
2199
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2200
+			$filtered_line_item_tree,
2201
+			array('EE_Registration' => $this->_registration)
2202
+		);
2203
+		$attendee = $this->_registration->attendee();
2204
+		if (EE_Registry::instance()->CAP->current_user_can(
2205
+			'ee_read_transaction',
2206
+			'espresso_transactions_view_transaction'
2207
+		)) {
2208
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2209
+				EE_Admin_Page::add_query_args_and_nonce(
2210
+					array(
2211
+						'action' => 'view_transaction',
2212
+						'TXN_ID' => $transaction->ID(),
2213
+					),
2214
+					TXN_ADMIN_URL
2215
+				),
2216
+				esc_html__(' View Transaction', 'event_espresso'),
2217
+				'button secondary-button right',
2218
+				'dashicons dashicons-cart'
2219
+			);
2220
+		} else {
2221
+			$this->_template_args['view_transaction_button'] = '';
2222
+		}
2223
+		if ($attendee instanceof EE_Attendee
2224
+			&& EE_Registry::instance()->CAP->current_user_can(
2225
+				'ee_send_message',
2226
+				'espresso_registrations_resend_registration'
2227
+			)
2228
+		) {
2229
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2230
+				EE_Admin_Page::add_query_args_and_nonce(
2231
+					array(
2232
+						'action'      => 'resend_registration',
2233
+						'_REG_ID'     => $this->_registration->ID(),
2234
+						'redirect_to' => 'view_registration',
2235
+					),
2236
+					REG_ADMIN_URL
2237
+				),
2238
+				esc_html__(' Resend Registration', 'event_espresso'),
2239
+				'button secondary-button right',
2240
+				'dashicons dashicons-email-alt'
2241
+			);
2242
+		} else {
2243
+			$this->_template_args['resend_registration_button'] = '';
2244
+		}
2245
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2246
+		$payment = $transaction->get_first_related('Payment');
2247
+		$payment = ! $payment instanceof EE_Payment
2248
+			? EE_Payment::new_instance()
2249
+			: $payment;
2250
+		$payment_method = $payment->get_first_related('Payment_Method');
2251
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2252
+			? EE_Payment_Method::new_instance()
2253
+			: $payment_method;
2254
+		$reg_details = array(
2255
+			'payment_method'       => $payment_method->name(),
2256
+			'response_msg'         => $payment->gateway_response(),
2257
+			'registration_id'      => $this->_registration->get('REG_code'),
2258
+			'registration_session' => $this->_registration->session_ID(),
2259
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2260
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2261
+		);
2262
+		if (isset($reg_details['registration_id'])) {
2263
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2264
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2265
+				'Registration ID',
2266
+				'event_espresso'
2267
+			);
2268
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2269
+		}
2270
+		if (isset($reg_details['payment_method'])) {
2271
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2272
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2273
+				'Most Recent Payment Method',
2274
+				'event_espresso'
2275
+			);
2276
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2277
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2278
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2279
+				'Payment method response',
2280
+				'event_espresso'
2281
+			);
2282
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2283
+		}
2284
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2285
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2286
+			'Registration Session',
2287
+			'event_espresso'
2288
+		);
2289
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2290
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2291
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2292
+			'Registration placed from IP',
2293
+			'event_espresso'
2294
+		);
2295
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2296
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2297
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2298
+			'Registrant User Agent',
2299
+			'event_espresso'
2300
+		);
2301
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2302
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2303
+			array(
2304
+				'action'   => 'default',
2305
+				'event_id' => $this->_registration->event_ID(),
2306
+			),
2307
+			REG_ADMIN_URL
2308
+		);
2309
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2310
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2311
+		$template_path =
2312
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2313
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2314
+	}
2315
+
2316
+
2317
+	/**
2318
+	 * generates HTML for the Registration Questions meta box.
2319
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2320
+	 * otherwise uses new forms system
2321
+	 *
2322
+	 * @access public
2323
+	 * @return void
2324
+	 * @throws DomainException
2325
+	 * @throws EE_Error
2326
+	 */
2327
+	public function _reg_questions_meta_box()
2328
+	{
2329
+		// allow someone to override this method entirely
2330
+		if (apply_filters(
2331
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2332
+			true,
2333
+			$this,
2334
+			$this->_registration
2335
+		)) {
2336
+			$form = $this->_get_reg_custom_questions_form(
2337
+				$this->_registration->ID()
2338
+			);
2339
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2340
+				? $form->get_html_and_js()
2341
+				: '';
2342
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2343
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2344
+			$template_path =
2345
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2346
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2347
+		}
2348
+	}
2349
+
2350
+
2351
+	/**
2352
+	 * form_before_question_group
2353
+	 *
2354
+	 * @deprecated    as of 4.8.32.rc.000
2355
+	 * @access        public
2356
+	 * @param        string $output
2357
+	 * @return        string
2358
+	 */
2359
+	public function form_before_question_group($output)
2360
+	{
2361
+		EE_Error::doing_it_wrong(
2362
+			__CLASS__ . '::' . __FUNCTION__,
2363
+			esc_html__(
2364
+				'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.',
2365
+				'event_espresso'
2366
+			),
2367
+			'4.8.32.rc.000'
2368
+		);
2369
+		return '
2370 2370
 	<table class="form-table ee-width-100">
2371 2371
 		<tbody>
2372 2372
 			';
2373
-    }
2374
-
2375
-
2376
-    /**
2377
-     * form_after_question_group
2378
-     *
2379
-     * @deprecated    as of 4.8.32.rc.000
2380
-     * @access        public
2381
-     * @param        string $output
2382
-     * @return        string
2383
-     */
2384
-    public function form_after_question_group($output)
2385
-    {
2386
-        EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2388
-            esc_html__(
2389
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
-                'event_espresso'
2391
-            ),
2392
-            '4.8.32.rc.000'
2393
-        );
2394
-        return '
2373
+	}
2374
+
2375
+
2376
+	/**
2377
+	 * form_after_question_group
2378
+	 *
2379
+	 * @deprecated    as of 4.8.32.rc.000
2380
+	 * @access        public
2381
+	 * @param        string $output
2382
+	 * @return        string
2383
+	 */
2384
+	public function form_after_question_group($output)
2385
+	{
2386
+		EE_Error::doing_it_wrong(
2387
+			__CLASS__ . '::' . __FUNCTION__,
2388
+			esc_html__(
2389
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390
+				'event_espresso'
2391
+			),
2392
+			'4.8.32.rc.000'
2393
+		);
2394
+		return '
2395 2395
 			<tr class="hide-if-no-js">
2396 2396
 				<th> </th>
2397 2397
 				<td class="reg-admin-edit-attendee-question-td">
2398 2398
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2399
-               . esc_attr__('click to edit question', 'event_espresso')
2400
-               . '">
2399
+			   . esc_attr__('click to edit question', 'event_espresso')
2400
+			   . '">
2401 2401
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2402
-               . esc_html__('edit the above question group', 'event_espresso')
2403
-               . '</span>
2402
+			   . esc_html__('edit the above question group', 'event_espresso')
2403
+			   . '</span>
2404 2404
 						<div class="dashicons dashicons-edit"></div>
2405 2405
 					</a>
2406 2406
 				</td>
@@ -2408,606 +2408,606 @@  discard block
 block discarded – undo
2408 2408
 		</tbody>
2409 2409
 	</table>
2410 2410
 ';
2411
-    }
2412
-
2413
-
2414
-    /**
2415
-     * form_form_field_label_wrap
2416
-     *
2417
-     * @deprecated    as of 4.8.32.rc.000
2418
-     * @access        public
2419
-     * @param        string $label
2420
-     * @return        string
2421
-     */
2422
-    public function form_form_field_label_wrap($label)
2423
-    {
2424
-        EE_Error::doing_it_wrong(
2425
-            __CLASS__ . '::' . __FUNCTION__,
2426
-            esc_html__(
2427
-                '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.',
2428
-                'event_espresso'
2429
-            ),
2430
-            '4.8.32.rc.000'
2431
-        );
2432
-        return '
2411
+	}
2412
+
2413
+
2414
+	/**
2415
+	 * form_form_field_label_wrap
2416
+	 *
2417
+	 * @deprecated    as of 4.8.32.rc.000
2418
+	 * @access        public
2419
+	 * @param        string $label
2420
+	 * @return        string
2421
+	 */
2422
+	public function form_form_field_label_wrap($label)
2423
+	{
2424
+		EE_Error::doing_it_wrong(
2425
+			__CLASS__ . '::' . __FUNCTION__,
2426
+			esc_html__(
2427
+				'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.',
2428
+				'event_espresso'
2429
+			),
2430
+			'4.8.32.rc.000'
2431
+		);
2432
+		return '
2433 2433
 			<tr>
2434 2434
 				<th>
2435 2435
 					' . $label . '
2436 2436
 				</th>';
2437
-    }
2438
-
2439
-
2440
-    /**
2441
-     * form_form_field_input__wrap
2442
-     *
2443
-     * @deprecated    as of 4.8.32.rc.000
2444
-     * @access        public
2445
-     * @param        string $input
2446
-     * @return        string
2447
-     */
2448
-    public function form_form_field_input__wrap($input)
2449
-    {
2450
-        EE_Error::doing_it_wrong(
2451
-            __CLASS__ . '::' . __FUNCTION__,
2452
-            esc_html__(
2453
-                '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.',
2454
-                'event_espresso'
2455
-            ),
2456
-            '4.8.32.rc.000'
2457
-        );
2458
-        return '
2437
+	}
2438
+
2439
+
2440
+	/**
2441
+	 * form_form_field_input__wrap
2442
+	 *
2443
+	 * @deprecated    as of 4.8.32.rc.000
2444
+	 * @access        public
2445
+	 * @param        string $input
2446
+	 * @return        string
2447
+	 */
2448
+	public function form_form_field_input__wrap($input)
2449
+	{
2450
+		EE_Error::doing_it_wrong(
2451
+			__CLASS__ . '::' . __FUNCTION__,
2452
+			esc_html__(
2453
+				'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.',
2454
+				'event_espresso'
2455
+			),
2456
+			'4.8.32.rc.000'
2457
+		);
2458
+		return '
2459 2459
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2460 2460
 					' . $input . '
2461 2461
 				</td>
2462 2462
 			</tr>';
2463
-    }
2464
-
2465
-
2466
-    /**
2467
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2468
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2469
-     * to display the page
2470
-     *
2471
-     * @access protected
2472
-     * @return void
2473
-     * @throws EE_Error
2474
-     */
2475
-    protected function _update_attendee_registration_form()
2476
-    {
2477
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2478
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2479
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2480
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2481
-            if ($success) {
2482
-                $what = esc_html__('Registration Form', 'event_espresso');
2483
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2484
-                    : array('action' => 'default');
2485
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2486
-            }
2487
-        }
2488
-    }
2489
-
2490
-
2491
-    /**
2492
-     * Gets the form for saving registrations custom questions (if done
2493
-     * previously retrieves the cached form object, which may have validation errors in it)
2494
-     *
2495
-     * @param int $REG_ID
2496
-     * @return EE_Registration_Custom_Questions_Form
2497
-     * @throws EE_Error
2498
-     * @throws InvalidArgumentException
2499
-     * @throws InvalidDataTypeException
2500
-     * @throws InvalidInterfaceException
2501
-     */
2502
-    protected function _get_reg_custom_questions_form($REG_ID)
2503
-    {
2504
-        if (! $this->_reg_custom_questions_form) {
2505
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2506
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2507
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2508
-            );
2509
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2510
-        }
2511
-        return $this->_reg_custom_questions_form;
2512
-    }
2513
-
2514
-
2515
-    /**
2516
-     * Saves
2517
-     *
2518
-     * @access private
2519
-     * @param bool $REG_ID
2520
-     * @return bool
2521
-     * @throws EE_Error
2522
-     * @throws InvalidArgumentException
2523
-     * @throws InvalidDataTypeException
2524
-     * @throws InvalidInterfaceException
2525
-     */
2526
-    private function _save_reg_custom_questions_form($REG_ID = false)
2527
-    {
2528
-        if (! $REG_ID) {
2529
-            EE_Error::add_error(
2530
-                esc_html__(
2531
-                    'An error occurred. No registration ID was received.',
2532
-                    'event_espresso'
2533
-                ),
2534
-                __FILE__,
2535
-                __FUNCTION__,
2536
-                __LINE__
2537
-            );
2538
-        }
2539
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2540
-        $form->receive_form_submission($this->_req_data);
2541
-        $success = false;
2542
-        if ($form->is_valid()) {
2543
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2544
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2545
-                    $where_conditions = array(
2546
-                        'QST_ID' => $question_id,
2547
-                        'REG_ID' => $REG_ID,
2548
-                    );
2549
-                    $possibly_new_values = array(
2550
-                        'ANS_value' => $input->normalized_value(),
2551
-                    );
2552
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2553
-                    if ($answer instanceof EE_Answer) {
2554
-                        $success = $answer->save($possibly_new_values);
2555
-                    } else {
2556
-                        // insert it then
2557
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2558
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2559
-                        $success = $answer->save();
2560
-                    }
2561
-                }
2562
-            }
2563
-        } else {
2564
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2565
-        }
2566
-        return $success;
2567
-    }
2568
-
2569
-
2570
-    /**
2571
-     *        generates HTML for the Registration main meta box
2572
-     *
2573
-     * @access public
2574
-     * @return void
2575
-     * @throws DomainException
2576
-     * @throws EE_Error
2577
-     * @throws InvalidArgumentException
2578
-     * @throws InvalidDataTypeException
2579
-     * @throws InvalidInterfaceException
2580
-     */
2581
-    public function _reg_attendees_meta_box()
2582
-    {
2583
-        $REG = EEM_Registration::instance();
2584
-        // get all other registrations on this transaction, and cache
2585
-        // the attendees for them so we don't have to run another query using force_join
2586
-        $registrations = $REG->get_all(
2587
-            array(
2588
-                array(
2589
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2590
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2591
-                ),
2592
-                'force_join' => array('Attendee'),
2593
-            )
2594
-        );
2595
-        $this->_template_args['attendees'] = array();
2596
-        $this->_template_args['attendee_notice'] = '';
2597
-        if (empty($registrations)
2598
-            || (is_array($registrations)
2599
-                && ! EEH_Array::get_one_item_from_array($registrations))
2600
-        ) {
2601
-            EE_Error::add_error(
2602
-                esc_html__(
2603
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2604
-                    'event_espresso'
2605
-                ),
2606
-                __FILE__,
2607
-                __FUNCTION__,
2608
-                __LINE__
2609
-            );
2610
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2611
-        } else {
2612
-            $att_nmbr = 1;
2613
-            foreach ($registrations as $registration) {
2614
-                /* @var $registration EE_Registration */
2615
-                $attendee = $registration->attendee()
2616
-                    ? $registration->attendee()
2617
-                    : EEM_Attendee::instance()
2618
-                                  ->create_default_object();
2619
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2620
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2621
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2622
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2623
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2624
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2625
-                    ', ',
2626
-                    $attendee->full_address_as_array()
2627
-                );
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2629
-                    array(
2630
-                        'action' => 'edit_attendee',
2631
-                        'post'   => $attendee->ID(),
2632
-                    ),
2633
-                    REG_ADMIN_URL
2634
-                );
2635
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2636
-                $att_nmbr++;
2637
-            }
2638
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2639
-        }
2640
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2641
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2642
-    }
2643
-
2644
-
2645
-    /**
2646
-     *        generates HTML for the Edit Registration side meta box
2647
-     *
2648
-     * @access public
2649
-     * @return void
2650
-     * @throws DomainException
2651
-     * @throws EE_Error
2652
-     * @throws InvalidArgumentException
2653
-     * @throws InvalidDataTypeException
2654
-     * @throws InvalidInterfaceException
2655
-     */
2656
-    public function _reg_registrant_side_meta_box()
2657
-    {
2658
-        /*@var $attendee EE_Attendee */
2659
-        $att_check = $this->_registration->attendee();
2660
-        $attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2661
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2662
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2663
-        // primary registration object (that way we know if we need to show create button or not)
2664
-        if (! $this->_registration->is_primary_registrant()) {
2665
-            $primary_registration = $this->_registration->get_primary_registration();
2666
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2667
-                : null;
2668
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2669
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2670
-                // custom attendee object so let's not worry about the primary reg.
2671
-                $primary_registration = null;
2672
-            }
2673
-        } else {
2674
-            $primary_registration = null;
2675
-        }
2676
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2677
-        $this->_template_args['fname'] = $attendee->fname();
2678
-        $this->_template_args['lname'] = $attendee->lname();
2679
-        $this->_template_args['email'] = $attendee->email();
2680
-        $this->_template_args['phone'] = $attendee->phone();
2681
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2682
-        // edit link
2683
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2684
-            array(
2685
-                'action' => 'edit_attendee',
2686
-                'post'   => $attendee->ID(),
2687
-            ),
2688
-            REG_ADMIN_URL
2689
-        );
2690
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2691
-        // create link
2692
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2693
-            ? EE_Admin_Page::add_query_args_and_nonce(
2694
-                array(
2695
-                    'action'  => 'duplicate_attendee',
2696
-                    '_REG_ID' => $this->_registration->ID(),
2697
-                ),
2698
-                REG_ADMIN_URL
2699
-            ) : '';
2700
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2701
-        $this->_template_args['att_check'] = $att_check;
2702
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2703
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2704
-    }
2705
-
2706
-
2707
-    /**
2708
-     * trash or restore registrations
2709
-     *
2710
-     * @param  boolean $trash whether to archive or restore
2711
-     * @return void
2712
-     * @throws EE_Error
2713
-     * @throws InvalidArgumentException
2714
-     * @throws InvalidDataTypeException
2715
-     * @throws InvalidInterfaceException
2716
-     * @throws RuntimeException
2717
-     * @access protected
2718
-     */
2719
-    protected function _trash_or_restore_registrations($trash = true)
2720
-    {
2721
-        // if empty _REG_ID then get out because there's nothing to do
2722
-        if (empty($this->_req_data['_REG_ID'])) {
2723
-            EE_Error::add_error(
2724
-                sprintf(
2725
-                    esc_html__(
2726
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2727
-                        'event_espresso'
2728
-                    ),
2729
-                    $trash ? 'trash' : 'restore'
2730
-                ),
2731
-                __FILE__,
2732
-                __LINE__,
2733
-                __FUNCTION__
2734
-            );
2735
-            $this->_redirect_after_action(false, '', '', array(), true);
2736
-        }
2737
-        $success = 0;
2738
-        $overwrite_msgs = false;
2739
-        // Checkboxes
2740
-        if (! is_array($this->_req_data['_REG_ID'])) {
2741
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2742
-        }
2743
-        $reg_count = count($this->_req_data['_REG_ID']);
2744
-        // cycle thru checkboxes
2745
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2746
-            /** @var EE_Registration $REG */
2747
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2748
-            $payments = $REG->registration_payments();
2749
-            if (! empty($payments)) {
2750
-                $name = $REG->attendee() instanceof EE_Attendee
2751
-                    ? $REG->attendee()->full_name()
2752
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2753
-                $overwrite_msgs = true;
2754
-                EE_Error::add_error(
2755
-                    sprintf(
2756
-                        esc_html__(
2757
-                            '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.',
2758
-                            'event_espresso'
2759
-                        ),
2760
-                        $name
2761
-                    ),
2762
-                    __FILE__,
2763
-                    __FUNCTION__,
2764
-                    __LINE__
2765
-                );
2766
-                // can't trash this registration because it has payments.
2767
-                continue;
2768
-            }
2769
-            $updated = $trash ? $REG->delete() : $REG->restore();
2770
-            if ($updated) {
2771
-                $success++;
2772
-            }
2773
-        }
2774
-        $this->_redirect_after_action(
2775
-            $success === $reg_count, // were ALL registrations affected?
2776
-            $success > 1
2777
-                ? esc_html__('Registrations', 'event_espresso')
2778
-                : esc_html__('Registration', 'event_espresso'),
2779
-            $trash
2780
-                ? esc_html__('moved to the trash', 'event_espresso')
2781
-                : esc_html__('restored', 'event_espresso'),
2782
-            array('action' => 'default'),
2783
-            $overwrite_msgs
2784
-        );
2785
-    }
2786
-
2787
-
2788
-    /**
2789
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2790
-     * registration but also.
2791
-     * 1. Removing relations to EE_Attendee
2792
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2793
-     * ALSO trashed.
2794
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2795
-     * 4. Removing relationships between all tickets and the related registrations
2796
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2797
-     * 6. Deleting permanently any related Checkins.
2798
-     *
2799
-     * @return void
2800
-     * @throws EE_Error
2801
-     * @throws InvalidArgumentException
2802
-     * @throws InvalidDataTypeException
2803
-     * @throws InvalidInterfaceException
2804
-     */
2805
-    protected function _delete_registrations()
2806
-    {
2807
-        $REG_MDL = EEM_Registration::instance();
2808
-        $success = 1;
2809
-        // Checkboxes
2810
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2811
-            // if array has more than one element than success message should be plural
2812
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2813
-            // cycle thru checkboxes
2814
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2815
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2816
-                if (! $REG instanceof EE_Registration) {
2817
-                    continue;
2818
-                }
2819
-                $deleted = $this->_delete_registration($REG);
2820
-                if (! $deleted) {
2821
-                    $success = 0;
2822
-                }
2823
-            }
2824
-        } else {
2825
-            // grab single id and delete
2826
-            $REG_ID = $this->_req_data['_REG_ID'];
2827
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2828
-            $deleted = $this->_delete_registration($REG);
2829
-            if (! $deleted) {
2830
-                $success = 0;
2831
-            }
2832
-        }
2833
-        $what = $success > 1
2834
-            ? esc_html__('Registrations', 'event_espresso')
2835
-            : esc_html__('Registration', 'event_espresso');
2836
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2837
-        $this->_redirect_after_action(
2838
-            $success,
2839
-            $what,
2840
-            $action_desc,
2841
-            array('action' => 'default'),
2842
-            true
2843
-        );
2844
-    }
2845
-
2846
-
2847
-    /**
2848
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2849
-     * models get affected.
2850
-     *
2851
-     * @param  EE_Registration $REG registration to be deleted permenantly
2852
-     * @return bool true = successful deletion, false = fail.
2853
-     * @throws EE_Error
2854
-     */
2855
-    protected function _delete_registration(EE_Registration $REG)
2856
-    {
2857
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2858
-        // registrations on the transaction that are NOT trashed.
2859
-        $TXN = $REG->get_first_related('Transaction');
2860
-        $REGS = $TXN->get_many_related('Registration');
2861
-        $all_trashed = true;
2862
-        foreach ($REGS as $registration) {
2863
-            if (! $registration->get('REG_deleted')) {
2864
-                $all_trashed = false;
2865
-            }
2866
-        }
2867
-        if (! $all_trashed) {
2868
-            EE_Error::add_error(
2869
-                esc_html__(
2870
-                    '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.',
2871
-                    'event_espresso'
2872
-                ),
2873
-                __FILE__,
2874
-                __FUNCTION__,
2875
-                __LINE__
2876
-            );
2877
-            return false;
2878
-        }
2879
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2880
-        // separately from THIS one).
2881
-        foreach ($REGS as $registration) {
2882
-            // delete related answers
2883
-            $registration->delete_related_permanently('Answer');
2884
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2885
-            $attendee = $registration->get_first_related('Attendee');
2886
-            if ($attendee instanceof EE_Attendee) {
2887
-                $registration->_remove_relation_to($attendee, 'Attendee');
2888
-            }
2889
-            // now remove relationships to tickets on this registration.
2890
-            $registration->_remove_relations('Ticket');
2891
-            // now delete permanently the checkins related to this registration.
2892
-            $registration->delete_related_permanently('Checkin');
2893
-            if ($registration->ID() === $REG->ID()) {
2894
-                continue;
2895
-            } //we don't want to delete permanently the existing registration just yet.
2896
-            // remove relation to transaction for these registrations if NOT the existing registrations
2897
-            $registration->_remove_relations('Transaction');
2898
-            // delete permanently any related messages.
2899
-            $registration->delete_related_permanently('Message');
2900
-            // now delete this registration permanently
2901
-            $registration->delete_permanently();
2902
-        }
2903
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2904
-        // (the transaction and line items should be all that's left).
2905
-        // delete the line items related to the transaction for this registration.
2906
-        $TXN->delete_related_permanently('Line_Item');
2907
-        // we need to remove all the relationships on the transaction
2908
-        $TXN->delete_related_permanently('Payment');
2909
-        $TXN->delete_related_permanently('Extra_Meta');
2910
-        $TXN->delete_related_permanently('Message');
2911
-        // now we can delete this REG permanently (and the transaction of course)
2912
-        $REG->delete_related_permanently('Transaction');
2913
-        return $REG->delete_permanently();
2914
-    }
2915
-
2916
-
2917
-    /**
2918
-     *    generates HTML for the Register New Attendee Admin page
2919
-     *
2920
-     * @access private
2921
-     * @throws DomainException
2922
-     * @throws EE_Error
2923
-     */
2924
-    public function new_registration()
2925
-    {
2926
-        if (! $this->_set_reg_event()) {
2927
-            throw new EE_Error(
2928
-                esc_html__(
2929
-                    'Unable to continue with registering because there is no Event ID in the request',
2930
-                    'event_espresso'
2931
-                )
2932
-            );
2933
-        }
2934
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2935
-        // gotta start with a clean slate if we're not coming here via ajax
2936
-        if (! defined('DOING_AJAX')
2937
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2938
-        ) {
2939
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2940
-        }
2941
-        $this->_template_args['event_name'] = '';
2942
-        // event name
2943
-        if ($this->_reg_event) {
2944
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2945
-            $edit_event_url = self::add_query_args_and_nonce(
2946
-                array(
2947
-                    'action' => 'edit',
2948
-                    'post'   => $this->_reg_event->ID(),
2949
-                ),
2950
-                EVENTS_ADMIN_URL
2951
-            );
2952
-            $edit_event_lnk = '<a href="'
2953
-                              . $edit_event_url
2954
-                              . '" title="'
2955
-                              . esc_attr__('Edit ', 'event_espresso')
2956
-                              . $this->_reg_event->name()
2957
-                              . '">'
2958
-                              . esc_html__('Edit Event', 'event_espresso')
2959
-                              . '</a>';
2960
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2961
-                                                   . $edit_event_lnk
2962
-                                                   . '</span>';
2963
-        }
2964
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2965
-        if (defined('DOING_AJAX')) {
2966
-            $this->_return_json();
2967
-        }
2968
-        // grab header
2969
-        $template_path =
2970
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2971
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2972
-            $template_path,
2973
-            $this->_template_args,
2974
-            true
2975
-        );
2976
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2977
-        // the details template wrapper
2978
-        $this->display_admin_page_with_sidebar();
2979
-    }
2980
-
2981
-
2982
-    /**
2983
-     * This returns the content for a registration step
2984
-     *
2985
-     * @access protected
2986
-     * @return string html
2987
-     * @throws DomainException
2988
-     * @throws EE_Error
2989
-     * @throws InvalidArgumentException
2990
-     * @throws InvalidDataTypeException
2991
-     * @throws InvalidInterfaceException
2992
-     */
2993
-    protected function _get_registration_step_content()
2994
-    {
2995
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2996
-            $warning_msg = sprintf(
2997
-                esc_html__(
2998
-                    '%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',
2999
-                    'event_espresso'
3000
-                ),
3001
-                '<br />',
3002
-                '<h3 class="important-notice">',
3003
-                '</h3>',
3004
-                '<div class="float-right">',
3005
-                '<span id="redirect_timer" class="important-notice">30</span>',
3006
-                '</div>',
3007
-                '<b>',
3008
-                '</b>'
3009
-            );
3010
-            return '
2463
+	}
2464
+
2465
+
2466
+	/**
2467
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2468
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2469
+	 * to display the page
2470
+	 *
2471
+	 * @access protected
2472
+	 * @return void
2473
+	 * @throws EE_Error
2474
+	 */
2475
+	protected function _update_attendee_registration_form()
2476
+	{
2477
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2478
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2479
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2480
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2481
+			if ($success) {
2482
+				$what = esc_html__('Registration Form', 'event_espresso');
2483
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2484
+					: array('action' => 'default');
2485
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2486
+			}
2487
+		}
2488
+	}
2489
+
2490
+
2491
+	/**
2492
+	 * Gets the form for saving registrations custom questions (if done
2493
+	 * previously retrieves the cached form object, which may have validation errors in it)
2494
+	 *
2495
+	 * @param int $REG_ID
2496
+	 * @return EE_Registration_Custom_Questions_Form
2497
+	 * @throws EE_Error
2498
+	 * @throws InvalidArgumentException
2499
+	 * @throws InvalidDataTypeException
2500
+	 * @throws InvalidInterfaceException
2501
+	 */
2502
+	protected function _get_reg_custom_questions_form($REG_ID)
2503
+	{
2504
+		if (! $this->_reg_custom_questions_form) {
2505
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2506
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2507
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2508
+			);
2509
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2510
+		}
2511
+		return $this->_reg_custom_questions_form;
2512
+	}
2513
+
2514
+
2515
+	/**
2516
+	 * Saves
2517
+	 *
2518
+	 * @access private
2519
+	 * @param bool $REG_ID
2520
+	 * @return bool
2521
+	 * @throws EE_Error
2522
+	 * @throws InvalidArgumentException
2523
+	 * @throws InvalidDataTypeException
2524
+	 * @throws InvalidInterfaceException
2525
+	 */
2526
+	private function _save_reg_custom_questions_form($REG_ID = false)
2527
+	{
2528
+		if (! $REG_ID) {
2529
+			EE_Error::add_error(
2530
+				esc_html__(
2531
+					'An error occurred. No registration ID was received.',
2532
+					'event_espresso'
2533
+				),
2534
+				__FILE__,
2535
+				__FUNCTION__,
2536
+				__LINE__
2537
+			);
2538
+		}
2539
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2540
+		$form->receive_form_submission($this->_req_data);
2541
+		$success = false;
2542
+		if ($form->is_valid()) {
2543
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2544
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2545
+					$where_conditions = array(
2546
+						'QST_ID' => $question_id,
2547
+						'REG_ID' => $REG_ID,
2548
+					);
2549
+					$possibly_new_values = array(
2550
+						'ANS_value' => $input->normalized_value(),
2551
+					);
2552
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2553
+					if ($answer instanceof EE_Answer) {
2554
+						$success = $answer->save($possibly_new_values);
2555
+					} else {
2556
+						// insert it then
2557
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2558
+						$answer = EE_Answer::new_instance($cols_n_vals);
2559
+						$success = $answer->save();
2560
+					}
2561
+				}
2562
+			}
2563
+		} else {
2564
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2565
+		}
2566
+		return $success;
2567
+	}
2568
+
2569
+
2570
+	/**
2571
+	 *        generates HTML for the Registration main meta box
2572
+	 *
2573
+	 * @access public
2574
+	 * @return void
2575
+	 * @throws DomainException
2576
+	 * @throws EE_Error
2577
+	 * @throws InvalidArgumentException
2578
+	 * @throws InvalidDataTypeException
2579
+	 * @throws InvalidInterfaceException
2580
+	 */
2581
+	public function _reg_attendees_meta_box()
2582
+	{
2583
+		$REG = EEM_Registration::instance();
2584
+		// get all other registrations on this transaction, and cache
2585
+		// the attendees for them so we don't have to run another query using force_join
2586
+		$registrations = $REG->get_all(
2587
+			array(
2588
+				array(
2589
+					'TXN_ID' => $this->_registration->transaction_ID(),
2590
+					'REG_ID' => array('!=', $this->_registration->ID()),
2591
+				),
2592
+				'force_join' => array('Attendee'),
2593
+			)
2594
+		);
2595
+		$this->_template_args['attendees'] = array();
2596
+		$this->_template_args['attendee_notice'] = '';
2597
+		if (empty($registrations)
2598
+			|| (is_array($registrations)
2599
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2600
+		) {
2601
+			EE_Error::add_error(
2602
+				esc_html__(
2603
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2604
+					'event_espresso'
2605
+				),
2606
+				__FILE__,
2607
+				__FUNCTION__,
2608
+				__LINE__
2609
+			);
2610
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2611
+		} else {
2612
+			$att_nmbr = 1;
2613
+			foreach ($registrations as $registration) {
2614
+				/* @var $registration EE_Registration */
2615
+				$attendee = $registration->attendee()
2616
+					? $registration->attendee()
2617
+					: EEM_Attendee::instance()
2618
+								  ->create_default_object();
2619
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2620
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2621
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2622
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2623
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2624
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2625
+					', ',
2626
+					$attendee->full_address_as_array()
2627
+				);
2628
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2629
+					array(
2630
+						'action' => 'edit_attendee',
2631
+						'post'   => $attendee->ID(),
2632
+					),
2633
+					REG_ADMIN_URL
2634
+				);
2635
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2636
+				$att_nmbr++;
2637
+			}
2638
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2639
+		}
2640
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2641
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2642
+	}
2643
+
2644
+
2645
+	/**
2646
+	 *        generates HTML for the Edit Registration side meta box
2647
+	 *
2648
+	 * @access public
2649
+	 * @return void
2650
+	 * @throws DomainException
2651
+	 * @throws EE_Error
2652
+	 * @throws InvalidArgumentException
2653
+	 * @throws InvalidDataTypeException
2654
+	 * @throws InvalidInterfaceException
2655
+	 */
2656
+	public function _reg_registrant_side_meta_box()
2657
+	{
2658
+		/*@var $attendee EE_Attendee */
2659
+		$att_check = $this->_registration->attendee();
2660
+		$attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2661
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2662
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2663
+		// primary registration object (that way we know if we need to show create button or not)
2664
+		if (! $this->_registration->is_primary_registrant()) {
2665
+			$primary_registration = $this->_registration->get_primary_registration();
2666
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2667
+				: null;
2668
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2669
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2670
+				// custom attendee object so let's not worry about the primary reg.
2671
+				$primary_registration = null;
2672
+			}
2673
+		} else {
2674
+			$primary_registration = null;
2675
+		}
2676
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2677
+		$this->_template_args['fname'] = $attendee->fname();
2678
+		$this->_template_args['lname'] = $attendee->lname();
2679
+		$this->_template_args['email'] = $attendee->email();
2680
+		$this->_template_args['phone'] = $attendee->phone();
2681
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2682
+		// edit link
2683
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2684
+			array(
2685
+				'action' => 'edit_attendee',
2686
+				'post'   => $attendee->ID(),
2687
+			),
2688
+			REG_ADMIN_URL
2689
+		);
2690
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2691
+		// create link
2692
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2693
+			? EE_Admin_Page::add_query_args_and_nonce(
2694
+				array(
2695
+					'action'  => 'duplicate_attendee',
2696
+					'_REG_ID' => $this->_registration->ID(),
2697
+				),
2698
+				REG_ADMIN_URL
2699
+			) : '';
2700
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2701
+		$this->_template_args['att_check'] = $att_check;
2702
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2703
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2704
+	}
2705
+
2706
+
2707
+	/**
2708
+	 * trash or restore registrations
2709
+	 *
2710
+	 * @param  boolean $trash whether to archive or restore
2711
+	 * @return void
2712
+	 * @throws EE_Error
2713
+	 * @throws InvalidArgumentException
2714
+	 * @throws InvalidDataTypeException
2715
+	 * @throws InvalidInterfaceException
2716
+	 * @throws RuntimeException
2717
+	 * @access protected
2718
+	 */
2719
+	protected function _trash_or_restore_registrations($trash = true)
2720
+	{
2721
+		// if empty _REG_ID then get out because there's nothing to do
2722
+		if (empty($this->_req_data['_REG_ID'])) {
2723
+			EE_Error::add_error(
2724
+				sprintf(
2725
+					esc_html__(
2726
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2727
+						'event_espresso'
2728
+					),
2729
+					$trash ? 'trash' : 'restore'
2730
+				),
2731
+				__FILE__,
2732
+				__LINE__,
2733
+				__FUNCTION__
2734
+			);
2735
+			$this->_redirect_after_action(false, '', '', array(), true);
2736
+		}
2737
+		$success = 0;
2738
+		$overwrite_msgs = false;
2739
+		// Checkboxes
2740
+		if (! is_array($this->_req_data['_REG_ID'])) {
2741
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2742
+		}
2743
+		$reg_count = count($this->_req_data['_REG_ID']);
2744
+		// cycle thru checkboxes
2745
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2746
+			/** @var EE_Registration $REG */
2747
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2748
+			$payments = $REG->registration_payments();
2749
+			if (! empty($payments)) {
2750
+				$name = $REG->attendee() instanceof EE_Attendee
2751
+					? $REG->attendee()->full_name()
2752
+					: esc_html__('Unknown Attendee', 'event_espresso');
2753
+				$overwrite_msgs = true;
2754
+				EE_Error::add_error(
2755
+					sprintf(
2756
+						esc_html__(
2757
+							'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.',
2758
+							'event_espresso'
2759
+						),
2760
+						$name
2761
+					),
2762
+					__FILE__,
2763
+					__FUNCTION__,
2764
+					__LINE__
2765
+				);
2766
+				// can't trash this registration because it has payments.
2767
+				continue;
2768
+			}
2769
+			$updated = $trash ? $REG->delete() : $REG->restore();
2770
+			if ($updated) {
2771
+				$success++;
2772
+			}
2773
+		}
2774
+		$this->_redirect_after_action(
2775
+			$success === $reg_count, // were ALL registrations affected?
2776
+			$success > 1
2777
+				? esc_html__('Registrations', 'event_espresso')
2778
+				: esc_html__('Registration', 'event_espresso'),
2779
+			$trash
2780
+				? esc_html__('moved to the trash', 'event_espresso')
2781
+				: esc_html__('restored', 'event_espresso'),
2782
+			array('action' => 'default'),
2783
+			$overwrite_msgs
2784
+		);
2785
+	}
2786
+
2787
+
2788
+	/**
2789
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2790
+	 * registration but also.
2791
+	 * 1. Removing relations to EE_Attendee
2792
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2793
+	 * ALSO trashed.
2794
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2795
+	 * 4. Removing relationships between all tickets and the related registrations
2796
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2797
+	 * 6. Deleting permanently any related Checkins.
2798
+	 *
2799
+	 * @return void
2800
+	 * @throws EE_Error
2801
+	 * @throws InvalidArgumentException
2802
+	 * @throws InvalidDataTypeException
2803
+	 * @throws InvalidInterfaceException
2804
+	 */
2805
+	protected function _delete_registrations()
2806
+	{
2807
+		$REG_MDL = EEM_Registration::instance();
2808
+		$success = 1;
2809
+		// Checkboxes
2810
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2811
+			// if array has more than one element than success message should be plural
2812
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2813
+			// cycle thru checkboxes
2814
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2815
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2816
+				if (! $REG instanceof EE_Registration) {
2817
+					continue;
2818
+				}
2819
+				$deleted = $this->_delete_registration($REG);
2820
+				if (! $deleted) {
2821
+					$success = 0;
2822
+				}
2823
+			}
2824
+		} else {
2825
+			// grab single id and delete
2826
+			$REG_ID = $this->_req_data['_REG_ID'];
2827
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2828
+			$deleted = $this->_delete_registration($REG);
2829
+			if (! $deleted) {
2830
+				$success = 0;
2831
+			}
2832
+		}
2833
+		$what = $success > 1
2834
+			? esc_html__('Registrations', 'event_espresso')
2835
+			: esc_html__('Registration', 'event_espresso');
2836
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2837
+		$this->_redirect_after_action(
2838
+			$success,
2839
+			$what,
2840
+			$action_desc,
2841
+			array('action' => 'default'),
2842
+			true
2843
+		);
2844
+	}
2845
+
2846
+
2847
+	/**
2848
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2849
+	 * models get affected.
2850
+	 *
2851
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2852
+	 * @return bool true = successful deletion, false = fail.
2853
+	 * @throws EE_Error
2854
+	 */
2855
+	protected function _delete_registration(EE_Registration $REG)
2856
+	{
2857
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2858
+		// registrations on the transaction that are NOT trashed.
2859
+		$TXN = $REG->get_first_related('Transaction');
2860
+		$REGS = $TXN->get_many_related('Registration');
2861
+		$all_trashed = true;
2862
+		foreach ($REGS as $registration) {
2863
+			if (! $registration->get('REG_deleted')) {
2864
+				$all_trashed = false;
2865
+			}
2866
+		}
2867
+		if (! $all_trashed) {
2868
+			EE_Error::add_error(
2869
+				esc_html__(
2870
+					'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.',
2871
+					'event_espresso'
2872
+				),
2873
+				__FILE__,
2874
+				__FUNCTION__,
2875
+				__LINE__
2876
+			);
2877
+			return false;
2878
+		}
2879
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2880
+		// separately from THIS one).
2881
+		foreach ($REGS as $registration) {
2882
+			// delete related answers
2883
+			$registration->delete_related_permanently('Answer');
2884
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2885
+			$attendee = $registration->get_first_related('Attendee');
2886
+			if ($attendee instanceof EE_Attendee) {
2887
+				$registration->_remove_relation_to($attendee, 'Attendee');
2888
+			}
2889
+			// now remove relationships to tickets on this registration.
2890
+			$registration->_remove_relations('Ticket');
2891
+			// now delete permanently the checkins related to this registration.
2892
+			$registration->delete_related_permanently('Checkin');
2893
+			if ($registration->ID() === $REG->ID()) {
2894
+				continue;
2895
+			} //we don't want to delete permanently the existing registration just yet.
2896
+			// remove relation to transaction for these registrations if NOT the existing registrations
2897
+			$registration->_remove_relations('Transaction');
2898
+			// delete permanently any related messages.
2899
+			$registration->delete_related_permanently('Message');
2900
+			// now delete this registration permanently
2901
+			$registration->delete_permanently();
2902
+		}
2903
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2904
+		// (the transaction and line items should be all that's left).
2905
+		// delete the line items related to the transaction for this registration.
2906
+		$TXN->delete_related_permanently('Line_Item');
2907
+		// we need to remove all the relationships on the transaction
2908
+		$TXN->delete_related_permanently('Payment');
2909
+		$TXN->delete_related_permanently('Extra_Meta');
2910
+		$TXN->delete_related_permanently('Message');
2911
+		// now we can delete this REG permanently (and the transaction of course)
2912
+		$REG->delete_related_permanently('Transaction');
2913
+		return $REG->delete_permanently();
2914
+	}
2915
+
2916
+
2917
+	/**
2918
+	 *    generates HTML for the Register New Attendee Admin page
2919
+	 *
2920
+	 * @access private
2921
+	 * @throws DomainException
2922
+	 * @throws EE_Error
2923
+	 */
2924
+	public function new_registration()
2925
+	{
2926
+		if (! $this->_set_reg_event()) {
2927
+			throw new EE_Error(
2928
+				esc_html__(
2929
+					'Unable to continue with registering because there is no Event ID in the request',
2930
+					'event_espresso'
2931
+				)
2932
+			);
2933
+		}
2934
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2935
+		// gotta start with a clean slate if we're not coming here via ajax
2936
+		if (! defined('DOING_AJAX')
2937
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2938
+		) {
2939
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2940
+		}
2941
+		$this->_template_args['event_name'] = '';
2942
+		// event name
2943
+		if ($this->_reg_event) {
2944
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2945
+			$edit_event_url = self::add_query_args_and_nonce(
2946
+				array(
2947
+					'action' => 'edit',
2948
+					'post'   => $this->_reg_event->ID(),
2949
+				),
2950
+				EVENTS_ADMIN_URL
2951
+			);
2952
+			$edit_event_lnk = '<a href="'
2953
+							  . $edit_event_url
2954
+							  . '" title="'
2955
+							  . esc_attr__('Edit ', 'event_espresso')
2956
+							  . $this->_reg_event->name()
2957
+							  . '">'
2958
+							  . esc_html__('Edit Event', 'event_espresso')
2959
+							  . '</a>';
2960
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2961
+												   . $edit_event_lnk
2962
+												   . '</span>';
2963
+		}
2964
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2965
+		if (defined('DOING_AJAX')) {
2966
+			$this->_return_json();
2967
+		}
2968
+		// grab header
2969
+		$template_path =
2970
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2971
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2972
+			$template_path,
2973
+			$this->_template_args,
2974
+			true
2975
+		);
2976
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2977
+		// the details template wrapper
2978
+		$this->display_admin_page_with_sidebar();
2979
+	}
2980
+
2981
+
2982
+	/**
2983
+	 * This returns the content for a registration step
2984
+	 *
2985
+	 * @access protected
2986
+	 * @return string html
2987
+	 * @throws DomainException
2988
+	 * @throws EE_Error
2989
+	 * @throws InvalidArgumentException
2990
+	 * @throws InvalidDataTypeException
2991
+	 * @throws InvalidInterfaceException
2992
+	 */
2993
+	protected function _get_registration_step_content()
2994
+	{
2995
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2996
+			$warning_msg = sprintf(
2997
+				esc_html__(
2998
+					'%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',
2999
+					'event_espresso'
3000
+				),
3001
+				'<br />',
3002
+				'<h3 class="important-notice">',
3003
+				'</h3>',
3004
+				'<div class="float-right">',
3005
+				'<span id="redirect_timer" class="important-notice">30</span>',
3006
+				'</div>',
3007
+				'<b>',
3008
+				'</b>'
3009
+			);
3010
+			return '
3011 3011
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3012 3012
 	<script >
3013 3013
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -3020,855 +3020,855 @@  discard block
 block discarded – undo
3020 3020
 	        }
3021 3021
 	    }, 800 );
3022 3022
 	</script >';
3023
-        }
3024
-        $template_args = array(
3025
-            'title'                    => '',
3026
-            'content'                  => '',
3027
-            'step_button_text'         => '',
3028
-            'show_notification_toggle' => false,
3029
-        );
3030
-        // to indicate we're processing a new registration
3031
-        $hidden_fields = array(
3032
-            'processing_registration' => array(
3033
-                'type'  => 'hidden',
3034
-                'value' => 0,
3035
-            ),
3036
-            'event_id'                => array(
3037
-                'type'  => 'hidden',
3038
-                'value' => $this->_reg_event->ID(),
3039
-            ),
3040
-        );
3041
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
3042
-        $cart = EE_Registry::instance()->SSN->cart();
3043
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3044
-        switch ($step) {
3045
-            case 'ticket':
3046
-                $hidden_fields['processing_registration']['value'] = 1;
3047
-                $template_args['title'] = esc_html__(
3048
-                    'Step One: Select the Ticket for this registration',
3049
-                    'event_espresso'
3050
-                );
3051
-                $template_args['content'] =
3052
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3053
-                $template_args['step_button_text'] = esc_html__(
3054
-                    'Add Tickets and Continue to Registrant Details',
3055
-                    'event_espresso'
3056
-                );
3057
-                $template_args['show_notification_toggle'] = false;
3058
-                break;
3059
-            case 'questions':
3060
-                $hidden_fields['processing_registration']['value'] = 2;
3061
-                $template_args['title'] = esc_html__(
3062
-                    'Step Two: Add Registrant Details for this Registration',
3063
-                    'event_espresso'
3064
-                );
3065
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3066
-                // properly by the first process_reg_step run.
3067
-                $template_args['content'] =
3068
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3069
-                $template_args['step_button_text'] = esc_html__(
3070
-                    'Save Registration and Continue to Details',
3071
-                    'event_espresso'
3072
-                );
3073
-                $template_args['show_notification_toggle'] = true;
3074
-                break;
3075
-        }
3076
-        // we come back to the process_registration_step route.
3077
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3078
-        return EEH_Template::display_template(
3079
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3080
-            $template_args,
3081
-            true
3082
-        );
3083
-    }
3084
-
3085
-
3086
-    /**
3087
-     *        set_reg_event
3088
-     *
3089
-     * @access private
3090
-     * @return bool
3091
-     * @throws EE_Error
3092
-     * @throws InvalidArgumentException
3093
-     * @throws InvalidDataTypeException
3094
-     * @throws InvalidInterfaceException
3095
-     */
3096
-    private function _set_reg_event()
3097
-    {
3098
-        if (is_object($this->_reg_event)) {
3099
-            return true;
3100
-        }
3101
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3102
-        if (! $EVT_ID) {
3103
-            return false;
3104
-        }
3105
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3106
-        return true;
3107
-    }
3108
-
3109
-
3110
-    /**
3111
-     * process_reg_step
3112
-     *
3113
-     * @access        public
3114
-     * @return string
3115
-     * @throws DomainException
3116
-     * @throws EE_Error
3117
-     * @throws InvalidArgumentException
3118
-     * @throws InvalidDataTypeException
3119
-     * @throws InvalidInterfaceException
3120
-     * @throws ReflectionException
3121
-     * @throws RuntimeException
3122
-     */
3123
-    public function process_reg_step()
3124
-    {
3125
-        EE_System::do_not_cache();
3126
-        $this->_set_reg_event();
3127
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3128
-        EE_Registry::instance()->REQ->set('uts', time());
3129
-        // what step are we on?
3130
-        $cart = EE_Registry::instance()->SSN->cart();
3131
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3132
-        // if doing ajax then we need to verify the nonce
3133
-        if (defined('DOING_AJAX')) {
3134
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3135
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3136
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3137
-        }
3138
-        switch ($step) {
3139
-            case 'ticket':
3140
-                // process ticket selection
3141
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3142
-                if ($success) {
3143
-                    EE_Error::add_success(
3144
-                        esc_html__(
3145
-                            'Tickets Selected. Now complete the registration.',
3146
-                            'event_espresso'
3147
-                        )
3148
-                    );
3149
-                } else {
3150
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3151
-                }
3152
-                if (defined('DOING_AJAX')) {
3153
-                    $this->new_registration(); // display next step
3154
-                } else {
3155
-                    $query_args = array(
3156
-                        'action'                  => 'new_registration',
3157
-                        'processing_registration' => 1,
3158
-                        'event_id'                => $this->_reg_event->ID(),
3159
-                        'uts'                     => time(),
3160
-                    );
3161
-                    $this->_redirect_after_action(
3162
-                        false,
3163
-                        '',
3164
-                        '',
3165
-                        $query_args,
3166
-                        true
3167
-                    );
3168
-                }
3169
-                break;
3170
-            case 'questions':
3171
-                if (! isset(
3172
-                    $this->_req_data['txn_reg_status_change'],
3173
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3174
-                )
3175
-                ) {
3176
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3177
-                }
3178
-                // process registration
3179
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3180
-                if ($cart instanceof EE_Cart) {
3181
-                    $grand_total = $cart->get_cart_grand_total();
3182
-                    if ($grand_total instanceof EE_Line_Item) {
3183
-                        $grand_total->save_this_and_descendants_to_txn();
3184
-                    }
3185
-                }
3186
-                if (! $transaction instanceof EE_Transaction) {
3187
-                    $query_args = array(
3188
-                        'action'                  => 'new_registration',
3189
-                        'processing_registration' => 2,
3190
-                        'event_id'                => $this->_reg_event->ID(),
3191
-                        'uts'                     => time(),
3192
-                    );
3193
-                    if (defined('DOING_AJAX')) {
3194
-                        // display registration form again because there are errors (maybe validation?)
3195
-                        $this->new_registration();
3196
-                        return;
3197
-                    } else {
3198
-                        $this->_redirect_after_action(
3199
-                            false,
3200
-                            '',
3201
-                            '',
3202
-                            $query_args,
3203
-                            true
3204
-                        );
3205
-                        return;
3206
-                    }
3207
-                }
3208
-                // maybe update status, and make sure to save transaction if not done already
3209
-                if (! $transaction->update_status_based_on_total_paid()) {
3210
-                    $transaction->save();
3211
-                }
3212
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3213
-                $this->_req_data = array();
3214
-                $query_args = array(
3215
-                    'action'        => 'redirect_to_txn',
3216
-                    'TXN_ID'        => $transaction->ID(),
3217
-                    'EVT_ID'        => $this->_reg_event->ID(),
3218
-                    'event_name'    => urlencode($this->_reg_event->name()),
3219
-                    'redirect_from' => 'new_registration',
3220
-                );
3221
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3222
-                break;
3223
-        }
3224
-        // what are you looking here for?  Should be nothing to do at this point.
3225
-    }
3226
-
3227
-
3228
-    /**
3229
-     * redirect_to_txn
3230
-     *
3231
-     * @access public
3232
-     * @return void
3233
-     * @throws EE_Error
3234
-     * @throws InvalidArgumentException
3235
-     * @throws InvalidDataTypeException
3236
-     * @throws InvalidInterfaceException
3237
-     */
3238
-    public function redirect_to_txn()
3239
-    {
3240
-        EE_System::do_not_cache();
3241
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3242
-        $query_args = array(
3243
-            'action' => 'view_transaction',
3244
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3245
-            'page'   => 'espresso_transactions',
3246
-        );
3247
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3248
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3249
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3250
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3251
-        }
3252
-        EE_Error::add_success(
3253
-            esc_html__(
3254
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3255
-                'event_espresso'
3256
-            )
3257
-        );
3258
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3259
-    }
3260
-
3261
-
3262
-    /**
3263
-     *        generates HTML for the Attendee Contact List
3264
-     *
3265
-     * @access protected
3266
-     * @return void
3267
-     */
3268
-    protected function _attendee_contact_list_table()
3269
-    {
3270
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3271
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3272
-        $this->display_admin_list_table_page_with_no_sidebar();
3273
-    }
3274
-
3275
-
3276
-    /**
3277
-     *        get_attendees
3278
-     *
3279
-     * @param      $per_page
3280
-     * @param bool $count whether to return count or data.
3281
-     * @param bool $trash
3282
-     * @return array
3283
-     * @throws EE_Error
3284
-     * @throws InvalidArgumentException
3285
-     * @throws InvalidDataTypeException
3286
-     * @throws InvalidInterfaceException
3287
-     * @access public
3288
-     */
3289
-    public function get_attendees($per_page, $count = false, $trash = false)
3290
-    {
3291
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3292
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3293
-        $ATT_MDL = EEM_Attendee::instance();
3294
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3295
-        switch ($this->_req_data['orderby']) {
3296
-            case 'ATT_ID':
3297
-                $orderby = 'ATT_ID';
3298
-                break;
3299
-            case 'ATT_fname':
3300
-                $orderby = 'ATT_fname';
3301
-                break;
3302
-            case 'ATT_email':
3303
-                $orderby = 'ATT_email';
3304
-                break;
3305
-            case 'ATT_city':
3306
-                $orderby = 'ATT_city';
3307
-                break;
3308
-            case 'STA_ID':
3309
-                $orderby = 'STA_ID';
3310
-                break;
3311
-            case 'CNT_ID':
3312
-                $orderby = 'CNT_ID';
3313
-                break;
3314
-            case 'Registration_Count':
3315
-                $orderby = 'Registration_Count';
3316
-                break;
3317
-            default:
3318
-                $orderby = 'ATT_lname';
3319
-        }
3320
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3321
-            ? $this->_req_data['order']
3322
-            : 'ASC';
3323
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3324
-            ? $this->_req_data['paged']
3325
-            : 1;
3326
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3327
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3328
-            ? $this->_req_data['perpage']
3329
-            : $per_page;
3330
-        $_where = array();
3331
-        if (! empty($this->_req_data['s'])) {
3332
-            $sstr = '%' . $this->_req_data['s'] . '%';
3333
-            $_where['OR'] = array(
3334
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3335
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3336
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3337
-                'ATT_fname'                         => array('LIKE', $sstr),
3338
-                'ATT_lname'                         => array('LIKE', $sstr),
3339
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3340
-                'ATT_email'                         => array('LIKE', $sstr),
3341
-                'ATT_address'                       => array('LIKE', $sstr),
3342
-                'ATT_address2'                      => array('LIKE', $sstr),
3343
-                'ATT_city'                          => array('LIKE', $sstr),
3344
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3345
-                'State.STA_name'                    => array('LIKE', $sstr),
3346
-                'ATT_phone'                         => array('LIKE', $sstr),
3347
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3348
-                'Registration.REG_code'             => array('LIKE', $sstr),
3349
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3350
-            );
3351
-        }
3352
-        $offset = ($current_page - 1) * $per_page;
3353
-        $limit = $count ? null : array($offset, $per_page);
3354
-        $query_args = array(
3355
-            $_where,
3356
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3357
-            'limit'         => $limit,
3358
-        );
3359
-        if (! $count) {
3360
-            $query_args['order_by'] = array($orderby => $sort);
3361
-        }
3362
-        if ($trash) {
3363
-            $query_args[0]['status'] = array('!=', 'publish');
3364
-            $all_attendees = $count
3365
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3366
-                : $ATT_MDL->get_all($query_args);
3367
-        } else {
3368
-            $query_args[0]['status'] = array('IN', array('publish'));
3369
-            $all_attendees = $count
3370
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3371
-                : $ATT_MDL->get_all($query_args);
3372
-        }
3373
-        return $all_attendees;
3374
-    }
3375
-
3376
-
3377
-    /**
3378
-     * This is just taking care of resending the registration confirmation
3379
-     *
3380
-     * @access protected
3381
-     * @return void
3382
-     */
3383
-    protected function _resend_registration()
3384
-    {
3385
-        $this->_process_resend_registration();
3386
-        $query_args = isset($this->_req_data['redirect_to'])
3387
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3388
-            : array('action' => 'default');
3389
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3390
-    }
3391
-
3392
-    /**
3393
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3394
-     * to use when selecting registrations
3395
-     *
3396
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3397
-     *                                                     the query parameters from the request
3398
-     * @return void ends the request with a redirect or download
3399
-     */
3400
-    public function _registrations_report_base($method_name_for_getting_query_params)
3401
-    {
3402
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3403
-            wp_redirect(
3404
-                EE_Admin_Page::add_query_args_and_nonce(
3405
-                    array(
3406
-                        'page'        => 'espresso_batch',
3407
-                        'batch'       => 'file',
3408
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3409
-                        'filters'     => urlencode(
3410
-                            serialize(
3411
-                                call_user_func(
3412
-                                    array($this, $method_name_for_getting_query_params),
3413
-                                    EEH_Array::is_set(
3414
-                                        $this->_req_data,
3415
-                                        'filters',
3416
-                                        array()
3417
-                                    )
3418
-                                )
3419
-                            )
3420
-                        ),
3421
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3422
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3423
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3424
-                    )
3425
-                )
3426
-            );
3427
-        } else {
3428
-            $new_request_args = array(
3429
-                'export' => 'report',
3430
-                'action' => 'registrations_report_for_event',
3431
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3432
-            );
3433
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3434
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3435
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3436
-                $EE_Export = EE_Export::instance($this->_req_data);
3437
-                $EE_Export->export();
3438
-            }
3439
-        }
3440
-    }
3441
-
3442
-
3443
-    /**
3444
-     * Creates a registration report using only query parameters in the request
3445
-     *
3446
-     * @return void
3447
-     */
3448
-    public function _registrations_report()
3449
-    {
3450
-        $this->_registrations_report_base('_get_registration_query_parameters');
3451
-    }
3452
-
3453
-
3454
-    public function _contact_list_export()
3455
-    {
3456
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3457
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3458
-            $EE_Export = EE_Export::instance($this->_req_data);
3459
-            $EE_Export->export_attendees();
3460
-        }
3461
-    }
3462
-
3463
-
3464
-    public function _contact_list_report()
3465
-    {
3466
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3467
-            wp_redirect(
3468
-                EE_Admin_Page::add_query_args_and_nonce(
3469
-                    array(
3470
-                        'page'        => 'espresso_batch',
3471
-                        'batch'       => 'file',
3472
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3473
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3474
-                    )
3475
-                )
3476
-            );
3477
-        } else {
3478
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3479
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3480
-                $EE_Export = EE_Export::instance($this->_req_data);
3481
-                $EE_Export->report_attendees();
3482
-            }
3483
-        }
3484
-    }
3485
-
3486
-
3487
-
3488
-
3489
-
3490
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3491
-    /**
3492
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3493
-     *
3494
-     * @return void
3495
-     * @throws EE_Error
3496
-     * @throws InvalidArgumentException
3497
-     * @throws InvalidDataTypeException
3498
-     * @throws InvalidInterfaceException
3499
-     */
3500
-    protected function _duplicate_attendee()
3501
-    {
3502
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3503
-        // verify we have necessary info
3504
-        if (empty($this->_req_data['_REG_ID'])) {
3505
-            EE_Error::add_error(
3506
-                esc_html__(
3507
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3508
-                    'event_espresso'
3509
-                ),
3510
-                __FILE__,
3511
-                __LINE__,
3512
-                __FUNCTION__
3513
-            );
3514
-            $query_args = array('action' => $action);
3515
-            $this->_redirect_after_action('', '', '', $query_args, true);
3516
-        }
3517
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3518
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3519
-        $attendee = $registration->attendee();
3520
-        // remove relation of existing attendee on registration
3521
-        $registration->_remove_relation_to($attendee, 'Attendee');
3522
-        // new attendee
3523
-        $new_attendee = clone $attendee;
3524
-        $new_attendee->set('ATT_ID', 0);
3525
-        $new_attendee->save();
3526
-        // add new attendee to reg
3527
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3528
-        EE_Error::add_success(
3529
-            esc_html__(
3530
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3531
-                'event_espresso'
3532
-            )
3533
-        );
3534
-        // redirect to edit page for attendee
3535
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3536
-        $this->_redirect_after_action('', '', '', $query_args, true);
3537
-    }
3538
-
3539
-
3540
-    /**
3541
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3542
-     *
3543
-     * @param int     $post_id
3544
-     * @param WP_POST $post
3545
-     * @throws DomainException
3546
-     * @throws EE_Error
3547
-     * @throws InvalidArgumentException
3548
-     * @throws InvalidDataTypeException
3549
-     * @throws InvalidInterfaceException
3550
-     * @throws LogicException
3551
-     * @throws InvalidFormSubmissionException
3552
-     */
3553
-    protected function _insert_update_cpt_item($post_id, $post)
3554
-    {
3555
-        $success = true;
3556
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3557
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3558
-            : null;
3559
-        // for attendee updates
3560
-        if ($attendee instanceof EE_Attendee) {
3561
-            // note we should only be UPDATING attendees at this point.
3562
-            $updated_fields = array(
3563
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3564
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3565
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3566
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3567
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3568
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3569
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3570
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3571
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3572
-            );
3573
-            foreach ($updated_fields as $field => $value) {
3574
-                $attendee->set($field, $value);
3575
-            }
3576
-
3577
-            // process contact details metabox form handler (which will also save the attendee)
3578
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3579
-            $success = $contact_details_form->process($this->_req_data);
3580
-
3581
-            $attendee_update_callbacks = apply_filters(
3582
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3583
-                array()
3584
-            );
3585
-            foreach ($attendee_update_callbacks as $a_callback) {
3586
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3587
-                    throw new EE_Error(
3588
-                        sprintf(
3589
-                            esc_html__(
3590
-                                '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.',
3591
-                                'event_espresso'
3592
-                            ),
3593
-                            $a_callback
3594
-                        )
3595
-                    );
3596
-                }
3597
-            }
3598
-        }
3599
-
3600
-        if ($success === false) {
3601
-            EE_Error::add_error(
3602
-                esc_html__(
3603
-                    'Something went wrong with updating the meta table data for the registration.',
3604
-                    'event_espresso'
3605
-                ),
3606
-                __FILE__,
3607
-                __FUNCTION__,
3608
-                __LINE__
3609
-            );
3610
-        }
3611
-    }
3612
-
3613
-
3614
-    public function trash_cpt_item($post_id)
3615
-    {
3616
-    }
3617
-
3618
-
3619
-    public function delete_cpt_item($post_id)
3620
-    {
3621
-    }
3622
-
3623
-
3624
-    public function restore_cpt_item($post_id)
3625
-    {
3626
-    }
3627
-
3628
-
3629
-    protected function _restore_cpt_item($post_id, $revision_id)
3630
-    {
3631
-    }
3632
-
3633
-
3634
-    public function attendee_editor_metaboxes()
3635
-    {
3636
-        $this->verify_cpt_object();
3637
-        remove_meta_box(
3638
-            'postexcerpt',
3639
-            esc_html__('Excerpt', 'event_espresso'),
3640
-            'post_excerpt_meta_box',
3641
-            $this->_cpt_routes[ $this->_req_action ],
3642
-            'normal',
3643
-            'core'
3644
-        );
3645
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3646
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3647
-            add_meta_box(
3648
-                'postexcerpt',
3649
-                esc_html__('Short Biography', 'event_espresso'),
3650
-                'post_excerpt_meta_box',
3651
-                $this->_cpt_routes[ $this->_req_action ],
3652
-                'normal'
3653
-            );
3654
-        }
3655
-        if (post_type_supports('espresso_attendees', 'comments')) {
3656
-            add_meta_box(
3657
-                'commentsdiv',
3658
-                esc_html__('Notes on the Contact', 'event_espresso'),
3659
-                'post_comment_meta_box',
3660
-                $this->_cpt_routes[ $this->_req_action ],
3661
-                'normal',
3662
-                'core'
3663
-            );
3664
-        }
3665
-        add_meta_box(
3666
-            'attendee_contact_info',
3667
-            esc_html__('Contact Info', 'event_espresso'),
3668
-            array($this, 'attendee_contact_info'),
3669
-            $this->_cpt_routes[ $this->_req_action ],
3670
-            'side',
3671
-            'core'
3672
-        );
3673
-        add_meta_box(
3674
-            'attendee_details_address',
3675
-            esc_html__('Address Details', 'event_espresso'),
3676
-            array($this, 'attendee_address_details'),
3677
-            $this->_cpt_routes[ $this->_req_action ],
3678
-            'normal',
3679
-            'core'
3680
-        );
3681
-        add_meta_box(
3682
-            'attendee_registrations',
3683
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3684
-            array($this, 'attendee_registrations_meta_box'),
3685
-            $this->_cpt_routes[ $this->_req_action ],
3686
-            'normal',
3687
-            'high'
3688
-        );
3689
-    }
3690
-
3691
-
3692
-    /**
3693
-     * Metabox for attendee contact info
3694
-     *
3695
-     * @param  WP_Post $post wp post object
3696
-     * @return string attendee contact info ( and form )
3697
-     * @throws EE_Error
3698
-     * @throws InvalidArgumentException
3699
-     * @throws InvalidDataTypeException
3700
-     * @throws InvalidInterfaceException
3701
-     * @throws LogicException
3702
-     * @throws DomainException
3703
-     */
3704
-    public function attendee_contact_info($post)
3705
-    {
3706
-        // get attendee object ( should already have it )
3707
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3708
-        $form->enqueueStylesAndScripts();
3709
-        echo $form->display();
3710
-    }
3711
-
3712
-
3713
-    /**
3714
-     * Return form handler for the contact details metabox
3715
-     *
3716
-     * @param EE_Attendee $attendee
3717
-     * @return AttendeeContactDetailsMetaboxFormHandler
3718
-     * @throws DomainException
3719
-     * @throws InvalidArgumentException
3720
-     * @throws InvalidDataTypeException
3721
-     * @throws InvalidInterfaceException
3722
-     */
3723
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3724
-    {
3725
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3726
-    }
3727
-
3728
-
3729
-    /**
3730
-     * Metabox for attendee details
3731
-     *
3732
-     * @param  WP_Post $post wp post object
3733
-     * @throws DomainException
3734
-     */
3735
-    public function attendee_address_details($post)
3736
-    {
3737
-        // get attendee object (should already have it)
3738
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3739
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3740
-            new EE_Question_Form_Input(
3741
-                EE_Question::new_instance(
3742
-                    array(
3743
-                        'QST_ID'           => 0,
3744
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3745
-                        'QST_system'       => 'admin-state',
3746
-                    )
3747
-                ),
3748
-                EE_Answer::new_instance(
3749
-                    array(
3750
-                        'ANS_ID'    => 0,
3751
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3752
-                    )
3753
-                ),
3754
-                array(
3755
-                    'input_id'       => 'STA_ID',
3756
-                    'input_name'     => 'STA_ID',
3757
-                    'input_prefix'   => '',
3758
-                    'append_qstn_id' => false,
3759
-                )
3760
-            )
3761
-        );
3762
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3763
-            new EE_Question_Form_Input(
3764
-                EE_Question::new_instance(
3765
-                    array(
3766
-                        'QST_ID'           => 0,
3767
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3768
-                        'QST_system'       => 'admin-country',
3769
-                    )
3770
-                ),
3771
-                EE_Answer::new_instance(
3772
-                    array(
3773
-                        'ANS_ID'    => 0,
3774
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3775
-                    )
3776
-                ),
3777
-                array(
3778
-                    'input_id'       => 'CNT_ISO',
3779
-                    'input_name'     => 'CNT_ISO',
3780
-                    'input_prefix'   => '',
3781
-                    'append_qstn_id' => false,
3782
-                )
3783
-            )
3784
-        );
3785
-        $template =
3786
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3787
-        EEH_Template::display_template($template, $this->_template_args);
3788
-    }
3789
-
3790
-
3791
-    /**
3792
-     *        _attendee_details
3793
-     *
3794
-     * @access protected
3795
-     * @param $post
3796
-     * @return void
3797
-     * @throws DomainException
3798
-     * @throws EE_Error
3799
-     */
3800
-    public function attendee_registrations_meta_box($post)
3801
-    {
3802
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3803
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3804
-        $template =
3805
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3806
-        EEH_Template::display_template($template, $this->_template_args);
3807
-    }
3808
-
3809
-
3810
-    /**
3811
-     * add in the form fields for the attendee edit
3812
-     *
3813
-     * @param  WP_Post $post wp post object
3814
-     * @return string html for new form.
3815
-     * @throws DomainException
3816
-     */
3817
-    public function after_title_form_fields($post)
3818
-    {
3819
-        if ($post->post_type == 'espresso_attendees') {
3820
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3821
-            $template_args['attendee'] = $this->_cpt_model_obj;
3822
-            EEH_Template::display_template($template, $template_args);
3823
-        }
3824
-    }
3825
-
3826
-
3827
-    /**
3828
-     *        _trash_or_restore_attendee
3829
-     *
3830
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3831
-     * @return void
3832
-     * @throws EE_Error
3833
-     * @throws InvalidArgumentException
3834
-     * @throws InvalidDataTypeException
3835
-     * @throws InvalidInterfaceException
3836
-     * @access protected
3837
-     */
3838
-    protected function _trash_or_restore_attendees($trash = true)
3839
-    {
3840
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3841
-        $ATT_MDL = EEM_Attendee::instance();
3842
-        $success = 1;
3843
-        // Checkboxes
3844
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3845
-            // if array has more than one element than success message should be plural
3846
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3847
-            // cycle thru checkboxes
3848
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3849
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3850
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3851
-                if (! $updated) {
3852
-                    $success = 0;
3853
-                }
3854
-            }
3855
-        } else {
3856
-            // grab single id and delete
3857
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3858
-            // get attendee
3859
-            $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3860
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3861
-            $updated = $att->save();
3862
-            if (! $updated) {
3863
-                $success = 0;
3864
-            }
3865
-        }
3866
-        $what = $success > 1
3867
-            ? esc_html__('Contacts', 'event_espresso')
3868
-            : esc_html__('Contact', 'event_espresso');
3869
-        $action_desc = $trash
3870
-            ? esc_html__('moved to the trash', 'event_espresso')
3871
-            : esc_html__('restored', 'event_espresso');
3872
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3873
-    }
3023
+		}
3024
+		$template_args = array(
3025
+			'title'                    => '',
3026
+			'content'                  => '',
3027
+			'step_button_text'         => '',
3028
+			'show_notification_toggle' => false,
3029
+		);
3030
+		// to indicate we're processing a new registration
3031
+		$hidden_fields = array(
3032
+			'processing_registration' => array(
3033
+				'type'  => 'hidden',
3034
+				'value' => 0,
3035
+			),
3036
+			'event_id'                => array(
3037
+				'type'  => 'hidden',
3038
+				'value' => $this->_reg_event->ID(),
3039
+			),
3040
+		);
3041
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
3042
+		$cart = EE_Registry::instance()->SSN->cart();
3043
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3044
+		switch ($step) {
3045
+			case 'ticket':
3046
+				$hidden_fields['processing_registration']['value'] = 1;
3047
+				$template_args['title'] = esc_html__(
3048
+					'Step One: Select the Ticket for this registration',
3049
+					'event_espresso'
3050
+				);
3051
+				$template_args['content'] =
3052
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3053
+				$template_args['step_button_text'] = esc_html__(
3054
+					'Add Tickets and Continue to Registrant Details',
3055
+					'event_espresso'
3056
+				);
3057
+				$template_args['show_notification_toggle'] = false;
3058
+				break;
3059
+			case 'questions':
3060
+				$hidden_fields['processing_registration']['value'] = 2;
3061
+				$template_args['title'] = esc_html__(
3062
+					'Step Two: Add Registrant Details for this Registration',
3063
+					'event_espresso'
3064
+				);
3065
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3066
+				// properly by the first process_reg_step run.
3067
+				$template_args['content'] =
3068
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3069
+				$template_args['step_button_text'] = esc_html__(
3070
+					'Save Registration and Continue to Details',
3071
+					'event_espresso'
3072
+				);
3073
+				$template_args['show_notification_toggle'] = true;
3074
+				break;
3075
+		}
3076
+		// we come back to the process_registration_step route.
3077
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3078
+		return EEH_Template::display_template(
3079
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3080
+			$template_args,
3081
+			true
3082
+		);
3083
+	}
3084
+
3085
+
3086
+	/**
3087
+	 *        set_reg_event
3088
+	 *
3089
+	 * @access private
3090
+	 * @return bool
3091
+	 * @throws EE_Error
3092
+	 * @throws InvalidArgumentException
3093
+	 * @throws InvalidDataTypeException
3094
+	 * @throws InvalidInterfaceException
3095
+	 */
3096
+	private function _set_reg_event()
3097
+	{
3098
+		if (is_object($this->_reg_event)) {
3099
+			return true;
3100
+		}
3101
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3102
+		if (! $EVT_ID) {
3103
+			return false;
3104
+		}
3105
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3106
+		return true;
3107
+	}
3108
+
3109
+
3110
+	/**
3111
+	 * process_reg_step
3112
+	 *
3113
+	 * @access        public
3114
+	 * @return string
3115
+	 * @throws DomainException
3116
+	 * @throws EE_Error
3117
+	 * @throws InvalidArgumentException
3118
+	 * @throws InvalidDataTypeException
3119
+	 * @throws InvalidInterfaceException
3120
+	 * @throws ReflectionException
3121
+	 * @throws RuntimeException
3122
+	 */
3123
+	public function process_reg_step()
3124
+	{
3125
+		EE_System::do_not_cache();
3126
+		$this->_set_reg_event();
3127
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3128
+		EE_Registry::instance()->REQ->set('uts', time());
3129
+		// what step are we on?
3130
+		$cart = EE_Registry::instance()->SSN->cart();
3131
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3132
+		// if doing ajax then we need to verify the nonce
3133
+		if (defined('DOING_AJAX')) {
3134
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3135
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3136
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3137
+		}
3138
+		switch ($step) {
3139
+			case 'ticket':
3140
+				// process ticket selection
3141
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3142
+				if ($success) {
3143
+					EE_Error::add_success(
3144
+						esc_html__(
3145
+							'Tickets Selected. Now complete the registration.',
3146
+							'event_espresso'
3147
+						)
3148
+					);
3149
+				} else {
3150
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3151
+				}
3152
+				if (defined('DOING_AJAX')) {
3153
+					$this->new_registration(); // display next step
3154
+				} else {
3155
+					$query_args = array(
3156
+						'action'                  => 'new_registration',
3157
+						'processing_registration' => 1,
3158
+						'event_id'                => $this->_reg_event->ID(),
3159
+						'uts'                     => time(),
3160
+					);
3161
+					$this->_redirect_after_action(
3162
+						false,
3163
+						'',
3164
+						'',
3165
+						$query_args,
3166
+						true
3167
+					);
3168
+				}
3169
+				break;
3170
+			case 'questions':
3171
+				if (! isset(
3172
+					$this->_req_data['txn_reg_status_change'],
3173
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3174
+				)
3175
+				) {
3176
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3177
+				}
3178
+				// process registration
3179
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3180
+				if ($cart instanceof EE_Cart) {
3181
+					$grand_total = $cart->get_cart_grand_total();
3182
+					if ($grand_total instanceof EE_Line_Item) {
3183
+						$grand_total->save_this_and_descendants_to_txn();
3184
+					}
3185
+				}
3186
+				if (! $transaction instanceof EE_Transaction) {
3187
+					$query_args = array(
3188
+						'action'                  => 'new_registration',
3189
+						'processing_registration' => 2,
3190
+						'event_id'                => $this->_reg_event->ID(),
3191
+						'uts'                     => time(),
3192
+					);
3193
+					if (defined('DOING_AJAX')) {
3194
+						// display registration form again because there are errors (maybe validation?)
3195
+						$this->new_registration();
3196
+						return;
3197
+					} else {
3198
+						$this->_redirect_after_action(
3199
+							false,
3200
+							'',
3201
+							'',
3202
+							$query_args,
3203
+							true
3204
+						);
3205
+						return;
3206
+					}
3207
+				}
3208
+				// maybe update status, and make sure to save transaction if not done already
3209
+				if (! $transaction->update_status_based_on_total_paid()) {
3210
+					$transaction->save();
3211
+				}
3212
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3213
+				$this->_req_data = array();
3214
+				$query_args = array(
3215
+					'action'        => 'redirect_to_txn',
3216
+					'TXN_ID'        => $transaction->ID(),
3217
+					'EVT_ID'        => $this->_reg_event->ID(),
3218
+					'event_name'    => urlencode($this->_reg_event->name()),
3219
+					'redirect_from' => 'new_registration',
3220
+				);
3221
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3222
+				break;
3223
+		}
3224
+		// what are you looking here for?  Should be nothing to do at this point.
3225
+	}
3226
+
3227
+
3228
+	/**
3229
+	 * redirect_to_txn
3230
+	 *
3231
+	 * @access public
3232
+	 * @return void
3233
+	 * @throws EE_Error
3234
+	 * @throws InvalidArgumentException
3235
+	 * @throws InvalidDataTypeException
3236
+	 * @throws InvalidInterfaceException
3237
+	 */
3238
+	public function redirect_to_txn()
3239
+	{
3240
+		EE_System::do_not_cache();
3241
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3242
+		$query_args = array(
3243
+			'action' => 'view_transaction',
3244
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3245
+			'page'   => 'espresso_transactions',
3246
+		);
3247
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3248
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3249
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3250
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3251
+		}
3252
+		EE_Error::add_success(
3253
+			esc_html__(
3254
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3255
+				'event_espresso'
3256
+			)
3257
+		);
3258
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3259
+	}
3260
+
3261
+
3262
+	/**
3263
+	 *        generates HTML for the Attendee Contact List
3264
+	 *
3265
+	 * @access protected
3266
+	 * @return void
3267
+	 */
3268
+	protected function _attendee_contact_list_table()
3269
+	{
3270
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3271
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3272
+		$this->display_admin_list_table_page_with_no_sidebar();
3273
+	}
3274
+
3275
+
3276
+	/**
3277
+	 *        get_attendees
3278
+	 *
3279
+	 * @param      $per_page
3280
+	 * @param bool $count whether to return count or data.
3281
+	 * @param bool $trash
3282
+	 * @return array
3283
+	 * @throws EE_Error
3284
+	 * @throws InvalidArgumentException
3285
+	 * @throws InvalidDataTypeException
3286
+	 * @throws InvalidInterfaceException
3287
+	 * @access public
3288
+	 */
3289
+	public function get_attendees($per_page, $count = false, $trash = false)
3290
+	{
3291
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3292
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3293
+		$ATT_MDL = EEM_Attendee::instance();
3294
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3295
+		switch ($this->_req_data['orderby']) {
3296
+			case 'ATT_ID':
3297
+				$orderby = 'ATT_ID';
3298
+				break;
3299
+			case 'ATT_fname':
3300
+				$orderby = 'ATT_fname';
3301
+				break;
3302
+			case 'ATT_email':
3303
+				$orderby = 'ATT_email';
3304
+				break;
3305
+			case 'ATT_city':
3306
+				$orderby = 'ATT_city';
3307
+				break;
3308
+			case 'STA_ID':
3309
+				$orderby = 'STA_ID';
3310
+				break;
3311
+			case 'CNT_ID':
3312
+				$orderby = 'CNT_ID';
3313
+				break;
3314
+			case 'Registration_Count':
3315
+				$orderby = 'Registration_Count';
3316
+				break;
3317
+			default:
3318
+				$orderby = 'ATT_lname';
3319
+		}
3320
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3321
+			? $this->_req_data['order']
3322
+			: 'ASC';
3323
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3324
+			? $this->_req_data['paged']
3325
+			: 1;
3326
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3327
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3328
+			? $this->_req_data['perpage']
3329
+			: $per_page;
3330
+		$_where = array();
3331
+		if (! empty($this->_req_data['s'])) {
3332
+			$sstr = '%' . $this->_req_data['s'] . '%';
3333
+			$_where['OR'] = array(
3334
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3335
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3336
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3337
+				'ATT_fname'                         => array('LIKE', $sstr),
3338
+				'ATT_lname'                         => array('LIKE', $sstr),
3339
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3340
+				'ATT_email'                         => array('LIKE', $sstr),
3341
+				'ATT_address'                       => array('LIKE', $sstr),
3342
+				'ATT_address2'                      => array('LIKE', $sstr),
3343
+				'ATT_city'                          => array('LIKE', $sstr),
3344
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3345
+				'State.STA_name'                    => array('LIKE', $sstr),
3346
+				'ATT_phone'                         => array('LIKE', $sstr),
3347
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3348
+				'Registration.REG_code'             => array('LIKE', $sstr),
3349
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3350
+			);
3351
+		}
3352
+		$offset = ($current_page - 1) * $per_page;
3353
+		$limit = $count ? null : array($offset, $per_page);
3354
+		$query_args = array(
3355
+			$_where,
3356
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3357
+			'limit'         => $limit,
3358
+		);
3359
+		if (! $count) {
3360
+			$query_args['order_by'] = array($orderby => $sort);
3361
+		}
3362
+		if ($trash) {
3363
+			$query_args[0]['status'] = array('!=', 'publish');
3364
+			$all_attendees = $count
3365
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3366
+				: $ATT_MDL->get_all($query_args);
3367
+		} else {
3368
+			$query_args[0]['status'] = array('IN', array('publish'));
3369
+			$all_attendees = $count
3370
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3371
+				: $ATT_MDL->get_all($query_args);
3372
+		}
3373
+		return $all_attendees;
3374
+	}
3375
+
3376
+
3377
+	/**
3378
+	 * This is just taking care of resending the registration confirmation
3379
+	 *
3380
+	 * @access protected
3381
+	 * @return void
3382
+	 */
3383
+	protected function _resend_registration()
3384
+	{
3385
+		$this->_process_resend_registration();
3386
+		$query_args = isset($this->_req_data['redirect_to'])
3387
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3388
+			: array('action' => 'default');
3389
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3390
+	}
3391
+
3392
+	/**
3393
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3394
+	 * to use when selecting registrations
3395
+	 *
3396
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3397
+	 *                                                     the query parameters from the request
3398
+	 * @return void ends the request with a redirect or download
3399
+	 */
3400
+	public function _registrations_report_base($method_name_for_getting_query_params)
3401
+	{
3402
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3403
+			wp_redirect(
3404
+				EE_Admin_Page::add_query_args_and_nonce(
3405
+					array(
3406
+						'page'        => 'espresso_batch',
3407
+						'batch'       => 'file',
3408
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3409
+						'filters'     => urlencode(
3410
+							serialize(
3411
+								call_user_func(
3412
+									array($this, $method_name_for_getting_query_params),
3413
+									EEH_Array::is_set(
3414
+										$this->_req_data,
3415
+										'filters',
3416
+										array()
3417
+									)
3418
+								)
3419
+							)
3420
+						),
3421
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3422
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3423
+						'return_url'  => urlencode($this->_req_data['return_url']),
3424
+					)
3425
+				)
3426
+			);
3427
+		} else {
3428
+			$new_request_args = array(
3429
+				'export' => 'report',
3430
+				'action' => 'registrations_report_for_event',
3431
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3432
+			);
3433
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3434
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3435
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3436
+				$EE_Export = EE_Export::instance($this->_req_data);
3437
+				$EE_Export->export();
3438
+			}
3439
+		}
3440
+	}
3441
+
3442
+
3443
+	/**
3444
+	 * Creates a registration report using only query parameters in the request
3445
+	 *
3446
+	 * @return void
3447
+	 */
3448
+	public function _registrations_report()
3449
+	{
3450
+		$this->_registrations_report_base('_get_registration_query_parameters');
3451
+	}
3452
+
3453
+
3454
+	public function _contact_list_export()
3455
+	{
3456
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3457
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3458
+			$EE_Export = EE_Export::instance($this->_req_data);
3459
+			$EE_Export->export_attendees();
3460
+		}
3461
+	}
3462
+
3463
+
3464
+	public function _contact_list_report()
3465
+	{
3466
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3467
+			wp_redirect(
3468
+				EE_Admin_Page::add_query_args_and_nonce(
3469
+					array(
3470
+						'page'        => 'espresso_batch',
3471
+						'batch'       => 'file',
3472
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3473
+						'return_url'  => urlencode($this->_req_data['return_url']),
3474
+					)
3475
+				)
3476
+			);
3477
+		} else {
3478
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3479
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3480
+				$EE_Export = EE_Export::instance($this->_req_data);
3481
+				$EE_Export->report_attendees();
3482
+			}
3483
+		}
3484
+	}
3485
+
3486
+
3487
+
3488
+
3489
+
3490
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3491
+	/**
3492
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3493
+	 *
3494
+	 * @return void
3495
+	 * @throws EE_Error
3496
+	 * @throws InvalidArgumentException
3497
+	 * @throws InvalidDataTypeException
3498
+	 * @throws InvalidInterfaceException
3499
+	 */
3500
+	protected function _duplicate_attendee()
3501
+	{
3502
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3503
+		// verify we have necessary info
3504
+		if (empty($this->_req_data['_REG_ID'])) {
3505
+			EE_Error::add_error(
3506
+				esc_html__(
3507
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3508
+					'event_espresso'
3509
+				),
3510
+				__FILE__,
3511
+				__LINE__,
3512
+				__FUNCTION__
3513
+			);
3514
+			$query_args = array('action' => $action);
3515
+			$this->_redirect_after_action('', '', '', $query_args, true);
3516
+		}
3517
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3518
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3519
+		$attendee = $registration->attendee();
3520
+		// remove relation of existing attendee on registration
3521
+		$registration->_remove_relation_to($attendee, 'Attendee');
3522
+		// new attendee
3523
+		$new_attendee = clone $attendee;
3524
+		$new_attendee->set('ATT_ID', 0);
3525
+		$new_attendee->save();
3526
+		// add new attendee to reg
3527
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3528
+		EE_Error::add_success(
3529
+			esc_html__(
3530
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3531
+				'event_espresso'
3532
+			)
3533
+		);
3534
+		// redirect to edit page for attendee
3535
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3536
+		$this->_redirect_after_action('', '', '', $query_args, true);
3537
+	}
3538
+
3539
+
3540
+	/**
3541
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3542
+	 *
3543
+	 * @param int     $post_id
3544
+	 * @param WP_POST $post
3545
+	 * @throws DomainException
3546
+	 * @throws EE_Error
3547
+	 * @throws InvalidArgumentException
3548
+	 * @throws InvalidDataTypeException
3549
+	 * @throws InvalidInterfaceException
3550
+	 * @throws LogicException
3551
+	 * @throws InvalidFormSubmissionException
3552
+	 */
3553
+	protected function _insert_update_cpt_item($post_id, $post)
3554
+	{
3555
+		$success = true;
3556
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3557
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3558
+			: null;
3559
+		// for attendee updates
3560
+		if ($attendee instanceof EE_Attendee) {
3561
+			// note we should only be UPDATING attendees at this point.
3562
+			$updated_fields = array(
3563
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3564
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3565
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3566
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3567
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3568
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3569
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3570
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3571
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3572
+			);
3573
+			foreach ($updated_fields as $field => $value) {
3574
+				$attendee->set($field, $value);
3575
+			}
3576
+
3577
+			// process contact details metabox form handler (which will also save the attendee)
3578
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3579
+			$success = $contact_details_form->process($this->_req_data);
3580
+
3581
+			$attendee_update_callbacks = apply_filters(
3582
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3583
+				array()
3584
+			);
3585
+			foreach ($attendee_update_callbacks as $a_callback) {
3586
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3587
+					throw new EE_Error(
3588
+						sprintf(
3589
+							esc_html__(
3590
+								'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.',
3591
+								'event_espresso'
3592
+							),
3593
+							$a_callback
3594
+						)
3595
+					);
3596
+				}
3597
+			}
3598
+		}
3599
+
3600
+		if ($success === false) {
3601
+			EE_Error::add_error(
3602
+				esc_html__(
3603
+					'Something went wrong with updating the meta table data for the registration.',
3604
+					'event_espresso'
3605
+				),
3606
+				__FILE__,
3607
+				__FUNCTION__,
3608
+				__LINE__
3609
+			);
3610
+		}
3611
+	}
3612
+
3613
+
3614
+	public function trash_cpt_item($post_id)
3615
+	{
3616
+	}
3617
+
3618
+
3619
+	public function delete_cpt_item($post_id)
3620
+	{
3621
+	}
3622
+
3623
+
3624
+	public function restore_cpt_item($post_id)
3625
+	{
3626
+	}
3627
+
3628
+
3629
+	protected function _restore_cpt_item($post_id, $revision_id)
3630
+	{
3631
+	}
3632
+
3633
+
3634
+	public function attendee_editor_metaboxes()
3635
+	{
3636
+		$this->verify_cpt_object();
3637
+		remove_meta_box(
3638
+			'postexcerpt',
3639
+			esc_html__('Excerpt', 'event_espresso'),
3640
+			'post_excerpt_meta_box',
3641
+			$this->_cpt_routes[ $this->_req_action ],
3642
+			'normal',
3643
+			'core'
3644
+		);
3645
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3646
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3647
+			add_meta_box(
3648
+				'postexcerpt',
3649
+				esc_html__('Short Biography', 'event_espresso'),
3650
+				'post_excerpt_meta_box',
3651
+				$this->_cpt_routes[ $this->_req_action ],
3652
+				'normal'
3653
+			);
3654
+		}
3655
+		if (post_type_supports('espresso_attendees', 'comments')) {
3656
+			add_meta_box(
3657
+				'commentsdiv',
3658
+				esc_html__('Notes on the Contact', 'event_espresso'),
3659
+				'post_comment_meta_box',
3660
+				$this->_cpt_routes[ $this->_req_action ],
3661
+				'normal',
3662
+				'core'
3663
+			);
3664
+		}
3665
+		add_meta_box(
3666
+			'attendee_contact_info',
3667
+			esc_html__('Contact Info', 'event_espresso'),
3668
+			array($this, 'attendee_contact_info'),
3669
+			$this->_cpt_routes[ $this->_req_action ],
3670
+			'side',
3671
+			'core'
3672
+		);
3673
+		add_meta_box(
3674
+			'attendee_details_address',
3675
+			esc_html__('Address Details', 'event_espresso'),
3676
+			array($this, 'attendee_address_details'),
3677
+			$this->_cpt_routes[ $this->_req_action ],
3678
+			'normal',
3679
+			'core'
3680
+		);
3681
+		add_meta_box(
3682
+			'attendee_registrations',
3683
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3684
+			array($this, 'attendee_registrations_meta_box'),
3685
+			$this->_cpt_routes[ $this->_req_action ],
3686
+			'normal',
3687
+			'high'
3688
+		);
3689
+	}
3690
+
3691
+
3692
+	/**
3693
+	 * Metabox for attendee contact info
3694
+	 *
3695
+	 * @param  WP_Post $post wp post object
3696
+	 * @return string attendee contact info ( and form )
3697
+	 * @throws EE_Error
3698
+	 * @throws InvalidArgumentException
3699
+	 * @throws InvalidDataTypeException
3700
+	 * @throws InvalidInterfaceException
3701
+	 * @throws LogicException
3702
+	 * @throws DomainException
3703
+	 */
3704
+	public function attendee_contact_info($post)
3705
+	{
3706
+		// get attendee object ( should already have it )
3707
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3708
+		$form->enqueueStylesAndScripts();
3709
+		echo $form->display();
3710
+	}
3711
+
3712
+
3713
+	/**
3714
+	 * Return form handler for the contact details metabox
3715
+	 *
3716
+	 * @param EE_Attendee $attendee
3717
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3718
+	 * @throws DomainException
3719
+	 * @throws InvalidArgumentException
3720
+	 * @throws InvalidDataTypeException
3721
+	 * @throws InvalidInterfaceException
3722
+	 */
3723
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3724
+	{
3725
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3726
+	}
3727
+
3728
+
3729
+	/**
3730
+	 * Metabox for attendee details
3731
+	 *
3732
+	 * @param  WP_Post $post wp post object
3733
+	 * @throws DomainException
3734
+	 */
3735
+	public function attendee_address_details($post)
3736
+	{
3737
+		// get attendee object (should already have it)
3738
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3739
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3740
+			new EE_Question_Form_Input(
3741
+				EE_Question::new_instance(
3742
+					array(
3743
+						'QST_ID'           => 0,
3744
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3745
+						'QST_system'       => 'admin-state',
3746
+					)
3747
+				),
3748
+				EE_Answer::new_instance(
3749
+					array(
3750
+						'ANS_ID'    => 0,
3751
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3752
+					)
3753
+				),
3754
+				array(
3755
+					'input_id'       => 'STA_ID',
3756
+					'input_name'     => 'STA_ID',
3757
+					'input_prefix'   => '',
3758
+					'append_qstn_id' => false,
3759
+				)
3760
+			)
3761
+		);
3762
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3763
+			new EE_Question_Form_Input(
3764
+				EE_Question::new_instance(
3765
+					array(
3766
+						'QST_ID'           => 0,
3767
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3768
+						'QST_system'       => 'admin-country',
3769
+					)
3770
+				),
3771
+				EE_Answer::new_instance(
3772
+					array(
3773
+						'ANS_ID'    => 0,
3774
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3775
+					)
3776
+				),
3777
+				array(
3778
+					'input_id'       => 'CNT_ISO',
3779
+					'input_name'     => 'CNT_ISO',
3780
+					'input_prefix'   => '',
3781
+					'append_qstn_id' => false,
3782
+				)
3783
+			)
3784
+		);
3785
+		$template =
3786
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3787
+		EEH_Template::display_template($template, $this->_template_args);
3788
+	}
3789
+
3790
+
3791
+	/**
3792
+	 *        _attendee_details
3793
+	 *
3794
+	 * @access protected
3795
+	 * @param $post
3796
+	 * @return void
3797
+	 * @throws DomainException
3798
+	 * @throws EE_Error
3799
+	 */
3800
+	public function attendee_registrations_meta_box($post)
3801
+	{
3802
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3803
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3804
+		$template =
3805
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3806
+		EEH_Template::display_template($template, $this->_template_args);
3807
+	}
3808
+
3809
+
3810
+	/**
3811
+	 * add in the form fields for the attendee edit
3812
+	 *
3813
+	 * @param  WP_Post $post wp post object
3814
+	 * @return string html for new form.
3815
+	 * @throws DomainException
3816
+	 */
3817
+	public function after_title_form_fields($post)
3818
+	{
3819
+		if ($post->post_type == 'espresso_attendees') {
3820
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3821
+			$template_args['attendee'] = $this->_cpt_model_obj;
3822
+			EEH_Template::display_template($template, $template_args);
3823
+		}
3824
+	}
3825
+
3826
+
3827
+	/**
3828
+	 *        _trash_or_restore_attendee
3829
+	 *
3830
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3831
+	 * @return void
3832
+	 * @throws EE_Error
3833
+	 * @throws InvalidArgumentException
3834
+	 * @throws InvalidDataTypeException
3835
+	 * @throws InvalidInterfaceException
3836
+	 * @access protected
3837
+	 */
3838
+	protected function _trash_or_restore_attendees($trash = true)
3839
+	{
3840
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3841
+		$ATT_MDL = EEM_Attendee::instance();
3842
+		$success = 1;
3843
+		// Checkboxes
3844
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3845
+			// if array has more than one element than success message should be plural
3846
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3847
+			// cycle thru checkboxes
3848
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3849
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3850
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3851
+				if (! $updated) {
3852
+					$success = 0;
3853
+				}
3854
+			}
3855
+		} else {
3856
+			// grab single id and delete
3857
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3858
+			// get attendee
3859
+			$att = $ATT_MDL->get_one_by_ID($ATT_ID);
3860
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3861
+			$updated = $att->save();
3862
+			if (! $updated) {
3863
+				$success = 0;
3864
+			}
3865
+		}
3866
+		$what = $success > 1
3867
+			? esc_html__('Contacts', 'event_espresso')
3868
+			: esc_html__('Contact', 'event_espresso');
3869
+		$action_desc = $trash
3870
+			? esc_html__('moved to the trash', 'event_espresso')
3871
+			: esc_html__('restored', 'event_espresso');
3872
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3873
+	}
3874 3874
 }
Please login to merge, or discard this patch.
Spacing   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
         // when adding a new registration...
66 66
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67 67
             EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
68
+            if ( ! isset($this->_req_data['processing_registration'])
69 69
                 || absint($this->_req_data['processing_registration']) !== 1
70 70
             ) {
71 71
                 // and it's NOT the attendee information reg step
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
         // style
659 659
         wp_register_style(
660 660
             'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
661
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
662 662
             array('ee-admin-css'),
663 663
             EVENT_ESPRESSO_VERSION
664 664
         );
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
         // script
667 667
         wp_register_script(
668 668
             'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
669
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
670 670
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671 671
             EVENT_ESPRESSO_VERSION,
672 672
             true
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
         wp_dequeue_style('espresso_reg');
705 705
         wp_register_style(
706 706
             'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
707
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
708 708
             array('ee-admin-css'),
709 709
             EVENT_ESPRESSO_VERSION
710 710
         );
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
     {
717 717
         wp_register_script(
718 718
             'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
719
+            REG_ASSETS_URL.'spco_for_admin.js',
720 720
             array('underscore', 'jquery'),
721 721
             EVENT_ESPRESSO_VERSION,
722 722
             true
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post'   => $ATT_ID,
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
             return true;
1117 1117
         }
1118 1118
         $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1119
+        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120 1120
         if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121 1121
             return true;
1122 1122
         } else {
@@ -1198,7 +1198,7 @@  discard block
 block discarded – undo
1198 1198
             'caps'                     => EEM_Registration::caps_read_admin,
1199 1199
             'default_where_conditions' => 'this_model_only',
1200 1200
         );
1201
-        if (! $count) {
1201
+        if ( ! $count) {
1202 1202
             $query_params = array_merge(
1203 1203
                 $query_params,
1204 1204
                 $this->_get_orderby_for_registrations_query(),
@@ -1219,7 +1219,7 @@  discard block
 block discarded – undo
1219 1219
     protected function addAttendeeIdToWhereConditions(array $request)
1220 1220
     {
1221 1221
         $where = array();
1222
-        if (! empty($request['ATT_ID'])) {
1222
+        if ( ! empty($request['ATT_ID'])) {
1223 1223
             $where['ATT_ID'] = absint($request['ATT_ID']);
1224 1224
         }
1225 1225
         return $where;
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
     protected function _add_event_id_to_where_conditions(array $request)
1236 1236
     {
1237 1237
         $where = array();
1238
-        if (! empty($request['event_id'])) {
1238
+        if ( ! empty($request['event_id'])) {
1239 1239
             $where['EVT_ID'] = absint($request['event_id']);
1240 1240
         }
1241 1241
         return $where;
@@ -1251,7 +1251,7 @@  discard block
 block discarded – undo
1251 1251
     protected function _add_category_id_to_where_conditions(array $request)
1252 1252
     {
1253 1253
         $where = array();
1254
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1254
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1255 1255
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1256 1256
         }
1257 1257
         return $where;
@@ -1267,10 +1267,10 @@  discard block
 block discarded – undo
1267 1267
     protected function _add_datetime_id_to_where_conditions(array $request)
1268 1268
     {
1269 1269
         $where = array();
1270
-        if (! empty($request['datetime_id'])) {
1270
+        if ( ! empty($request['datetime_id'])) {
1271 1271
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1272 1272
         }
1273
-        if (! empty($request['DTT_ID'])) {
1273
+        if ( ! empty($request['DTT_ID'])) {
1274 1274
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1275 1275
         }
1276 1276
         return $where;
@@ -1296,7 +1296,7 @@  discard block
 block discarded – undo
1296 1296
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1297 1297
          * UNLESS viewing trashed registrations.
1298 1298
          */
1299
-        if (! empty($registration_status)) {
1299
+        if ( ! empty($registration_status)) {
1300 1300
             $where['STS_ID'] = $registration_status;
1301 1301
         } else {
1302 1302
             // make sure we exclude incomplete registrations, but only if not trashed.
@@ -1339,12 +1339,12 @@  discard block
 block discarded – undo
1339 1339
                 array(
1340 1340
                     EEM_Registration::instance()->convert_datetime_for_query(
1341 1341
                         'REG_date',
1342
-                        $now . ' 00:00:00',
1342
+                        $now.' 00:00:00',
1343 1343
                         'Y-m-d H:i:s'
1344 1344
                     ),
1345 1345
                     EEM_Registration::instance()->convert_datetime_for_query(
1346 1346
                         'REG_date',
1347
-                        $now . ' 23:59:59',
1347
+                        $now.' 23:59:59',
1348 1348
                         'Y-m-d H:i:s'
1349 1349
                     ),
1350 1350
                 ),
@@ -1357,12 +1357,12 @@  discard block
 block discarded – undo
1357 1357
                 array(
1358 1358
                     EEM_Registration::instance()->convert_datetime_for_query(
1359 1359
                         'REG_date',
1360
-                        $current_year_and_month . '-01 00:00:00',
1360
+                        $current_year_and_month.'-01 00:00:00',
1361 1361
                         'Y-m-d H:i:s'
1362 1362
                     ),
1363 1363
                     EEM_Registration::instance()->convert_datetime_for_query(
1364 1364
                         'REG_date',
1365
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1365
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1366 1366
                         'Y-m-d H:i:s'
1367 1367
                     ),
1368 1368
                 ),
@@ -1377,18 +1377,18 @@  discard block
 block discarded – undo
1377 1377
                 : '';
1378 1378
             // if there is not a month or year then we can't go further
1379 1379
             if ($month_requested && $year_requested) {
1380
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1380
+                $days_in_month = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1381 1381
                 $where['REG_date'] = array(
1382 1382
                     'BETWEEN',
1383 1383
                     array(
1384 1384
                         EEM_Registration::instance()->convert_datetime_for_query(
1385 1385
                             'REG_date',
1386
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1386
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1387 1387
                             'Y-m-d H:i:s'
1388 1388
                         ),
1389 1389
                         EEM_Registration::instance()->convert_datetime_for_query(
1390 1390
                             'REG_date',
1391
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1391
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1392 1392
                             'Y-m-d H:i:s'
1393 1393
                         ),
1394 1394
                     ),
@@ -1408,8 +1408,8 @@  discard block
 block discarded – undo
1408 1408
     protected function _add_search_to_where_conditions(array $request)
1409 1409
     {
1410 1410
         $where = array();
1411
-        if (! empty($request['s'])) {
1412
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1411
+        if ( ! empty($request['s'])) {
1412
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1413 1413
             $where['OR*search_conditions'] = array(
1414 1414
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1415 1415
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1634,7 +1634,7 @@  discard block
 block discarded – undo
1634 1634
                 )
1635 1635
                 : '';
1636 1636
             // grab header
1637
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1637
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1638 1638
             $this->_template_args['REG_ID'] = $this->_registration->ID();
1639 1639
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1640 1640
                 $template_path,
@@ -1772,7 +1772,7 @@  discard block
 block discarded – undo
1772 1772
                                 EEH_HTML::strong(
1773 1773
                                     $this->_registration->pretty_status(),
1774 1774
                                     '',
1775
-                                    'status-' . $this->_registration->status_ID(),
1775
+                                    'status-'.$this->_registration->status_ID(),
1776 1776
                                     'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1777 1777
                                 )
1778 1778
                             )
@@ -1821,14 +1821,14 @@  discard block
 block discarded – undo
1821 1821
     protected function _get_reg_statuses()
1822 1822
     {
1823 1823
         $reg_status_array = EEM_Registration::instance()->reg_status_array();
1824
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1824
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1825 1825
         // get current reg status
1826 1826
         $current_status = $this->_registration->status_ID();
1827 1827
         // is registration for free event? This will determine whether to display the pending payment option
1828 1828
         if ($current_status !== EEM_Registration::status_id_pending_payment
1829 1829
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1830 1830
         ) {
1831
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1831
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1832 1832
         }
1833 1833
         return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1834 1834
     }
@@ -1920,7 +1920,7 @@  discard block
 block discarded – undo
1920 1920
         $success = false;
1921 1921
         // typecast $REG_IDs
1922 1922
         $REG_IDs = (array) $REG_IDs;
1923
-        if (! empty($REG_IDs)) {
1923
+        if ( ! empty($REG_IDs)) {
1924 1924
             $success = true;
1925 1925
             // set default status if none is passed
1926 1926
             $status = $status ? $status : EEM_Registration::status_id_pending_payment;
@@ -2000,11 +2000,11 @@  discard block
 block discarded – undo
2000 2000
         // unset nonces
2001 2001
         foreach ($this->_req_data as $ref => $value) {
2002 2002
             if (strpos($ref, 'nonce') !== false) {
2003
-                unset($this->_req_data[ $ref ]);
2003
+                unset($this->_req_data[$ref]);
2004 2004
                 continue;
2005 2005
             }
2006 2006
             $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
2007
-            $this->_req_data[ $ref ] = $value;
2007
+            $this->_req_data[$ref] = $value;
2008 2008
         }
2009 2009
         // merge request vars so that the reloaded list table contains any existing filter query params
2010 2010
         $route = array_merge($this->_req_data, $route);
@@ -2078,7 +2078,7 @@  discard block
 block discarded – undo
2078 2078
             $action,
2079 2079
             $notify
2080 2080
         );
2081
-        $method = $action . '_registration';
2081
+        $method = $action.'_registration';
2082 2082
         if (method_exists($this, $method)) {
2083 2083
             $this->$method($notify);
2084 2084
         }
@@ -2309,7 +2309,7 @@  discard block
 block discarded – undo
2309 2309
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2310 2310
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2311 2311
         $template_path =
2312
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2312
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2313 2313
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2314 2314
     }
2315 2315
 
@@ -2342,7 +2342,7 @@  discard block
 block discarded – undo
2342 2342
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2343 2343
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2344 2344
             $template_path =
2345
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2345
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2346 2346
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2347 2347
         }
2348 2348
     }
@@ -2359,7 +2359,7 @@  discard block
 block discarded – undo
2359 2359
     public function form_before_question_group($output)
2360 2360
     {
2361 2361
         EE_Error::doing_it_wrong(
2362
-            __CLASS__ . '::' . __FUNCTION__,
2362
+            __CLASS__.'::'.__FUNCTION__,
2363 2363
             esc_html__(
2364 2364
                 '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.',
2365 2365
                 'event_espresso'
@@ -2384,7 +2384,7 @@  discard block
 block discarded – undo
2384 2384
     public function form_after_question_group($output)
2385 2385
     {
2386 2386
         EE_Error::doing_it_wrong(
2387
-            __CLASS__ . '::' . __FUNCTION__,
2387
+            __CLASS__.'::'.__FUNCTION__,
2388 2388
             esc_html__(
2389 2389
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2390 2390
                 'event_espresso'
@@ -2422,7 +2422,7 @@  discard block
 block discarded – undo
2422 2422
     public function form_form_field_label_wrap($label)
2423 2423
     {
2424 2424
         EE_Error::doing_it_wrong(
2425
-            __CLASS__ . '::' . __FUNCTION__,
2425
+            __CLASS__.'::'.__FUNCTION__,
2426 2426
             esc_html__(
2427 2427
                 '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.',
2428 2428
                 'event_espresso'
@@ -2432,7 +2432,7 @@  discard block
 block discarded – undo
2432 2432
         return '
2433 2433
 			<tr>
2434 2434
 				<th>
2435
-					' . $label . '
2435
+					' . $label.'
2436 2436
 				</th>';
2437 2437
     }
2438 2438
 
@@ -2448,7 +2448,7 @@  discard block
 block discarded – undo
2448 2448
     public function form_form_field_input__wrap($input)
2449 2449
     {
2450 2450
         EE_Error::doing_it_wrong(
2451
-            __CLASS__ . '::' . __FUNCTION__,
2451
+            __CLASS__.'::'.__FUNCTION__,
2452 2452
             esc_html__(
2453 2453
                 '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.',
2454 2454
                 'event_espresso'
@@ -2457,7 +2457,7 @@  discard block
 block discarded – undo
2457 2457
         );
2458 2458
         return '
2459 2459
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2460
-					' . $input . '
2460
+					' . $input.'
2461 2461
 				</td>
2462 2462
 			</tr>';
2463 2463
     }
@@ -2501,8 +2501,8 @@  discard block
 block discarded – undo
2501 2501
      */
2502 2502
     protected function _get_reg_custom_questions_form($REG_ID)
2503 2503
     {
2504
-        if (! $this->_reg_custom_questions_form) {
2505
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2504
+        if ( ! $this->_reg_custom_questions_form) {
2505
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2506 2506
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2507 2507
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2508 2508
             );
@@ -2525,7 +2525,7 @@  discard block
 block discarded – undo
2525 2525
      */
2526 2526
     private function _save_reg_custom_questions_form($REG_ID = false)
2527 2527
     {
2528
-        if (! $REG_ID) {
2528
+        if ( ! $REG_ID) {
2529 2529
             EE_Error::add_error(
2530 2530
                 esc_html__(
2531 2531
                     'An error occurred. No registration ID was received.',
@@ -2616,28 +2616,28 @@  discard block
 block discarded – undo
2616 2616
                     ? $registration->attendee()
2617 2617
                     : EEM_Attendee::instance()
2618 2618
                                   ->create_default_object();
2619
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2620
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2621
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2622
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2623
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2624
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2619
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID'] = $registration->status_ID();
2620
+                $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
2621
+                $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
2622
+                $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
2623
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2624
+                $this->_template_args['attendees'][$att_nmbr]['address'] = implode(
2625 2625
                     ', ',
2626 2626
                     $attendee->full_address_as_array()
2627 2627
                 );
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2628
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2629 2629
                     array(
2630 2630
                         'action' => 'edit_attendee',
2631 2631
                         'post'   => $attendee->ID(),
2632 2632
                     ),
2633 2633
                     REG_ADMIN_URL
2634 2634
                 );
2635
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj()->name();
2635
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj()->name();
2636 2636
                 $att_nmbr++;
2637 2637
             }
2638 2638
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2639 2639
         }
2640
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2640
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2641 2641
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2642 2642
     }
2643 2643
 
@@ -2661,11 +2661,11 @@  discard block
 block discarded – undo
2661 2661
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2662 2662
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2663 2663
         // primary registration object (that way we know if we need to show create button or not)
2664
-        if (! $this->_registration->is_primary_registrant()) {
2664
+        if ( ! $this->_registration->is_primary_registrant()) {
2665 2665
             $primary_registration = $this->_registration->get_primary_registration();
2666 2666
             $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2667 2667
                 : null;
2668
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2668
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2669 2669
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2670 2670
                 // custom attendee object so let's not worry about the primary reg.
2671 2671
                 $primary_registration = null;
@@ -2699,7 +2699,7 @@  discard block
 block discarded – undo
2699 2699
             ) : '';
2700 2700
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2701 2701
         $this->_template_args['att_check'] = $att_check;
2702
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2702
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2703 2703
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2704 2704
     }
2705 2705
 
@@ -2737,7 +2737,7 @@  discard block
 block discarded – undo
2737 2737
         $success = 0;
2738 2738
         $overwrite_msgs = false;
2739 2739
         // Checkboxes
2740
-        if (! is_array($this->_req_data['_REG_ID'])) {
2740
+        if ( ! is_array($this->_req_data['_REG_ID'])) {
2741 2741
             $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2742 2742
         }
2743 2743
         $reg_count = count($this->_req_data['_REG_ID']);
@@ -2746,7 +2746,7 @@  discard block
 block discarded – undo
2746 2746
             /** @var EE_Registration $REG */
2747 2747
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2748 2748
             $payments = $REG->registration_payments();
2749
-            if (! empty($payments)) {
2749
+            if ( ! empty($payments)) {
2750 2750
                 $name = $REG->attendee() instanceof EE_Attendee
2751 2751
                     ? $REG->attendee()->full_name()
2752 2752
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2807,17 +2807,17 @@  discard block
 block discarded – undo
2807 2807
         $REG_MDL = EEM_Registration::instance();
2808 2808
         $success = 1;
2809 2809
         // Checkboxes
2810
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2810
+        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2811 2811
             // if array has more than one element than success message should be plural
2812 2812
             $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2813 2813
             // cycle thru checkboxes
2814 2814
             while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2815 2815
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2816
-                if (! $REG instanceof EE_Registration) {
2816
+                if ( ! $REG instanceof EE_Registration) {
2817 2817
                     continue;
2818 2818
                 }
2819 2819
                 $deleted = $this->_delete_registration($REG);
2820
-                if (! $deleted) {
2820
+                if ( ! $deleted) {
2821 2821
                     $success = 0;
2822 2822
                 }
2823 2823
             }
@@ -2826,7 +2826,7 @@  discard block
 block discarded – undo
2826 2826
             $REG_ID = $this->_req_data['_REG_ID'];
2827 2827
             $REG = $REG_MDL->get_one_by_ID($REG_ID);
2828 2828
             $deleted = $this->_delete_registration($REG);
2829
-            if (! $deleted) {
2829
+            if ( ! $deleted) {
2830 2830
                 $success = 0;
2831 2831
             }
2832 2832
         }
@@ -2860,11 +2860,11 @@  discard block
 block discarded – undo
2860 2860
         $REGS = $TXN->get_many_related('Registration');
2861 2861
         $all_trashed = true;
2862 2862
         foreach ($REGS as $registration) {
2863
-            if (! $registration->get('REG_deleted')) {
2863
+            if ( ! $registration->get('REG_deleted')) {
2864 2864
                 $all_trashed = false;
2865 2865
             }
2866 2866
         }
2867
-        if (! $all_trashed) {
2867
+        if ( ! $all_trashed) {
2868 2868
             EE_Error::add_error(
2869 2869
                 esc_html__(
2870 2870
                     '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.',
@@ -2923,7 +2923,7 @@  discard block
 block discarded – undo
2923 2923
      */
2924 2924
     public function new_registration()
2925 2925
     {
2926
-        if (! $this->_set_reg_event()) {
2926
+        if ( ! $this->_set_reg_event()) {
2927 2927
             throw new EE_Error(
2928 2928
                 esc_html__(
2929 2929
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2933,8 +2933,8 @@  discard block
 block discarded – undo
2933 2933
         }
2934 2934
         EE_Registry::instance()->REQ->set_espresso_page(true);
2935 2935
         // gotta start with a clean slate if we're not coming here via ajax
2936
-        if (! defined('DOING_AJAX')
2937
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2936
+        if ( ! defined('DOING_AJAX')
2937
+            && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2938 2938
         ) {
2939 2939
             EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2940 2940
         }
@@ -2967,7 +2967,7 @@  discard block
 block discarded – undo
2967 2967
         }
2968 2968
         // grab header
2969 2969
         $template_path =
2970
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2970
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2971 2971
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2972 2972
             $template_path,
2973 2973
             $this->_template_args,
@@ -3008,7 +3008,7 @@  discard block
 block discarded – undo
3008 3008
                 '</b>'
3009 3009
             );
3010 3010
             return '
3011
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3011
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
3012 3012
 	<script >
3013 3013
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
3014 3014
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3076,7 +3076,7 @@  discard block
 block discarded – undo
3076 3076
         // we come back to the process_registration_step route.
3077 3077
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3078 3078
         return EEH_Template::display_template(
3079
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3079
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3080 3080
             $template_args,
3081 3081
             true
3082 3082
         );
@@ -3098,8 +3098,8 @@  discard block
 block discarded – undo
3098 3098
         if (is_object($this->_reg_event)) {
3099 3099
             return true;
3100 3100
         }
3101
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3102
-        if (! $EVT_ID) {
3101
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3102
+        if ( ! $EVT_ID) {
3103 3103
             return false;
3104 3104
         }
3105 3105
         $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
@@ -3131,8 +3131,8 @@  discard block
 block discarded – undo
3131 3131
         $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3132 3132
         // if doing ajax then we need to verify the nonce
3133 3133
         if (defined('DOING_AJAX')) {
3134
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3135
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3134
+            $nonce = isset($this->_req_data[$this->_req_nonce])
3135
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3136 3136
             $this->_verify_nonce($nonce, $this->_req_nonce);
3137 3137
         }
3138 3138
         switch ($step) {
@@ -3168,7 +3168,7 @@  discard block
 block discarded – undo
3168 3168
                 }
3169 3169
                 break;
3170 3170
             case 'questions':
3171
-                if (! isset(
3171
+                if ( ! isset(
3172 3172
                     $this->_req_data['txn_reg_status_change'],
3173 3173
                     $this->_req_data['txn_reg_status_change']['send_notifications']
3174 3174
                 )
@@ -3183,7 +3183,7 @@  discard block
 block discarded – undo
3183 3183
                         $grand_total->save_this_and_descendants_to_txn();
3184 3184
                     }
3185 3185
                 }
3186
-                if (! $transaction instanceof EE_Transaction) {
3186
+                if ( ! $transaction instanceof EE_Transaction) {
3187 3187
                     $query_args = array(
3188 3188
                         'action'                  => 'new_registration',
3189 3189
                         'processing_registration' => 2,
@@ -3206,7 +3206,7 @@  discard block
 block discarded – undo
3206 3206
                     }
3207 3207
                 }
3208 3208
                 // maybe update status, and make sure to save transaction if not done already
3209
-                if (! $transaction->update_status_based_on_total_paid()) {
3209
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3210 3210
                     $transaction->save();
3211 3211
                 }
3212 3212
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3289,7 +3289,7 @@  discard block
 block discarded – undo
3289 3289
     public function get_attendees($per_page, $count = false, $trash = false)
3290 3290
     {
3291 3291
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3292
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3292
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3293 3293
         $ATT_MDL = EEM_Attendee::instance();
3294 3294
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3295 3295
         switch ($this->_req_data['orderby']) {
@@ -3328,8 +3328,8 @@  discard block
 block discarded – undo
3328 3328
             ? $this->_req_data['perpage']
3329 3329
             : $per_page;
3330 3330
         $_where = array();
3331
-        if (! empty($this->_req_data['s'])) {
3332
-            $sstr = '%' . $this->_req_data['s'] . '%';
3331
+        if ( ! empty($this->_req_data['s'])) {
3332
+            $sstr = '%'.$this->_req_data['s'].'%';
3333 3333
             $_where['OR'] = array(
3334 3334
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3335 3335
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3356,7 +3356,7 @@  discard block
 block discarded – undo
3356 3356
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3357 3357
             'limit'         => $limit,
3358 3358
         );
3359
-        if (! $count) {
3359
+        if ( ! $count) {
3360 3360
             $query_args['order_by'] = array($orderby => $sort);
3361 3361
         }
3362 3362
         if ($trash) {
@@ -3399,7 +3399,7 @@  discard block
 block discarded – undo
3399 3399
      */
3400 3400
     public function _registrations_report_base($method_name_for_getting_query_params)
3401 3401
     {
3402
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3402
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3403 3403
             wp_redirect(
3404 3404
                 EE_Admin_Page::add_query_args_and_nonce(
3405 3405
                     array(
@@ -3431,8 +3431,8 @@  discard block
 block discarded – undo
3431 3431
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3432 3432
             );
3433 3433
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3434
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3435
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3434
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3435
+                require_once(EE_CLASSES.'EE_Export.class.php');
3436 3436
                 $EE_Export = EE_Export::instance($this->_req_data);
3437 3437
                 $EE_Export->export();
3438 3438
             }
@@ -3453,8 +3453,8 @@  discard block
 block discarded – undo
3453 3453
 
3454 3454
     public function _contact_list_export()
3455 3455
     {
3456
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3457
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3456
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3457
+            require_once(EE_CLASSES.'EE_Export.class.php');
3458 3458
             $EE_Export = EE_Export::instance($this->_req_data);
3459 3459
             $EE_Export->export_attendees();
3460 3460
         }
@@ -3463,7 +3463,7 @@  discard block
 block discarded – undo
3463 3463
 
3464 3464
     public function _contact_list_report()
3465 3465
     {
3466
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3466
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3467 3467
             wp_redirect(
3468 3468
                 EE_Admin_Page::add_query_args_and_nonce(
3469 3469
                     array(
@@ -3475,8 +3475,8 @@  discard block
 block discarded – undo
3475 3475
                 )
3476 3476
             );
3477 3477
         } else {
3478
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3479
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3478
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3479
+                require_once(EE_CLASSES.'EE_Export.class.php');
3480 3480
                 $EE_Export = EE_Export::instance($this->_req_data);
3481 3481
                 $EE_Export->report_attendees();
3482 3482
             }
@@ -3562,7 +3562,7 @@  discard block
 block discarded – undo
3562 3562
             $updated_fields = array(
3563 3563
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3564 3564
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3565
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3565
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3566 3566
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3567 3567
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3568 3568
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3638,17 +3638,17 @@  discard block
 block discarded – undo
3638 3638
             'postexcerpt',
3639 3639
             esc_html__('Excerpt', 'event_espresso'),
3640 3640
             'post_excerpt_meta_box',
3641
-            $this->_cpt_routes[ $this->_req_action ],
3641
+            $this->_cpt_routes[$this->_req_action],
3642 3642
             'normal',
3643 3643
             'core'
3644 3644
         );
3645
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3645
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3646 3646
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3647 3647
             add_meta_box(
3648 3648
                 'postexcerpt',
3649 3649
                 esc_html__('Short Biography', 'event_espresso'),
3650 3650
                 'post_excerpt_meta_box',
3651
-                $this->_cpt_routes[ $this->_req_action ],
3651
+                $this->_cpt_routes[$this->_req_action],
3652 3652
                 'normal'
3653 3653
             );
3654 3654
         }
@@ -3657,7 +3657,7 @@  discard block
 block discarded – undo
3657 3657
                 'commentsdiv',
3658 3658
                 esc_html__('Notes on the Contact', 'event_espresso'),
3659 3659
                 'post_comment_meta_box',
3660
-                $this->_cpt_routes[ $this->_req_action ],
3660
+                $this->_cpt_routes[$this->_req_action],
3661 3661
                 'normal',
3662 3662
                 'core'
3663 3663
             );
@@ -3666,7 +3666,7 @@  discard block
 block discarded – undo
3666 3666
             'attendee_contact_info',
3667 3667
             esc_html__('Contact Info', 'event_espresso'),
3668 3668
             array($this, 'attendee_contact_info'),
3669
-            $this->_cpt_routes[ $this->_req_action ],
3669
+            $this->_cpt_routes[$this->_req_action],
3670 3670
             'side',
3671 3671
             'core'
3672 3672
         );
@@ -3674,7 +3674,7 @@  discard block
 block discarded – undo
3674 3674
             'attendee_details_address',
3675 3675
             esc_html__('Address Details', 'event_espresso'),
3676 3676
             array($this, 'attendee_address_details'),
3677
-            $this->_cpt_routes[ $this->_req_action ],
3677
+            $this->_cpt_routes[$this->_req_action],
3678 3678
             'normal',
3679 3679
             'core'
3680 3680
         );
@@ -3682,7 +3682,7 @@  discard block
 block discarded – undo
3682 3682
             'attendee_registrations',
3683 3683
             esc_html__('Registrations for this Contact', 'event_espresso'),
3684 3684
             array($this, 'attendee_registrations_meta_box'),
3685
-            $this->_cpt_routes[ $this->_req_action ],
3685
+            $this->_cpt_routes[$this->_req_action],
3686 3686
             'normal',
3687 3687
             'high'
3688 3688
         );
@@ -3783,7 +3783,7 @@  discard block
 block discarded – undo
3783 3783
             )
3784 3784
         );
3785 3785
         $template =
3786
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3786
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3787 3787
         EEH_Template::display_template($template, $this->_template_args);
3788 3788
     }
3789 3789
 
@@ -3802,7 +3802,7 @@  discard block
 block discarded – undo
3802 3802
         $this->_template_args['attendee'] = $this->_cpt_model_obj;
3803 3803
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3804 3804
         $template =
3805
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3805
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3806 3806
         EEH_Template::display_template($template, $this->_template_args);
3807 3807
     }
3808 3808
 
@@ -3817,7 +3817,7 @@  discard block
 block discarded – undo
3817 3817
     public function after_title_form_fields($post)
3818 3818
     {
3819 3819
         if ($post->post_type == 'espresso_attendees') {
3820
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3820
+            $template = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3821 3821
             $template_args['attendee'] = $this->_cpt_model_obj;
3822 3822
             EEH_Template::display_template($template, $template_args);
3823 3823
         }
@@ -3841,14 +3841,14 @@  discard block
 block discarded – undo
3841 3841
         $ATT_MDL = EEM_Attendee::instance();
3842 3842
         $success = 1;
3843 3843
         // Checkboxes
3844
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3844
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3845 3845
             // if array has more than one element than success message should be plural
3846 3846
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3847 3847
             // cycle thru checkboxes
3848 3848
             while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3849 3849
                 $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3850 3850
                     : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3851
-                if (! $updated) {
3851
+                if ( ! $updated) {
3852 3852
                     $success = 0;
3853 3853
                 }
3854 3854
             }
@@ -3859,7 +3859,7 @@  discard block
 block discarded – undo
3859 3859
             $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3860 3860
             $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3861 3861
             $updated = $att->save();
3862
-            if (! $updated) {
3862
+            if ( ! $updated) {
3863 3863
                 $success = 0;
3864 3864
             }
3865 3865
         }
Please login to merge, or discard this patch.
core/db_classes/EE_Message.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -697,7 +697,7 @@
 block discarded – undo
697 697
     /**
698 698
      * Gets any error message.
699 699
      *
700
-     * @return mixed|null
700
+     * @return string
701 701
      */
702 702
     public function error_message()
703 703
     {
Please login to merge, or discard this patch.
Indentation   +867 added lines, -867 removed lines patch added patch discarded remove patch
@@ -10,875 +10,875 @@
 block discarded – undo
10 10
 class EE_Message extends EE_Base_Class implements EEI_Admin_Links
11 11
 {
12 12
 
13
-    /**
14
-     * @deprecated 4.9.0  Added for backward compat with add-on's
15
-     * @type null
16
-     */
17
-    public $template_pack;
18
-
19
-    /**
20
-     * @deprecated 4.9.0 Added for backward compat with add-on's
21
-     * @type null
22
-     */
23
-    public $template_variation;
24
-
25
-    /**
26
-     * @deprecated 4.9.0 Added for backward compat with add-on's
27
-     * @type string
28
-     */
29
-    public $content = '';
30
-
31
-
32
-    /**
33
-     * @type EE_messenger $_messenger
34
-     */
35
-    protected $_messenger = null;
36
-
37
-    /**
38
-     * @type EE_message_type $_message_type
39
-     */
40
-    protected $_message_type = null;
41
-
42
-
43
-    /**
44
-     * @param array  $props_n_values
45
-     * @param string $timezone
46
-     * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
47
-     *                             format.
48
-     * @return EE_Message
49
-     */
50
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
51
-    {
52
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
53
-        // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
-        if (! $has_object) {
55
-            EE_Registry::instance()->load_helper('URL');
56
-            $props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57
-        }
58
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
59
-    }
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values
64
-     * @param string $timezone
65
-     * @return EE_Message
66
-     */
67
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
-    {
69
-        return new self($props_n_values, true, $timezone);
70
-    }
71
-
72
-
73
-    /**
74
-     * Gets MSG_token
75
-     *
76
-     * @return int
77
-     */
78
-    public function MSG_token()
79
-    {
80
-        return $this->get('MSG_token');
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets MSG_token
86
-     *
87
-     * @param int $MSG_token
88
-     */
89
-    public function set_MSG_token($MSG_token)
90
-    {
91
-        $this->set('MSG_token', $MSG_token);
92
-    }
93
-
94
-
95
-    /**
96
-     * Gets GRP_ID
97
-     *
98
-     * @return int
99
-     */
100
-    public function GRP_ID()
101
-    {
102
-        return $this->get('GRP_ID');
103
-    }
104
-
105
-
106
-    /**
107
-     * Sets GRP_ID
108
-     *
109
-     * @param int $GRP_ID
110
-     */
111
-    public function set_GRP_ID($GRP_ID)
112
-    {
113
-        $this->set('GRP_ID', $GRP_ID);
114
-    }
115
-
116
-
117
-    /**
118
-     * Gets TXN_ID
119
-     *
120
-     * @return int
121
-     */
122
-    public function TXN_ID()
123
-    {
124
-        return $this->get('TXN_ID');
125
-    }
126
-
127
-
128
-    /**
129
-     * Sets TXN_ID
130
-     *
131
-     * @param int $TXN_ID
132
-     */
133
-    public function set_TXN_ID($TXN_ID)
134
-    {
135
-        $this->set('TXN_ID', $TXN_ID);
136
-    }
137
-
138
-
139
-    /**
140
-     * Gets messenger
141
-     *
142
-     * @return string
143
-     */
144
-    public function messenger()
145
-    {
146
-        return $this->get('MSG_messenger');
147
-    }
148
-
149
-
150
-    /**
151
-     * Sets messenger
152
-     *
153
-     * @param string $messenger
154
-     */
155
-    public function set_messenger($messenger)
156
-    {
157
-        $this->set('MSG_messenger', $messenger);
158
-    }
159
-
160
-
161
-    /**
162
-     * Returns corresponding messenger object for the set messenger on this message
163
-     *
164
-     * @return EE_messenger | null
165
-     */
166
-    public function messenger_object()
167
-    {
168
-        return $this->_messenger;
169
-    }
170
-
171
-
172
-    /**
173
-     * Sets messenger
174
-     *
175
-     * @param EE_messenger $messenger
176
-     */
177
-    public function set_messenger_object(EE_messenger $messenger)
178
-    {
179
-        $this->_messenger = $messenger;
180
-    }
181
-
182
-
183
-    /**
184
-     * validates messenger
185
-     *
186
-     * @param bool $throw_exceptions
187
-     * @return bool
188
-     * @throws \EE_Error
189
-     */
190
-    public function valid_messenger($throw_exceptions = false)
191
-    {
192
-        if ($this->_messenger instanceof EE_messenger) {
193
-            return true;
194
-        }
195
-        if ($throw_exceptions) {
196
-            throw new EE_Error(
197
-                sprintf(
198
-                    __(
199
-                        'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
200
-                        'event_espresso'
201
-                    ),
202
-                    $this->messenger()
203
-                )
204
-            );
205
-        }
206
-        return false;
207
-    }
208
-
209
-
210
-    /**
211
-     * This returns the set localized label for the messenger on this message.
212
-     * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
213
-     * with this message.
214
-     *
215
-     * @param   bool $plural whether to return the plural label or not.
216
-     * @return string
217
-     */
218
-    public function messenger_label($plural = false)
219
-    {
220
-        $label_type = $plural ? 'plural' : 'singular';
221
-        $messenger = $this->messenger_object();
222
-        return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets message_type
228
-     *
229
-     * @return string
230
-     */
231
-    public function message_type()
232
-    {
233
-        return $this->get('MSG_message_type');
234
-    }
235
-
236
-
237
-    /**
238
-     * Sets message_type
239
-     *
240
-     * @param string $message_type
241
-     */
242
-    public function set_message_type($message_type)
243
-    {
244
-        $this->set('MSG_message_type', $message_type);
245
-    }
246
-
247
-
248
-    /**
249
-     * Returns the message type object for the set message type on this message
250
-     *
251
-     * @return EE_message_type | null
252
-     */
253
-    public function message_type_object()
254
-    {
255
-        return $this->_message_type;
256
-    }
257
-
258
-
259
-    /**
260
-     * Sets message_type
261
-     *
262
-     * @param EE_message_type $message_type
263
-     * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
264
-     *                                        the message type or not.
265
-     */
266
-    public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
267
-    {
268
-        $this->_message_type = $message_type;
269
-        if ($set_priority) {
270
-            $this->set_priority($this->_message_type->get_priority());
271
-        }
272
-    }
273
-
274
-
275
-    /**
276
-     * validates message_type
277
-     *
278
-     * @param bool $throw_exceptions
279
-     * @return bool
280
-     * @throws \EE_Error
281
-     */
282
-    public function valid_message_type($throw_exceptions = false)
283
-    {
284
-        if ($this->_message_type instanceof EE_message_type) {
285
-            return true;
286
-        }
287
-        if ($throw_exceptions) {
288
-            throw new EE_Error(
289
-                sprintf(
290
-                    __(
291
-                        'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
292
-                        'event_espresso'
293
-                    ),
294
-                    $this->message_type()
295
-                )
296
-            );
297
-        }
298
-        return false;
299
-    }
300
-
301
-
302
-    /**
303
-     * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
304
-     *
305
-     * @param bool $throw_exceptions
306
-     * @return bool
307
-     * @throws \EE_Error
308
-     */
309
-    public function is_valid($throw_exceptions = false)
310
-    {
311
-        if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
312
-            return true;
313
-        }
314
-        return false;
315
-    }
316
-
317
-
318
-    /**
319
-     * This validates whether the internal messenger and message type objects are valid for sending.
320
-     * Three checks are done:
321
-     * 1. There is a valid messenger object.
322
-     * 2. There is a valid message type object.
323
-     * 3. The message type object is active for the messenger.
324
-     *
325
-     * @throws EE_Error  But only if $throw_exceptions is set to true.
326
-     * @param bool $throw_exceptions
327
-     * @return bool
328
-     */
329
-    public function is_valid_for_sending_or_generation($throw_exceptions = false)
330
-    {
331
-        $valid = false;
332
-        if ($this->is_valid($throw_exceptions)) {
333
-            /** @var EE_Message_Resource_Manager $message_resource_manager */
334
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
335
-            $valid = $message_resource_manager->is_message_type_active_for_messenger(
336
-                $this->messenger(),
337
-                $this->message_type()
338
-            );
339
-            if (! $valid && $throw_exceptions) {
340
-                throw new EE_Error(
341
-                    sprintf(
342
-                        __(
343
-                            'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
344
-                            'event_espresso'
345
-                        ),
346
-                        $this->message_type(),
347
-                        $this->messenger()
348
-                    )
349
-                );
350
-            }
351
-        }
352
-        return $valid;
353
-    }
354
-
355
-
356
-    /**
357
-     * This returns the set localized label for the message type on this message.
358
-     * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
359
-     * with this message.
360
-     *
361
-     * @param   bool $plural whether to return the plural label or not.
362
-     * @return string
363
-     */
364
-    public function message_type_label($plural = false)
365
-    {
366
-        $label_type = $plural ? 'plural' : 'singular';
367
-        $message_type = $this->message_type_object();
368
-        return $message_type instanceof EE_message_type
369
-            ? $message_type->label[ $label_type ]
370
-            : str_replace(
371
-                '_',
372
-                ' ',
373
-                $this->message_type()
374
-            );
375
-    }
376
-
377
-
378
-    /**
379
-     * Gets context
380
-     *
381
-     * @return string
382
-     */
383
-    public function context()
384
-    {
385
-        return $this->get('MSG_context');
386
-    }
387
-
388
-
389
-    /**
390
-     * This returns the corresponding localized label for the given context slug, if possible from installed message
391
-     * types. Otherwise, this will just return the set context slug on this object.
392
-     *
393
-     * @return string
394
-     */
395
-    public function context_label()
396
-    {
397
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
398
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399
-        $contexts = $message_resource_manager->get_all_contexts();
400
-        return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
401
-    }
402
-
403
-
404
-    /**
405
-     * Sets context
406
-     *
407
-     * @param string $context
408
-     */
409
-    public function set_context($context)
410
-    {
411
-        $this->set('MSG_context', $context);
412
-    }
413
-
414
-
415
-    /**
416
-     * Gets recipient_ID
417
-     *
418
-     * @return int
419
-     */
420
-    public function recipient_ID()
421
-    {
422
-        return $this->get('MSG_recipient_ID');
423
-    }
424
-
425
-
426
-    /**
427
-     * Sets recipient_ID
428
-     *
429
-     * @param string $recipient_ID
430
-     */
431
-    public function set_recipient_ID($recipient_ID)
432
-    {
433
-        $this->set('MSG_recipient_ID', $recipient_ID);
434
-    }
435
-
436
-
437
-    /**
438
-     * Gets recipient_type
439
-     *
440
-     * @return string
441
-     */
442
-    public function recipient_type()
443
-    {
444
-        return $this->get('MSG_recipient_type');
445
-    }
446
-
447
-
448
-    /**
449
-     * Return the related object matching the recipient type and ID.
450
-     *
451
-     * @return EE_Base_Class | null
452
-     */
453
-    public function recipient_object()
454
-    {
455
-        if (! $this->recipient_type() || ! $this->recipient_ID()) {
456
-            return null;
457
-        }
458
-
459
-        return $this->get_first_related($this->recipient_type());
460
-    }
461
-
462
-
463
-    /**
464
-     * Sets recipient_type
465
-     *
466
-     * @param string $recipient_type
467
-     */
468
-    public function set_recipient_type($recipient_type)
469
-    {
470
-        $this->set('MSG_recipient_type', $recipient_type);
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets content
476
-     *
477
-     * @return string
478
-     */
479
-    public function content()
480
-    {
481
-        return $this->get('MSG_content');
482
-    }
483
-
484
-
485
-    /**
486
-     * Sets content
487
-     *
488
-     * @param string $content
489
-     */
490
-    public function set_content($content)
491
-    {
492
-        $this->set('MSG_content', $content);
493
-    }
494
-
495
-
496
-    /**
497
-     * Gets subject
498
-     *
499
-     * @return string
500
-     */
501
-    public function subject()
502
-    {
503
-        return $this->get('MSG_subject');
504
-    }
505
-
506
-
507
-    /**
508
-     * Sets subject
509
-     *
510
-     * @param string $subject
511
-     */
512
-    public function set_subject($subject)
513
-    {
514
-        $this->set('MSG_subject', $subject);
515
-    }
516
-
517
-
518
-    /**
519
-     * Gets to
520
-     *
521
-     * @return string
522
-     */
523
-    public function to()
524
-    {
525
-        $to = $this->get('MSG_to');
526
-        return empty($to) ? __('No recipient', 'event_espresso') : $to;
527
-    }
528
-
529
-
530
-    /**
531
-     * Sets to
532
-     *
533
-     * @param string $to
534
-     */
535
-    public function set_to($to)
536
-    {
537
-        $this->set('MSG_to', $to);
538
-    }
539
-
540
-
541
-    /**
542
-     * Gets from
543
-     *
544
-     * @return string
545
-     */
546
-    public function from()
547
-    {
548
-        return $this->get('MSG_from');
549
-    }
550
-
551
-
552
-    /**
553
-     * Sets from
554
-     *
555
-     * @param string $from
556
-     */
557
-    public function set_from($from)
558
-    {
559
-        $this->set('MSG_from', $from);
560
-    }
561
-
562
-
563
-    /**
564
-     * Gets priority
565
-     *
566
-     * @return int
567
-     */
568
-    public function priority()
569
-    {
570
-        return $this->get('MSG_priority');
571
-    }
572
-
573
-
574
-    /**
575
-     * Sets priority
576
-     * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
577
-     * this method calls the send_now method to verify that.
578
-     *
579
-     * @param int $priority
580
-     */
581
-    public function set_priority($priority)
582
-    {
583
-        $priority = $this->send_now() ? EEM_Message::priority_high : $priority;
584
-        parent::set('MSG_priority', $priority);
585
-    }
586
-
587
-
588
-    /**
589
-     * Overrides parent::set method so we can capture any sets for priority.
590
-     *
591
-     * @see parent::set() for phpdocs
592
-     * @param string $field_name
593
-     * @param mixed  $field_value
594
-     * @param bool   $use_default
595
-     * @throws EE_Error
596
-     */
597
-    public function set($field_name, $field_value, $use_default = false)
598
-    {
599
-        if ($field_name === 'MSG_priority') {
600
-            $this->set_priority($field_value);
601
-        }
602
-        parent::set($field_name, $field_value, $use_default);
603
-    }
604
-
605
-
606
-    /**
607
-     * @return bool
608
-     * @throws \EE_Error
609
-     */
610
-    public function send_now()
611
-    {
612
-        $send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high
613
-            : $this->priority();
614
-        return $send_now === EEM_Message::priority_high ? true : false;
615
-    }
616
-
617
-
618
-    /**
619
-     * Gets STS_ID
620
-     *
621
-     * @return string
622
-     */
623
-    public function STS_ID()
624
-    {
625
-        return $this->get('STS_ID');
626
-    }
627
-
628
-
629
-    /**
630
-     * Sets STS_ID
631
-     *
632
-     * @param string $STS_ID
633
-     */
634
-    public function set_STS_ID($STS_ID)
635
-    {
636
-        $this->set('STS_ID', $STS_ID);
637
-    }
638
-
639
-
640
-    /**
641
-     * Gets created
642
-     *
643
-     * @return string
644
-     */
645
-    public function created()
646
-    {
647
-        return $this->get('MSG_created');
648
-    }
649
-
650
-
651
-    /**
652
-     * Sets created
653
-     *
654
-     * @param string $created
655
-     */
656
-    public function set_created($created)
657
-    {
658
-        $this->set('MSG_created', $created);
659
-    }
660
-
661
-
662
-    /**
663
-     * Gets modified
664
-     *
665
-     * @return string
666
-     */
667
-    public function modified()
668
-    {
669
-        return $this->get('MSG_modified');
670
-    }
671
-
672
-
673
-    /**
674
-     * Sets modified
675
-     *
676
-     * @param string $modified
677
-     */
678
-    public function set_modified($modified)
679
-    {
680
-        $this->set('MSG_modified', $modified);
681
-    }
682
-
683
-
684
-    /**
685
-     * Sets generation data for this message.
686
-     *
687
-     * @param mixed $data
688
-     */
689
-    public function set_generation_data($data)
690
-    {
691
-        $this->set_field_or_extra_meta('MSG_generation_data', $data);
692
-    }
693
-
694
-
695
-    /**
696
-     * Returns any set generation data for this message.
697
-     *
698
-     * @return mixed|null
699
-     */
700
-    public function get_generation_data()
701
-    {
702
-        return $this->get_field_or_extra_meta('MSG_generation_data');
703
-    }
704
-
705
-
706
-    /**
707
-     * Gets any error message.
708
-     *
709
-     * @return mixed|null
710
-     */
711
-    public function error_message()
712
-    {
713
-        return $this->get_field_or_extra_meta('MSG_error');
714
-    }
715
-
716
-
717
-    /**
718
-     * Sets an error message.
719
-     *
720
-     * @param $message
721
-     * @return bool|int
722
-     */
723
-    public function set_error_message($message)
724
-    {
725
-        return $this->set_field_or_extra_meta('MSG_error', $message);
726
-    }
727
-
728
-
729
-    /**
730
-     * This retrieves the associated template pack with this message.
731
-     *
732
-     * @return EE_Messages_Template_Pack | null
733
-     */
734
-    public function get_template_pack()
735
-    {
736
-        /**
737
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738
-         */
739
-        if (! empty($this->template_pack)) {
740
-            return $this->template_pack;
741
-        }
742
-        /** @type EE_Message_Template_Group $grp */
743
-        $grp = $this->get_first_related('Message_Template_Group');
744
-        // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
-        if (! $grp instanceof EE_Message_Template_Group) {
746
-            $grp = EEM_Message_Template_Group::instance()->get_one(
747
-                array(
748
-                    array(
749
-                        'MTP_messenger'    => $this->messenger(),
750
-                        'MTP_message_type' => $this->message_type(),
751
-                        'MTP_is_global'    => true,
752
-                    ),
753
-                )
754
-            );
755
-        }
756
-
757
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
758
-    }
759
-
760
-
761
-    /**
762
-     * Retrieves the variation used for generating this message.
763
-     *
764
-     * @return string
765
-     */
766
-    public function get_template_pack_variation()
767
-    {
768
-        /**
769
-         * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770
-         */
771
-        if (! empty($this->template_variation)) {
772
-            return $this->template_variation;
773
-        }
774
-
775
-        /** @type EE_Message_Template_Group $grp */
776
-        $grp = $this->get_first_related('Message_Template_Group');
777
-
778
-        // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
-        if (! $grp instanceof EE_Message_Template_Group) {
780
-            $grp = EEM_Message_Template_Group::instance()->get_one(
781
-                array(
782
-                    array(
783
-                        'MTP_messenger'    => $this->messenger(),
784
-                        'MTP_message_type' => $this->message_type(),
785
-                        'MTP_is_global'    => true,
786
-                    ),
787
-                )
788
-            );
789
-        }
790
-
791
-        return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
792
-    }
793
-
794
-    /**
795
-     * Return the link to the admin details for the object.
796
-     *
797
-     * @return string
798
-     */
799
-    public function get_admin_details_link()
800
-    {
801
-        EE_Registry::instance()->load_helper('URL');
802
-        EE_Registry::instance()->load_helper('MSG_Template');
803
-        switch ($this->STS_ID()) {
804
-            case EEM_Message::status_failed:
805
-            case EEM_Message::status_debug_only:
806
-                return EEH_MSG_Template::generate_error_display_trigger($this);
807
-                break;
808
-
809
-            case EEM_Message::status_sent:
810
-                return EEH_MSG_Template::generate_browser_trigger($this);
811
-                break;
812
-
813
-            default:
814
-                return '';
815
-        }
816
-    }
817
-
818
-    /**
819
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
820
-     *
821
-     * @return string
822
-     */
823
-    public function get_admin_edit_link()
824
-    {
825
-        return $this->get_admin_details_link();
826
-    }
827
-
828
-    /**
829
-     * Returns the link to a settings page for the object.
830
-     *
831
-     * @return string
832
-     */
833
-    public function get_admin_settings_link()
834
-    {
835
-        EE_Registry::instance()->load_helper('URL');
836
-        return EEH_URL::add_query_args_and_nonce(
837
-            array(
838
-                'page'   => 'espresso_messages',
839
-                'action' => 'settings',
840
-            ),
841
-            admin_url('admin.php')
842
-        );
843
-    }
844
-
845
-    /**
846
-     * Returns the link to the "overview" for the object (typically the "list table" view).
847
-     *
848
-     * @return string
849
-     */
850
-    public function get_admin_overview_link()
851
-    {
852
-        EE_Registry::instance()->load_helper('URL');
853
-        return EEH_URL::add_query_args_and_nonce(
854
-            array(
855
-                'page'   => 'espresso_messages',
856
-                'action' => 'default',
857
-            ),
858
-            admin_url('admin.php')
859
-        );
860
-    }
861
-
862
-
863
-    /**
864
-     * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
865
-     * it.
866
-     * Note this also SAVES the current message object to the db because it adds an error message to accompany the
867
-     * status.
868
-     *
869
-     */
870
-    public function set_messenger_is_executing()
871
-    {
872
-        $this->set_STS_ID(EEM_Message::status_messenger_executing);
873
-        $this->set_error_message(
874
-            esc_html__(
875
-                'A message with this status indicates that there was a problem that occurred while the message was being
13
+	/**
14
+	 * @deprecated 4.9.0  Added for backward compat with add-on's
15
+	 * @type null
16
+	 */
17
+	public $template_pack;
18
+
19
+	/**
20
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
21
+	 * @type null
22
+	 */
23
+	public $template_variation;
24
+
25
+	/**
26
+	 * @deprecated 4.9.0 Added for backward compat with add-on's
27
+	 * @type string
28
+	 */
29
+	public $content = '';
30
+
31
+
32
+	/**
33
+	 * @type EE_messenger $_messenger
34
+	 */
35
+	protected $_messenger = null;
36
+
37
+	/**
38
+	 * @type EE_message_type $_message_type
39
+	 */
40
+	protected $_message_type = null;
41
+
42
+
43
+	/**
44
+	 * @param array  $props_n_values
45
+	 * @param string $timezone
46
+	 * @param array  $date_formats incoming date formats in an array.  First value is the date_format, second is time
47
+	 *                             format.
48
+	 * @return EE_Message
49
+	 */
50
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
51
+	{
52
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
53
+		// if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
+		if (! $has_object) {
55
+			EE_Registry::instance()->load_helper('URL');
56
+			$props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57
+		}
58
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values
64
+	 * @param string $timezone
65
+	 * @return EE_Message
66
+	 */
67
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
+	{
69
+		return new self($props_n_values, true, $timezone);
70
+	}
71
+
72
+
73
+	/**
74
+	 * Gets MSG_token
75
+	 *
76
+	 * @return int
77
+	 */
78
+	public function MSG_token()
79
+	{
80
+		return $this->get('MSG_token');
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets MSG_token
86
+	 *
87
+	 * @param int $MSG_token
88
+	 */
89
+	public function set_MSG_token($MSG_token)
90
+	{
91
+		$this->set('MSG_token', $MSG_token);
92
+	}
93
+
94
+
95
+	/**
96
+	 * Gets GRP_ID
97
+	 *
98
+	 * @return int
99
+	 */
100
+	public function GRP_ID()
101
+	{
102
+		return $this->get('GRP_ID');
103
+	}
104
+
105
+
106
+	/**
107
+	 * Sets GRP_ID
108
+	 *
109
+	 * @param int $GRP_ID
110
+	 */
111
+	public function set_GRP_ID($GRP_ID)
112
+	{
113
+		$this->set('GRP_ID', $GRP_ID);
114
+	}
115
+
116
+
117
+	/**
118
+	 * Gets TXN_ID
119
+	 *
120
+	 * @return int
121
+	 */
122
+	public function TXN_ID()
123
+	{
124
+		return $this->get('TXN_ID');
125
+	}
126
+
127
+
128
+	/**
129
+	 * Sets TXN_ID
130
+	 *
131
+	 * @param int $TXN_ID
132
+	 */
133
+	public function set_TXN_ID($TXN_ID)
134
+	{
135
+		$this->set('TXN_ID', $TXN_ID);
136
+	}
137
+
138
+
139
+	/**
140
+	 * Gets messenger
141
+	 *
142
+	 * @return string
143
+	 */
144
+	public function messenger()
145
+	{
146
+		return $this->get('MSG_messenger');
147
+	}
148
+
149
+
150
+	/**
151
+	 * Sets messenger
152
+	 *
153
+	 * @param string $messenger
154
+	 */
155
+	public function set_messenger($messenger)
156
+	{
157
+		$this->set('MSG_messenger', $messenger);
158
+	}
159
+
160
+
161
+	/**
162
+	 * Returns corresponding messenger object for the set messenger on this message
163
+	 *
164
+	 * @return EE_messenger | null
165
+	 */
166
+	public function messenger_object()
167
+	{
168
+		return $this->_messenger;
169
+	}
170
+
171
+
172
+	/**
173
+	 * Sets messenger
174
+	 *
175
+	 * @param EE_messenger $messenger
176
+	 */
177
+	public function set_messenger_object(EE_messenger $messenger)
178
+	{
179
+		$this->_messenger = $messenger;
180
+	}
181
+
182
+
183
+	/**
184
+	 * validates messenger
185
+	 *
186
+	 * @param bool $throw_exceptions
187
+	 * @return bool
188
+	 * @throws \EE_Error
189
+	 */
190
+	public function valid_messenger($throw_exceptions = false)
191
+	{
192
+		if ($this->_messenger instanceof EE_messenger) {
193
+			return true;
194
+		}
195
+		if ($throw_exceptions) {
196
+			throw new EE_Error(
197
+				sprintf(
198
+					__(
199
+						'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
200
+						'event_espresso'
201
+					),
202
+					$this->messenger()
203
+				)
204
+			);
205
+		}
206
+		return false;
207
+	}
208
+
209
+
210
+	/**
211
+	 * This returns the set localized label for the messenger on this message.
212
+	 * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved
213
+	 * with this message.
214
+	 *
215
+	 * @param   bool $plural whether to return the plural label or not.
216
+	 * @return string
217
+	 */
218
+	public function messenger_label($plural = false)
219
+	{
220
+		$label_type = $plural ? 'plural' : 'singular';
221
+		$messenger = $this->messenger_object();
222
+		return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets message_type
228
+	 *
229
+	 * @return string
230
+	 */
231
+	public function message_type()
232
+	{
233
+		return $this->get('MSG_message_type');
234
+	}
235
+
236
+
237
+	/**
238
+	 * Sets message_type
239
+	 *
240
+	 * @param string $message_type
241
+	 */
242
+	public function set_message_type($message_type)
243
+	{
244
+		$this->set('MSG_message_type', $message_type);
245
+	}
246
+
247
+
248
+	/**
249
+	 * Returns the message type object for the set message type on this message
250
+	 *
251
+	 * @return EE_message_type | null
252
+	 */
253
+	public function message_type_object()
254
+	{
255
+		return $this->_message_type;
256
+	}
257
+
258
+
259
+	/**
260
+	 * Sets message_type
261
+	 *
262
+	 * @param EE_message_type $message_type
263
+	 * @param bool            $set_priority   This indicates whether to set the priority to whatever the priority is on
264
+	 *                                        the message type or not.
265
+	 */
266
+	public function set_message_type_object(EE_message_type $message_type, $set_priority = false)
267
+	{
268
+		$this->_message_type = $message_type;
269
+		if ($set_priority) {
270
+			$this->set_priority($this->_message_type->get_priority());
271
+		}
272
+	}
273
+
274
+
275
+	/**
276
+	 * validates message_type
277
+	 *
278
+	 * @param bool $throw_exceptions
279
+	 * @return bool
280
+	 * @throws \EE_Error
281
+	 */
282
+	public function valid_message_type($throw_exceptions = false)
283
+	{
284
+		if ($this->_message_type instanceof EE_message_type) {
285
+			return true;
286
+		}
287
+		if ($throw_exceptions) {
288
+			throw new EE_Error(
289
+				sprintf(
290
+					__(
291
+						'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.',
292
+						'event_espresso'
293
+					),
294
+					$this->message_type()
295
+				)
296
+			);
297
+		}
298
+		return false;
299
+	}
300
+
301
+
302
+	/**
303
+	 * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects).
304
+	 *
305
+	 * @param bool $throw_exceptions
306
+	 * @return bool
307
+	 * @throws \EE_Error
308
+	 */
309
+	public function is_valid($throw_exceptions = false)
310
+	{
311
+		if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) {
312
+			return true;
313
+		}
314
+		return false;
315
+	}
316
+
317
+
318
+	/**
319
+	 * This validates whether the internal messenger and message type objects are valid for sending.
320
+	 * Three checks are done:
321
+	 * 1. There is a valid messenger object.
322
+	 * 2. There is a valid message type object.
323
+	 * 3. The message type object is active for the messenger.
324
+	 *
325
+	 * @throws EE_Error  But only if $throw_exceptions is set to true.
326
+	 * @param bool $throw_exceptions
327
+	 * @return bool
328
+	 */
329
+	public function is_valid_for_sending_or_generation($throw_exceptions = false)
330
+	{
331
+		$valid = false;
332
+		if ($this->is_valid($throw_exceptions)) {
333
+			/** @var EE_Message_Resource_Manager $message_resource_manager */
334
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
335
+			$valid = $message_resource_manager->is_message_type_active_for_messenger(
336
+				$this->messenger(),
337
+				$this->message_type()
338
+			);
339
+			if (! $valid && $throw_exceptions) {
340
+				throw new EE_Error(
341
+					sprintf(
342
+						__(
343
+							'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.',
344
+							'event_espresso'
345
+						),
346
+						$this->message_type(),
347
+						$this->messenger()
348
+					)
349
+				);
350
+			}
351
+		}
352
+		return $valid;
353
+	}
354
+
355
+
356
+	/**
357
+	 * This returns the set localized label for the message type on this message.
358
+	 * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved
359
+	 * with this message.
360
+	 *
361
+	 * @param   bool $plural whether to return the plural label or not.
362
+	 * @return string
363
+	 */
364
+	public function message_type_label($plural = false)
365
+	{
366
+		$label_type = $plural ? 'plural' : 'singular';
367
+		$message_type = $this->message_type_object();
368
+		return $message_type instanceof EE_message_type
369
+			? $message_type->label[ $label_type ]
370
+			: str_replace(
371
+				'_',
372
+				' ',
373
+				$this->message_type()
374
+			);
375
+	}
376
+
377
+
378
+	/**
379
+	 * Gets context
380
+	 *
381
+	 * @return string
382
+	 */
383
+	public function context()
384
+	{
385
+		return $this->get('MSG_context');
386
+	}
387
+
388
+
389
+	/**
390
+	 * This returns the corresponding localized label for the given context slug, if possible from installed message
391
+	 * types. Otherwise, this will just return the set context slug on this object.
392
+	 *
393
+	 * @return string
394
+	 */
395
+	public function context_label()
396
+	{
397
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
398
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399
+		$contexts = $message_resource_manager->get_all_contexts();
400
+		return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
401
+	}
402
+
403
+
404
+	/**
405
+	 * Sets context
406
+	 *
407
+	 * @param string $context
408
+	 */
409
+	public function set_context($context)
410
+	{
411
+		$this->set('MSG_context', $context);
412
+	}
413
+
414
+
415
+	/**
416
+	 * Gets recipient_ID
417
+	 *
418
+	 * @return int
419
+	 */
420
+	public function recipient_ID()
421
+	{
422
+		return $this->get('MSG_recipient_ID');
423
+	}
424
+
425
+
426
+	/**
427
+	 * Sets recipient_ID
428
+	 *
429
+	 * @param string $recipient_ID
430
+	 */
431
+	public function set_recipient_ID($recipient_ID)
432
+	{
433
+		$this->set('MSG_recipient_ID', $recipient_ID);
434
+	}
435
+
436
+
437
+	/**
438
+	 * Gets recipient_type
439
+	 *
440
+	 * @return string
441
+	 */
442
+	public function recipient_type()
443
+	{
444
+		return $this->get('MSG_recipient_type');
445
+	}
446
+
447
+
448
+	/**
449
+	 * Return the related object matching the recipient type and ID.
450
+	 *
451
+	 * @return EE_Base_Class | null
452
+	 */
453
+	public function recipient_object()
454
+	{
455
+		if (! $this->recipient_type() || ! $this->recipient_ID()) {
456
+			return null;
457
+		}
458
+
459
+		return $this->get_first_related($this->recipient_type());
460
+	}
461
+
462
+
463
+	/**
464
+	 * Sets recipient_type
465
+	 *
466
+	 * @param string $recipient_type
467
+	 */
468
+	public function set_recipient_type($recipient_type)
469
+	{
470
+		$this->set('MSG_recipient_type', $recipient_type);
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets content
476
+	 *
477
+	 * @return string
478
+	 */
479
+	public function content()
480
+	{
481
+		return $this->get('MSG_content');
482
+	}
483
+
484
+
485
+	/**
486
+	 * Sets content
487
+	 *
488
+	 * @param string $content
489
+	 */
490
+	public function set_content($content)
491
+	{
492
+		$this->set('MSG_content', $content);
493
+	}
494
+
495
+
496
+	/**
497
+	 * Gets subject
498
+	 *
499
+	 * @return string
500
+	 */
501
+	public function subject()
502
+	{
503
+		return $this->get('MSG_subject');
504
+	}
505
+
506
+
507
+	/**
508
+	 * Sets subject
509
+	 *
510
+	 * @param string $subject
511
+	 */
512
+	public function set_subject($subject)
513
+	{
514
+		$this->set('MSG_subject', $subject);
515
+	}
516
+
517
+
518
+	/**
519
+	 * Gets to
520
+	 *
521
+	 * @return string
522
+	 */
523
+	public function to()
524
+	{
525
+		$to = $this->get('MSG_to');
526
+		return empty($to) ? __('No recipient', 'event_espresso') : $to;
527
+	}
528
+
529
+
530
+	/**
531
+	 * Sets to
532
+	 *
533
+	 * @param string $to
534
+	 */
535
+	public function set_to($to)
536
+	{
537
+		$this->set('MSG_to', $to);
538
+	}
539
+
540
+
541
+	/**
542
+	 * Gets from
543
+	 *
544
+	 * @return string
545
+	 */
546
+	public function from()
547
+	{
548
+		return $this->get('MSG_from');
549
+	}
550
+
551
+
552
+	/**
553
+	 * Sets from
554
+	 *
555
+	 * @param string $from
556
+	 */
557
+	public function set_from($from)
558
+	{
559
+		$this->set('MSG_from', $from);
560
+	}
561
+
562
+
563
+	/**
564
+	 * Gets priority
565
+	 *
566
+	 * @return int
567
+	 */
568
+	public function priority()
569
+	{
570
+		return $this->get('MSG_priority');
571
+	}
572
+
573
+
574
+	/**
575
+	 * Sets priority
576
+	 * Note.  Send Now Messengers always override any priority that may be set on a Message.  So
577
+	 * this method calls the send_now method to verify that.
578
+	 *
579
+	 * @param int $priority
580
+	 */
581
+	public function set_priority($priority)
582
+	{
583
+		$priority = $this->send_now() ? EEM_Message::priority_high : $priority;
584
+		parent::set('MSG_priority', $priority);
585
+	}
586
+
587
+
588
+	/**
589
+	 * Overrides parent::set method so we can capture any sets for priority.
590
+	 *
591
+	 * @see parent::set() for phpdocs
592
+	 * @param string $field_name
593
+	 * @param mixed  $field_value
594
+	 * @param bool   $use_default
595
+	 * @throws EE_Error
596
+	 */
597
+	public function set($field_name, $field_value, $use_default = false)
598
+	{
599
+		if ($field_name === 'MSG_priority') {
600
+			$this->set_priority($field_value);
601
+		}
602
+		parent::set($field_name, $field_value, $use_default);
603
+	}
604
+
605
+
606
+	/**
607
+	 * @return bool
608
+	 * @throws \EE_Error
609
+	 */
610
+	public function send_now()
611
+	{
612
+		$send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high
613
+			: $this->priority();
614
+		return $send_now === EEM_Message::priority_high ? true : false;
615
+	}
616
+
617
+
618
+	/**
619
+	 * Gets STS_ID
620
+	 *
621
+	 * @return string
622
+	 */
623
+	public function STS_ID()
624
+	{
625
+		return $this->get('STS_ID');
626
+	}
627
+
628
+
629
+	/**
630
+	 * Sets STS_ID
631
+	 *
632
+	 * @param string $STS_ID
633
+	 */
634
+	public function set_STS_ID($STS_ID)
635
+	{
636
+		$this->set('STS_ID', $STS_ID);
637
+	}
638
+
639
+
640
+	/**
641
+	 * Gets created
642
+	 *
643
+	 * @return string
644
+	 */
645
+	public function created()
646
+	{
647
+		return $this->get('MSG_created');
648
+	}
649
+
650
+
651
+	/**
652
+	 * Sets created
653
+	 *
654
+	 * @param string $created
655
+	 */
656
+	public function set_created($created)
657
+	{
658
+		$this->set('MSG_created', $created);
659
+	}
660
+
661
+
662
+	/**
663
+	 * Gets modified
664
+	 *
665
+	 * @return string
666
+	 */
667
+	public function modified()
668
+	{
669
+		return $this->get('MSG_modified');
670
+	}
671
+
672
+
673
+	/**
674
+	 * Sets modified
675
+	 *
676
+	 * @param string $modified
677
+	 */
678
+	public function set_modified($modified)
679
+	{
680
+		$this->set('MSG_modified', $modified);
681
+	}
682
+
683
+
684
+	/**
685
+	 * Sets generation data for this message.
686
+	 *
687
+	 * @param mixed $data
688
+	 */
689
+	public function set_generation_data($data)
690
+	{
691
+		$this->set_field_or_extra_meta('MSG_generation_data', $data);
692
+	}
693
+
694
+
695
+	/**
696
+	 * Returns any set generation data for this message.
697
+	 *
698
+	 * @return mixed|null
699
+	 */
700
+	public function get_generation_data()
701
+	{
702
+		return $this->get_field_or_extra_meta('MSG_generation_data');
703
+	}
704
+
705
+
706
+	/**
707
+	 * Gets any error message.
708
+	 *
709
+	 * @return mixed|null
710
+	 */
711
+	public function error_message()
712
+	{
713
+		return $this->get_field_or_extra_meta('MSG_error');
714
+	}
715
+
716
+
717
+	/**
718
+	 * Sets an error message.
719
+	 *
720
+	 * @param $message
721
+	 * @return bool|int
722
+	 */
723
+	public function set_error_message($message)
724
+	{
725
+		return $this->set_field_or_extra_meta('MSG_error', $message);
726
+	}
727
+
728
+
729
+	/**
730
+	 * This retrieves the associated template pack with this message.
731
+	 *
732
+	 * @return EE_Messages_Template_Pack | null
733
+	 */
734
+	public function get_template_pack()
735
+	{
736
+		/**
737
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738
+		 */
739
+		if (! empty($this->template_pack)) {
740
+			return $this->template_pack;
741
+		}
742
+		/** @type EE_Message_Template_Group $grp */
743
+		$grp = $this->get_first_related('Message_Template_Group');
744
+		// if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
+		if (! $grp instanceof EE_Message_Template_Group) {
746
+			$grp = EEM_Message_Template_Group::instance()->get_one(
747
+				array(
748
+					array(
749
+						'MTP_messenger'    => $this->messenger(),
750
+						'MTP_message_type' => $this->message_type(),
751
+						'MTP_is_global'    => true,
752
+					),
753
+				)
754
+			);
755
+		}
756
+
757
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null;
758
+	}
759
+
760
+
761
+	/**
762
+	 * Retrieves the variation used for generating this message.
763
+	 *
764
+	 * @return string
765
+	 */
766
+	public function get_template_pack_variation()
767
+	{
768
+		/**
769
+		 * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770
+		 */
771
+		if (! empty($this->template_variation)) {
772
+			return $this->template_variation;
773
+		}
774
+
775
+		/** @type EE_Message_Template_Group $grp */
776
+		$grp = $this->get_first_related('Message_Template_Group');
777
+
778
+		// if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
+		if (! $grp instanceof EE_Message_Template_Group) {
780
+			$grp = EEM_Message_Template_Group::instance()->get_one(
781
+				array(
782
+					array(
783
+						'MTP_messenger'    => $this->messenger(),
784
+						'MTP_message_type' => $this->message_type(),
785
+						'MTP_is_global'    => true,
786
+					),
787
+				)
788
+			);
789
+		}
790
+
791
+		return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : '';
792
+	}
793
+
794
+	/**
795
+	 * Return the link to the admin details for the object.
796
+	 *
797
+	 * @return string
798
+	 */
799
+	public function get_admin_details_link()
800
+	{
801
+		EE_Registry::instance()->load_helper('URL');
802
+		EE_Registry::instance()->load_helper('MSG_Template');
803
+		switch ($this->STS_ID()) {
804
+			case EEM_Message::status_failed:
805
+			case EEM_Message::status_debug_only:
806
+				return EEH_MSG_Template::generate_error_display_trigger($this);
807
+				break;
808
+
809
+			case EEM_Message::status_sent:
810
+				return EEH_MSG_Template::generate_browser_trigger($this);
811
+				break;
812
+
813
+			default:
814
+				return '';
815
+		}
816
+	}
817
+
818
+	/**
819
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
820
+	 *
821
+	 * @return string
822
+	 */
823
+	public function get_admin_edit_link()
824
+	{
825
+		return $this->get_admin_details_link();
826
+	}
827
+
828
+	/**
829
+	 * Returns the link to a settings page for the object.
830
+	 *
831
+	 * @return string
832
+	 */
833
+	public function get_admin_settings_link()
834
+	{
835
+		EE_Registry::instance()->load_helper('URL');
836
+		return EEH_URL::add_query_args_and_nonce(
837
+			array(
838
+				'page'   => 'espresso_messages',
839
+				'action' => 'settings',
840
+			),
841
+			admin_url('admin.php')
842
+		);
843
+	}
844
+
845
+	/**
846
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
847
+	 *
848
+	 * @return string
849
+	 */
850
+	public function get_admin_overview_link()
851
+	{
852
+		EE_Registry::instance()->load_helper('URL');
853
+		return EEH_URL::add_query_args_and_nonce(
854
+			array(
855
+				'page'   => 'espresso_messages',
856
+				'action' => 'default',
857
+			),
858
+			admin_url('admin.php')
859
+		);
860
+	}
861
+
862
+
863
+	/**
864
+	 * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for
865
+	 * it.
866
+	 * Note this also SAVES the current message object to the db because it adds an error message to accompany the
867
+	 * status.
868
+	 *
869
+	 */
870
+	public function set_messenger_is_executing()
871
+	{
872
+		$this->set_STS_ID(EEM_Message::status_messenger_executing);
873
+		$this->set_error_message(
874
+			esc_html__(
875
+				'A message with this status indicates that there was a problem that occurred while the message was being
876 876
                 processed by the messenger.  It is still possible that the message was sent successfully, but at some
877 877
                 point during the processing there was a failure.  This usually is indicative of a timeout issue with PHP 
878 878
                 or memory limits being reached.  If you see this repeatedly you may want to consider upgrading the memory 
879 879
                 available to PHP on your server.',
880
-                'event_espresso'
881
-            )
882
-        );
883
-    }
880
+				'event_espresso'
881
+			)
882
+		);
883
+	}
884 884
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
     {
52 52
         $has_object = parent::_check_for_object($props_n_values, __CLASS__);
53 53
         // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db.
54
-        if (! $has_object) {
54
+        if ( ! $has_object) {
55 55
             EE_Registry::instance()->load_helper('URL');
56 56
             $props_n_values['MSG_token'] = EEH_URL::generate_unique_token();
57 57
         }
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
     {
220 220
         $label_type = $plural ? 'plural' : 'singular';
221 221
         $messenger = $this->messenger_object();
222
-        return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger();
222
+        return $messenger instanceof EE_messenger ? $messenger->label[$label_type] : $this->messenger();
223 223
     }
224 224
 
225 225
 
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
                 $this->messenger(),
337 337
                 $this->message_type()
338 338
             );
339
-            if (! $valid && $throw_exceptions) {
339
+            if ( ! $valid && $throw_exceptions) {
340 340
                 throw new EE_Error(
341 341
                     sprintf(
342 342
                         __(
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
         $label_type = $plural ? 'plural' : 'singular';
367 367
         $message_type = $this->message_type_object();
368 368
         return $message_type instanceof EE_message_type
369
-            ? $message_type->label[ $label_type ]
369
+            ? $message_type->label[$label_type]
370 370
             : str_replace(
371 371
                 '_',
372 372
                 ' ',
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
         /** @type EE_Message_Resource_Manager $message_resource_manager */
398 398
         $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
399 399
         $contexts = $message_resource_manager->get_all_contexts();
400
-        return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context();
400
+        return isset($contexts[$this->context()]) ? $contexts[$this->context()] : $this->context();
401 401
     }
402 402
 
403 403
 
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
      */
453 453
     public function recipient_object()
454 454
     {
455
-        if (! $this->recipient_type() || ! $this->recipient_ID()) {
455
+        if ( ! $this->recipient_type() || ! $this->recipient_ID()) {
456 456
             return null;
457 457
         }
458 458
 
@@ -736,13 +736,13 @@  discard block
 block discarded – undo
736 736
         /**
737 737
          * This is deprecated functionality that will be removed eventually but included here now for backward compat.
738 738
          */
739
-        if (! empty($this->template_pack)) {
739
+        if ( ! empty($this->template_pack)) {
740 740
             return $this->template_pack;
741 741
         }
742 742
         /** @type EE_Message_Template_Group $grp */
743 743
         $grp = $this->get_first_related('Message_Template_Group');
744 744
         // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
745
-        if (! $grp instanceof EE_Message_Template_Group) {
745
+        if ( ! $grp instanceof EE_Message_Template_Group) {
746 746
             $grp = EEM_Message_Template_Group::instance()->get_one(
747 747
                 array(
748 748
                     array(
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
         /**
769 769
          * This is deprecated functionality that will be removed eventually but included here now for backward compat.
770 770
          */
771
-        if (! empty($this->template_variation)) {
771
+        if ( ! empty($this->template_variation)) {
772 772
             return $this->template_variation;
773 773
         }
774 774
 
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
         $grp = $this->get_first_related('Message_Template_Group');
777 777
 
778 778
         // if no group then let's try to get the first related group by internal messenger and message type (will use global grp).
779
-        if (! $grp instanceof EE_Message_Template_Group) {
779
+        if ( ! $grp instanceof EE_Message_Template_Group) {
780 780
             $grp = EEM_Message_Template_Group::instance()->get_one(
781 781
                 array(
782 782
                     array(
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Queue.lib.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -603,7 +603,7 @@
 block discarded – undo
603 603
      * @param EE_Message      $message
604 604
      * @param EE_messenger    $messenger
605 605
      * @param EE_message_type $message_type
606
-     * @param                 $test_send
606
+     * @param                 boolean $test_send
607 607
      * @return bool   true means all went well, false means, not so much.
608 608
      */
609 609
     protected function _do_preview(
Please login to merge, or discard this patch.
Indentation   +685 added lines, -685 removed lines patch added patch discarded remove patch
@@ -14,689 +14,689 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * @type    string  reference for sending action
19
-     */
20
-    const action_sending = 'sending';
21
-
22
-    /**
23
-     * @type    string  reference for generation action
24
-     */
25
-    const action_generating = 'generation';
26
-
27
-
28
-    /**
29
-     * @type EE_Message_Repository $_message_repository
30
-     */
31
-    protected $_message_repository;
32
-
33
-    /**
34
-     * Sets the limit of how many messages are generated per process.
35
-     *
36
-     * @type int
37
-     */
38
-    protected $_batch_count;
39
-
40
-
41
-    /**
42
-     * This is an array of cached queue items being stored in this object.
43
-     * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
44
-     * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
45
-     *
46
-     * @type EE_Message[]
47
-     */
48
-    protected $_cached_queue_items;
49
-
50
-    /**
51
-     * Tracks the number of unsaved queue items.
52
-     *
53
-     * @type int
54
-     */
55
-    protected $_unsaved_count = 0;
56
-
57
-    /**
58
-     * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
59
-     * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
60
-     *
61
-     * @type array
62
-     */
63
-    protected $_did_hook = array();
64
-
65
-
66
-    /**
67
-     * Constructor.
68
-     * Setup all the initial properties and load a EE_Message_Repository.
69
-     *
70
-     * @param \EE_Message_Repository $message_repository
71
-     */
72
-    public function __construct(EE_Message_Repository $message_repository)
73
-    {
74
-        $this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
75
-        $this->_message_repository = $message_repository;
76
-    }
77
-
78
-
79
-    /**
80
-     * Add a EE_Message object to the queue
81
-     *
82
-     * @param EE_Message $message
83
-     * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
84
-     *                                 object is persisted, this data will be saved on an extra_meta object related to
85
-     *                                 EE_Message.
86
-     * @param  bool      $preview      Whether this EE_Message represents a preview or not.
87
-     * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
88
-     *                                 use the messenger send method but typically is based on preview data.
89
-     * @return bool          Whether the message was successfully added to the repository or not.
90
-     */
91
-    public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
92
-    {
93
-        $data['preview']   = $preview;
94
-        $data['test_send'] = $test_send;
95
-        return $this->_message_repository->add($message, $data);
96
-    }
97
-
98
-
99
-    /**
100
-     * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
101
-     *
102
-     * @param EE_Message $message The message to detach from the queue
103
-     * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
104
-     * @return bool
105
-     */
106
-    public function remove(EE_Message $message, $persist = false)
107
-    {
108
-        if ($persist && $this->_message_repository->current() !== $message) {
109
-            // get pointer on right message
110
-            if ($this->_message_repository->has($message)) {
111
-                $this->_message_repository->rewind();
112
-                while ($this->_message_repository->valid()) {
113
-                    if ($this->_message_repository->current() === $message) {
114
-                        break;
115
-                    }
116
-                    $this->_message_repository->next();
117
-                }
118
-            } else {
119
-                return false;
120
-            }
121
-        }
122
-        return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
123
-    }
124
-
125
-
126
-    /**
127
-     * Persists all queued EE_Message objects to the db.
128
-     *
129
-     * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
130
-     * @return array @see EE_Messages_Repository::saveAll() for return values.
131
-     */
132
-    public function save($do_hooks_only = false)
133
-    {
134
-        return $this->_message_repository->saveAll($do_hooks_only);
135
-    }
136
-
137
-
138
-    /**
139
-     * @return EE_Message_Repository
140
-     */
141
-    public function get_message_repository()
142
-    {
143
-        return $this->_message_repository;
144
-    }
145
-
146
-
147
-    /**
148
-     * This does the following things:
149
-     * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
150
-     * false).
151
-     * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
152
-     * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
153
-     * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
154
-     * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
155
-     * removed.
156
-     *
157
-     * @return bool  true if successfully retrieved batch, false no batch ready.
158
-     */
159
-    public function get_batch_to_generate()
160
-    {
161
-        if ($this->is_locked(EE_Messages_Queue::action_generating)) {
162
-            return false;
163
-        }
164
-
165
-        // lock batch generation to prevent race conditions.
166
-        $this->lock_queue(EE_Messages_Queue::action_generating);
167
-
168
-        $query_args = array(
169
-            // key 0 = where conditions
170
-            0          => array('STS_ID' => EEM_Message::status_incomplete),
171
-            'order_by' => $this->_get_priority_orderby(),
172
-            'limit'    => $this->_batch_count,
173
-        );
174
-        $messages   = EEM_Message::instance()->get_all($query_args);
175
-
176
-        if (! $messages) {
177
-            return false; // nothing to generate
178
-        }
179
-
180
-        foreach ($messages as $message) {
181
-            if ($message instanceof EE_Message) {
182
-                $data = $message->all_extra_meta_array();
183
-                $this->add($message, $data);
184
-            }
185
-        }
186
-        return true;
187
-    }
188
-
189
-
190
-    /**
191
-     * This does the following things:
192
-     * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
193
-     * false).
194
-     * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
195
-     * return false.
196
-     * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
197
-     * 3. On success or unsuccessful send, sets status appropriately.
198
-     * 4. Saves messages via the queue
199
-     * 5. Releases lock.
200
-     *
201
-     * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
202
-     *               necessarily mean that all messages were successfully sent.  It just means that this method
203
-     *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
204
-     *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
205
-     *               will also have a saved error message on it to assist with notifying user.
206
-     */
207
-    public function get_to_send_batch_and_send()
208
-    {
209
-        $rate_limit = $this->get_rate_limit();
210
-        if ($rate_limit < 1 || $this->is_locked(EE_Messages_Queue::action_sending)) {
211
-            return false;
212
-        }
213
-
214
-        $this->lock_queue(EE_Messages_Queue::action_sending);
215
-
216
-        $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
217
-
218
-        $query_args = array(
219
-            // key 0 = where conditions
220
-            0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
221
-            'order_by' => $this->_get_priority_orderby(),
222
-            'limit'    => $batch,
223
-        );
224
-
225
-        $messages_to_send = EEM_Message::instance()->get_all($query_args);
226
-
227
-
228
-        // any to send?
229
-        if (! $messages_to_send) {
230
-            $this->unlock_queue(EE_Messages_Queue::action_sending);
231
-            return false;
232
-        }
233
-
234
-        $queue_count = 0;
235
-
236
-        // add to queue.
237
-        foreach ($messages_to_send as $message) {
238
-            if ($message instanceof EE_Message) {
239
-                $queue_count++;
240
-                $this->add($message);
241
-            }
242
-        }
243
-
244
-        // send messages  (this also updates the rate limit)
245
-        $this->execute();
246
-
247
-        // release lock
248
-        $this->unlock_queue(EE_Messages_Queue::action_sending);
249
-        // update rate limit
250
-        $this->set_rate_limit($queue_count);
251
-        return true;
252
-    }
253
-
254
-
255
-    /**
256
-     * Locks the queue so that no other queues can call the "batch" methods.
257
-     *
258
-     * @param   string $type The type of queue being locked.
259
-     */
260
-    public function lock_queue($type = EE_Messages_Queue::action_generating)
261
-    {
262
-        update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
263
-    }
264
-
265
-
266
-    /**
267
-     * Unlocks the queue so that batch methods can be used.
268
-     *
269
-     * @param   string $type The type of queue being unlocked.
270
-     */
271
-    public function unlock_queue($type = EE_Messages_Queue::action_generating)
272
-    {
273
-        delete_option($this->_get_lock_key($type));
274
-    }
275
-
276
-
277
-    /**
278
-     * Retrieve the key used for the lock transient.
279
-     *
280
-     * @param string $type The type of lock.
281
-     * @return string
282
-     */
283
-    protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
284
-    {
285
-        return '_ee_lock_' . $type;
286
-    }
287
-
288
-
289
-    /**
290
-     * Retrieve the expiry time for the lock transient.
291
-     *
292
-     * @param string $type The type of lock
293
-     * @return int   time to expiry in seconds.
294
-     */
295
-    protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
296
-    {
297
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
298
-    }
299
-
300
-
301
-    /**
302
-     * Returns the key used for rate limit transient.
303
-     *
304
-     * @return string
305
-     */
306
-    protected function _get_rate_limit_key()
307
-    {
308
-        return '_ee_rate_limit';
309
-    }
310
-
311
-
312
-    /**
313
-     * Returns the rate limit expiry time.
314
-     *
315
-     * @return int
316
-     */
317
-    protected function _get_rate_limit_expiry()
318
-    {
319
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
320
-    }
321
-
322
-
323
-    /**
324
-     * Returns the default rate limit for sending messages.
325
-     *
326
-     * @return int
327
-     */
328
-    protected function _default_rate_limit()
329
-    {
330
-        return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
331
-    }
332
-
333
-
334
-    /**
335
-     * Return the orderby array for priority.
336
-     *
337
-     * @return array
338
-     */
339
-    protected function _get_priority_orderby()
340
-    {
341
-        return array(
342
-            'MSG_priority' => 'ASC',
343
-            'MSG_modified' => 'DESC',
344
-        );
345
-    }
346
-
347
-
348
-    /**
349
-     * Returns whether batch methods are "locked" or not.
350
-     *
351
-     * @param  string $type The type of lock being checked for.
352
-     * @return bool
353
-     */
354
-    public function is_locked($type = EE_Messages_Queue::action_generating)
355
-    {
356
-        $lock = (int) get_option($this->_get_lock_key($type), 0);
357
-        /**
358
-         * This filters the default is_locked behaviour.
359
-         */
360
-        $is_locked = filter_var(
361
-            apply_filters(
362
-                'FHEE__EE_Messages_Queue__is_locked',
363
-                $lock > time(),
364
-                $this
365
-            ),
366
-            FILTER_VALIDATE_BOOLEAN
367
-        );
368
-
369
-        /**
370
-         * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
371
-         *            Also implemented here because messages processed on the same request should not have any locks applied.
372
-         */
373
-        if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
374
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
375
-        ) {
376
-            $is_locked = false;
377
-        }
378
-
379
-
380
-        return $is_locked;
381
-    }
382
-
383
-
384
-    /**
385
-     * Retrieves the rate limit that may be cached as a transient.
386
-     * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
387
-     *
388
-     * @param bool $return_expiry  If true then return the expiry time not the rate_limit.
389
-     * @return int
390
-     */
391
-    protected function get_rate_limit($return_expiry = false)
392
-    {
393
-        $stored_rate_info = get_option($this->_get_rate_limit_key(), array());
394
-        $rate_limit = isset($stored_rate_info[0])
395
-            ? (int) $stored_rate_info[0]
396
-            : 0;
397
-        $expiry = isset($stored_rate_info[1])
398
-            ? (int) $stored_rate_info[1]
399
-            : 0;
400
-        // set the default for tracking?
401
-        if (empty($stored_rate_info) || time() > $expiry) {
402
-            $expiry = $this->_get_rate_limit_expiry();
403
-            $rate_limit = $this->_default_rate_limit();
404
-            update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry));
405
-        }
406
-        return $return_expiry ? $expiry : $rate_limit;
407
-    }
408
-
409
-
410
-    /**
411
-     * This updates existing rate limit with the new limit which is the old minus the batch.
412
-     *
413
-     * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
414
-     */
415
-    protected function set_rate_limit($batch_completed)
416
-    {
417
-        // first get the most up to date rate limit (in case its expired and reset)
418
-        $rate_limit = $this->get_rate_limit();
419
-        $expiry = $this->get_rate_limit(true);
420
-        $new_limit  = $rate_limit - $batch_completed;
421
-        // updating the transient option directly to avoid resetting the expiry.
422
-
423
-        update_option($this->_get_rate_limit_key(), array($new_limit, $expiry));
424
-    }
425
-
426
-
427
-    /**
428
-     * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
429
-     * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
430
-     * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
431
-     * request running on a queue for the given task.
432
-     *
433
-     * @param string $task     This indicates what type of request is going to be initiated.
434
-     * @param int    $priority This indicates the priority that triggers initiating the request.
435
-     */
436
-    public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
437
-    {
438
-        // determine what status is matched with the priority as part of the trigger conditions.
439
-        $status = $task == 'generate'
440
-            ? EEM_Message::status_incomplete
441
-            : EEM_Message::instance()->stati_indicating_to_send();
442
-        // always make sure we save because either this will get executed immediately on a separate request
443
-        // or remains in the queue for the regularly scheduled queue batch.
444
-        $this->save();
445
-        /**
446
-         * This filter/option allows users to override processing of messages on separate requests and instead have everything
447
-         * happen on the same request.  If this is utilized remember:
448
-         * - message priorities don't matter
449
-         * - existing unprocessed messages in the queue will not get processed unless manually triggered.
450
-         * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
451
-         *   processing happening on the same request.
452
-         * - any race condition protection (locks) are removed because they don't apply when things are processed on
453
-         *   the same request.
454
-         */
455
-        if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
456
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
457
-        ) {
458
-            $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
459
-            if ($messages_processor instanceof EE_Messages_Processor) {
460
-                return $messages_processor->process_immediately_from_queue($this);
461
-            }
462
-            // if we get here then that means the messages processor couldn't be loaded so messages will just remain
463
-            // queued for manual triggering by end user.
464
-        }
465
-
466
-        if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
467
-            EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
468
-        }
469
-    }
470
-
471
-
472
-    /**
473
-     *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
474
-     *
475
-     * @param   bool     $save                    Used to indicate whether to save the message queue after sending
476
-     *                                            (default will save).
477
-     * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
478
-     *                                            what is on the EE_Message object in the queue.
479
-     *                                            For instance, showing the browser view of an email message,
480
-     *                                            or giving a pdf generated view of an html document.
481
-     *                                            This should be an instance of EE_messenger but if you call this
482
-     *                                            method
483
-     *                                            intending it to be a sending messenger but a valid one could not be
484
-     *                                            retrieved then send in an instance of EE_Error that contains the
485
-     *                                            related error message.
486
-     * @param   bool|int $by_priority             When set, this indicates that only messages
487
-     *                                            matching the given priority should be executed.
488
-     * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
489
-     *                                            Also, if the messenger is an request type messenger (or a preview),
490
-     *                                            its entirely possible that the messenger will exit before
491
-     */
492
-    public function execute($save = true, $sending_messenger = null, $by_priority = false)
493
-    {
494
-        $messages_sent   = 0;
495
-        $this->_did_hook = array();
496
-        $this->_message_repository->rewind();
497
-
498
-        while ($this->_message_repository->valid()) {
499
-            $error_messages = array();
500
-            /** @type EE_Message $message */
501
-            $message = $this->_message_repository->current();
502
-            // only process things that are queued for sending
503
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
504
-                $this->_message_repository->next();
505
-                continue;
506
-            }
507
-            // if $by_priority is set and does not match then continue;
508
-            if ($by_priority && $by_priority != $message->priority()) {
509
-                $this->_message_repository->next();
510
-                continue;
511
-            }
512
-            // error checking
513
-            if (! $message->valid_messenger()) {
514
-                $error_messages[] = sprintf(
515
-                    __('The %s messenger is not active at time of sending.', 'event_espresso'),
516
-                    $message->messenger()
517
-                );
518
-            }
519
-            if (! $message->valid_message_type()) {
520
-                $error_messages[] = sprintf(
521
-                    __('The %s message type is not active at the time of sending.', 'event_espresso'),
522
-                    $message->message_type()
523
-                );
524
-            }
525
-            // if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
526
-            // then it will instead be an EE_Error object, so let's check for that
527
-            if ($sending_messenger instanceof EE_Error) {
528
-                $error_messages[] = $sending_messenger->getMessage();
529
-            }
530
-            // if there are no errors, then let's process the message
531
-            if (empty($error_messages)) {
532
-                if ($save) {
533
-                    $message->set_messenger_is_executing();
534
-                }
535
-                if ($this->_process_message($message, $sending_messenger)) {
536
-                    $messages_sent++;
537
-                }
538
-            }
539
-            $this->_set_error_message($message, $error_messages);
540
-            // add modified time
541
-            $message->set_modified(time());
542
-            // we save each message after its processed to make sure its status persists in case PHP times-out or runs
543
-            // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
544
-            if ($save) {
545
-                $message->save();
546
-            }
547
-
548
-            $this->_message_repository->next();
549
-        }
550
-        if ($save) {
551
-            $this->save(true);
552
-        }
553
-        return $messages_sent;
554
-    }
555
-
556
-
557
-    /**
558
-     * _process_message
559
-     *
560
-     * @param EE_Message $message
561
-     * @param mixed      $sending_messenger (optional)
562
-     * @return bool
563
-     */
564
-    protected function _process_message(EE_Message $message, $sending_messenger = null)
565
-    {
566
-        // these *should* have been validated in the execute() method above
567
-        $messenger    = $message->messenger_object();
568
-        $message_type = $message->message_type_object();
569
-        // do actions for sending messenger if it differs from generating messenger and swap values.
570
-        if ($sending_messenger instanceof EE_messenger
571
-            && $messenger instanceof EE_messenger
572
-            && $sending_messenger->name != $messenger->name
573
-        ) {
574
-            $messenger->do_secondary_messenger_hooks($sending_messenger->name);
575
-            $messenger = $sending_messenger;
576
-        }
577
-        // send using messenger, but double check objects
578
-        if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
579
-            // set hook for message type (but only if not using another messenger to send).
580
-            if (! isset($this->_did_hook[ $message_type->name ])) {
581
-                $message_type->do_messenger_hooks($messenger);
582
-                $this->_did_hook[ $message_type->name ] = 1;
583
-            }
584
-            // if preview then use preview method
585
-            return $this->_message_repository->is_preview()
586
-                ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
587
-                : $this->_do_send($message, $messenger, $message_type);
588
-        }
589
-        return false;
590
-    }
591
-
592
-
593
-    /**
594
-     * The intention of this method is to count how many EE_Message objects
595
-     * are in the queue with a given status.
596
-     * Example usage:
597
-     * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
598
-     * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
599
-     *
600
-     * @param array|string $status Stati to check for in queue
601
-     * @return int  Count of EE_Message's matching the given status.
602
-     */
603
-    public function count_STS_in_queue($status)
604
-    {
605
-        $count  = 0;
606
-        $status = is_array($status) ? $status : array($status);
607
-        $this->_message_repository->rewind();
608
-        foreach ($this->_message_repository as $message) {
609
-            if (in_array($message->STS_ID(), $status)) {
610
-                $count++;
611
-            }
612
-        }
613
-        return $count;
614
-    }
615
-
616
-
617
-    /**
618
-     * Executes the get_preview method on the provided messenger.
619
-     *
620
-     * @param EE_Message      $message
621
-     * @param EE_messenger    $messenger
622
-     * @param EE_message_type $message_type
623
-     * @param                 $test_send
624
-     * @return bool   true means all went well, false means, not so much.
625
-     */
626
-    protected function _do_preview(
627
-        EE_Message $message,
628
-        EE_messenger $messenger,
629
-        EE_message_type $message_type,
630
-        $test_send
631
-    ) {
632
-        if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
633
-            if (! $test_send) {
634
-                $message->set_content($preview);
635
-            }
636
-            $message->set_STS_ID(EEM_Message::status_sent);
637
-            return true;
638
-        } else {
639
-            $message->set_STS_ID(EEM_Message::status_failed);
640
-            return false;
641
-        }
642
-    }
643
-
644
-
645
-    /**
646
-     * Executes the send method on the provided messenger
647
-     * EE_Messengers are expected to:
648
-     * - return true if the send was successful.
649
-     * - return false if the send was unsuccessful but can be tried again.
650
-     * - throw an Exception if the send was unsuccessful and cannot be tried again.
651
-     *
652
-     * @param EE_Message      $message
653
-     * @param EE_messenger    $messenger
654
-     * @param EE_message_type $message_type
655
-     * @return bool true means all went well, false means, not so much.
656
-     */
657
-    protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
658
-    {
659
-        try {
660
-            if ($messenger->send_message($message, $message_type)) {
661
-                $message->set_STS_ID(EEM_Message::status_sent);
662
-                return true;
663
-            } else {
664
-                $message->set_STS_ID(EEM_Message::status_retry);
665
-                return false;
666
-            }
667
-        } catch (SendMessageException $e) {
668
-            $message->set_STS_ID(EEM_Message::status_failed);
669
-            $message->set_error_message($e->getMessage());
670
-            return false;
671
-        }
672
-    }
673
-
674
-
675
-    /**
676
-     * This sets any necessary error messages on the message object and its status to failed.
677
-     *
678
-     * @param EE_Message $message
679
-     * @param array      $error_messages the response from the messenger.
680
-     */
681
-    protected function _set_error_message(EE_Message $message, $error_messages)
682
-    {
683
-        $error_messages = (array) $error_messages;
684
-        if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
685
-            $notices          = EE_Error::has_notices();
686
-            $error_messages[] = __(
687
-                'Messenger and Message Type were valid and active, but the messenger send method failed.',
688
-                'event_espresso'
689
-            );
690
-            if ($notices === 1) {
691
-                $notices           = EE_Error::get_vanilla_notices();
692
-                $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
693
-                $error_messages[]  = implode("\n", $notices['errors']);
694
-            }
695
-        }
696
-        if (count($error_messages) > 0) {
697
-            $msg = __('Message was not executed successfully.', 'event_espresso');
698
-            $msg = $msg . "\n" . implode("\n", $error_messages);
699
-            $message->set_error_message($msg);
700
-        }
701
-    }
17
+	/**
18
+	 * @type    string  reference for sending action
19
+	 */
20
+	const action_sending = 'sending';
21
+
22
+	/**
23
+	 * @type    string  reference for generation action
24
+	 */
25
+	const action_generating = 'generation';
26
+
27
+
28
+	/**
29
+	 * @type EE_Message_Repository $_message_repository
30
+	 */
31
+	protected $_message_repository;
32
+
33
+	/**
34
+	 * Sets the limit of how many messages are generated per process.
35
+	 *
36
+	 * @type int
37
+	 */
38
+	protected $_batch_count;
39
+
40
+
41
+	/**
42
+	 * This is an array of cached queue items being stored in this object.
43
+	 * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
44
+	 * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
45
+	 *
46
+	 * @type EE_Message[]
47
+	 */
48
+	protected $_cached_queue_items;
49
+
50
+	/**
51
+	 * Tracks the number of unsaved queue items.
52
+	 *
53
+	 * @type int
54
+	 */
55
+	protected $_unsaved_count = 0;
56
+
57
+	/**
58
+	 * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
59
+	 * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
60
+	 *
61
+	 * @type array
62
+	 */
63
+	protected $_did_hook = array();
64
+
65
+
66
+	/**
67
+	 * Constructor.
68
+	 * Setup all the initial properties and load a EE_Message_Repository.
69
+	 *
70
+	 * @param \EE_Message_Repository $message_repository
71
+	 */
72
+	public function __construct(EE_Message_Repository $message_repository)
73
+	{
74
+		$this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
75
+		$this->_message_repository = $message_repository;
76
+	}
77
+
78
+
79
+	/**
80
+	 * Add a EE_Message object to the queue
81
+	 *
82
+	 * @param EE_Message $message
83
+	 * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
84
+	 *                                 object is persisted, this data will be saved on an extra_meta object related to
85
+	 *                                 EE_Message.
86
+	 * @param  bool      $preview      Whether this EE_Message represents a preview or not.
87
+	 * @param  bool      $test_send    This indicates whether to do a test send instead of actual send. A test send will
88
+	 *                                 use the messenger send method but typically is based on preview data.
89
+	 * @return bool          Whether the message was successfully added to the repository or not.
90
+	 */
91
+	public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false)
92
+	{
93
+		$data['preview']   = $preview;
94
+		$data['test_send'] = $test_send;
95
+		return $this->_message_repository->add($message, $data);
96
+	}
97
+
98
+
99
+	/**
100
+	 * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
101
+	 *
102
+	 * @param EE_Message $message The message to detach from the queue
103
+	 * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
104
+	 * @return bool
105
+	 */
106
+	public function remove(EE_Message $message, $persist = false)
107
+	{
108
+		if ($persist && $this->_message_repository->current() !== $message) {
109
+			// get pointer on right message
110
+			if ($this->_message_repository->has($message)) {
111
+				$this->_message_repository->rewind();
112
+				while ($this->_message_repository->valid()) {
113
+					if ($this->_message_repository->current() === $message) {
114
+						break;
115
+					}
116
+					$this->_message_repository->next();
117
+				}
118
+			} else {
119
+				return false;
120
+			}
121
+		}
122
+		return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
123
+	}
124
+
125
+
126
+	/**
127
+	 * Persists all queued EE_Message objects to the db.
128
+	 *
129
+	 * @param bool $do_hooks_only       @see EE_Message_Repository::saveAll
130
+	 * @return array @see EE_Messages_Repository::saveAll() for return values.
131
+	 */
132
+	public function save($do_hooks_only = false)
133
+	{
134
+		return $this->_message_repository->saveAll($do_hooks_only);
135
+	}
136
+
137
+
138
+	/**
139
+	 * @return EE_Message_Repository
140
+	 */
141
+	public function get_message_repository()
142
+	{
143
+		return $this->_message_repository;
144
+	}
145
+
146
+
147
+	/**
148
+	 * This does the following things:
149
+	 * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
150
+	 * false).
151
+	 * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
152
+	 * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
153
+	 * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
154
+	 * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
155
+	 * removed.
156
+	 *
157
+	 * @return bool  true if successfully retrieved batch, false no batch ready.
158
+	 */
159
+	public function get_batch_to_generate()
160
+	{
161
+		if ($this->is_locked(EE_Messages_Queue::action_generating)) {
162
+			return false;
163
+		}
164
+
165
+		// lock batch generation to prevent race conditions.
166
+		$this->lock_queue(EE_Messages_Queue::action_generating);
167
+
168
+		$query_args = array(
169
+			// key 0 = where conditions
170
+			0          => array('STS_ID' => EEM_Message::status_incomplete),
171
+			'order_by' => $this->_get_priority_orderby(),
172
+			'limit'    => $this->_batch_count,
173
+		);
174
+		$messages   = EEM_Message::instance()->get_all($query_args);
175
+
176
+		if (! $messages) {
177
+			return false; // nothing to generate
178
+		}
179
+
180
+		foreach ($messages as $message) {
181
+			if ($message instanceof EE_Message) {
182
+				$data = $message->all_extra_meta_array();
183
+				$this->add($message, $data);
184
+			}
185
+		}
186
+		return true;
187
+	}
188
+
189
+
190
+	/**
191
+	 * This does the following things:
192
+	 * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
193
+	 * false).
194
+	 * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
195
+	 * return false.
196
+	 * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
197
+	 * 3. On success or unsuccessful send, sets status appropriately.
198
+	 * 4. Saves messages via the queue
199
+	 * 5. Releases lock.
200
+	 *
201
+	 * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
202
+	 *               necessarily mean that all messages were successfully sent.  It just means that this method
203
+	 *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
204
+	 *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
205
+	 *               will also have a saved error message on it to assist with notifying user.
206
+	 */
207
+	public function get_to_send_batch_and_send()
208
+	{
209
+		$rate_limit = $this->get_rate_limit();
210
+		if ($rate_limit < 1 || $this->is_locked(EE_Messages_Queue::action_sending)) {
211
+			return false;
212
+		}
213
+
214
+		$this->lock_queue(EE_Messages_Queue::action_sending);
215
+
216
+		$batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
217
+
218
+		$query_args = array(
219
+			// key 0 = where conditions
220
+			0          => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())),
221
+			'order_by' => $this->_get_priority_orderby(),
222
+			'limit'    => $batch,
223
+		);
224
+
225
+		$messages_to_send = EEM_Message::instance()->get_all($query_args);
226
+
227
+
228
+		// any to send?
229
+		if (! $messages_to_send) {
230
+			$this->unlock_queue(EE_Messages_Queue::action_sending);
231
+			return false;
232
+		}
233
+
234
+		$queue_count = 0;
235
+
236
+		// add to queue.
237
+		foreach ($messages_to_send as $message) {
238
+			if ($message instanceof EE_Message) {
239
+				$queue_count++;
240
+				$this->add($message);
241
+			}
242
+		}
243
+
244
+		// send messages  (this also updates the rate limit)
245
+		$this->execute();
246
+
247
+		// release lock
248
+		$this->unlock_queue(EE_Messages_Queue::action_sending);
249
+		// update rate limit
250
+		$this->set_rate_limit($queue_count);
251
+		return true;
252
+	}
253
+
254
+
255
+	/**
256
+	 * Locks the queue so that no other queues can call the "batch" methods.
257
+	 *
258
+	 * @param   string $type The type of queue being locked.
259
+	 */
260
+	public function lock_queue($type = EE_Messages_Queue::action_generating)
261
+	{
262
+		update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
263
+	}
264
+
265
+
266
+	/**
267
+	 * Unlocks the queue so that batch methods can be used.
268
+	 *
269
+	 * @param   string $type The type of queue being unlocked.
270
+	 */
271
+	public function unlock_queue($type = EE_Messages_Queue::action_generating)
272
+	{
273
+		delete_option($this->_get_lock_key($type));
274
+	}
275
+
276
+
277
+	/**
278
+	 * Retrieve the key used for the lock transient.
279
+	 *
280
+	 * @param string $type The type of lock.
281
+	 * @return string
282
+	 */
283
+	protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
284
+	{
285
+		return '_ee_lock_' . $type;
286
+	}
287
+
288
+
289
+	/**
290
+	 * Retrieve the expiry time for the lock transient.
291
+	 *
292
+	 * @param string $type The type of lock
293
+	 * @return int   time to expiry in seconds.
294
+	 */
295
+	protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
296
+	{
297
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
298
+	}
299
+
300
+
301
+	/**
302
+	 * Returns the key used for rate limit transient.
303
+	 *
304
+	 * @return string
305
+	 */
306
+	protected function _get_rate_limit_key()
307
+	{
308
+		return '_ee_rate_limit';
309
+	}
310
+
311
+
312
+	/**
313
+	 * Returns the rate limit expiry time.
314
+	 *
315
+	 * @return int
316
+	 */
317
+	protected function _get_rate_limit_expiry()
318
+	{
319
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
320
+	}
321
+
322
+
323
+	/**
324
+	 * Returns the default rate limit for sending messages.
325
+	 *
326
+	 * @return int
327
+	 */
328
+	protected function _default_rate_limit()
329
+	{
330
+		return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
331
+	}
332
+
333
+
334
+	/**
335
+	 * Return the orderby array for priority.
336
+	 *
337
+	 * @return array
338
+	 */
339
+	protected function _get_priority_orderby()
340
+	{
341
+		return array(
342
+			'MSG_priority' => 'ASC',
343
+			'MSG_modified' => 'DESC',
344
+		);
345
+	}
346
+
347
+
348
+	/**
349
+	 * Returns whether batch methods are "locked" or not.
350
+	 *
351
+	 * @param  string $type The type of lock being checked for.
352
+	 * @return bool
353
+	 */
354
+	public function is_locked($type = EE_Messages_Queue::action_generating)
355
+	{
356
+		$lock = (int) get_option($this->_get_lock_key($type), 0);
357
+		/**
358
+		 * This filters the default is_locked behaviour.
359
+		 */
360
+		$is_locked = filter_var(
361
+			apply_filters(
362
+				'FHEE__EE_Messages_Queue__is_locked',
363
+				$lock > time(),
364
+				$this
365
+			),
366
+			FILTER_VALIDATE_BOOLEAN
367
+		);
368
+
369
+		/**
370
+		 * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
371
+		 *            Also implemented here because messages processed on the same request should not have any locks applied.
372
+		 */
373
+		if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
374
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
375
+		) {
376
+			$is_locked = false;
377
+		}
378
+
379
+
380
+		return $is_locked;
381
+	}
382
+
383
+
384
+	/**
385
+	 * Retrieves the rate limit that may be cached as a transient.
386
+	 * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
387
+	 *
388
+	 * @param bool $return_expiry  If true then return the expiry time not the rate_limit.
389
+	 * @return int
390
+	 */
391
+	protected function get_rate_limit($return_expiry = false)
392
+	{
393
+		$stored_rate_info = get_option($this->_get_rate_limit_key(), array());
394
+		$rate_limit = isset($stored_rate_info[0])
395
+			? (int) $stored_rate_info[0]
396
+			: 0;
397
+		$expiry = isset($stored_rate_info[1])
398
+			? (int) $stored_rate_info[1]
399
+			: 0;
400
+		// set the default for tracking?
401
+		if (empty($stored_rate_info) || time() > $expiry) {
402
+			$expiry = $this->_get_rate_limit_expiry();
403
+			$rate_limit = $this->_default_rate_limit();
404
+			update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry));
405
+		}
406
+		return $return_expiry ? $expiry : $rate_limit;
407
+	}
408
+
409
+
410
+	/**
411
+	 * This updates existing rate limit with the new limit which is the old minus the batch.
412
+	 *
413
+	 * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
414
+	 */
415
+	protected function set_rate_limit($batch_completed)
416
+	{
417
+		// first get the most up to date rate limit (in case its expired and reset)
418
+		$rate_limit = $this->get_rate_limit();
419
+		$expiry = $this->get_rate_limit(true);
420
+		$new_limit  = $rate_limit - $batch_completed;
421
+		// updating the transient option directly to avoid resetting the expiry.
422
+
423
+		update_option($this->_get_rate_limit_key(), array($new_limit, $expiry));
424
+	}
425
+
426
+
427
+	/**
428
+	 * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
429
+	 * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
430
+	 * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
431
+	 * request running on a queue for the given task.
432
+	 *
433
+	 * @param string $task     This indicates what type of request is going to be initiated.
434
+	 * @param int    $priority This indicates the priority that triggers initiating the request.
435
+	 */
436
+	public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
437
+	{
438
+		// determine what status is matched with the priority as part of the trigger conditions.
439
+		$status = $task == 'generate'
440
+			? EEM_Message::status_incomplete
441
+			: EEM_Message::instance()->stati_indicating_to_send();
442
+		// always make sure we save because either this will get executed immediately on a separate request
443
+		// or remains in the queue for the regularly scheduled queue batch.
444
+		$this->save();
445
+		/**
446
+		 * This filter/option allows users to override processing of messages on separate requests and instead have everything
447
+		 * happen on the same request.  If this is utilized remember:
448
+		 * - message priorities don't matter
449
+		 * - existing unprocessed messages in the queue will not get processed unless manually triggered.
450
+		 * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
451
+		 *   processing happening on the same request.
452
+		 * - any race condition protection (locks) are removed because they don't apply when things are processed on
453
+		 *   the same request.
454
+		 */
455
+		if (apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
456
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
457
+		) {
458
+			$messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
459
+			if ($messages_processor instanceof EE_Messages_Processor) {
460
+				return $messages_processor->process_immediately_from_queue($this);
461
+			}
462
+			// if we get here then that means the messages processor couldn't be loaded so messages will just remain
463
+			// queued for manual triggering by end user.
464
+		}
465
+
466
+		if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
467
+			EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
468
+		}
469
+	}
470
+
471
+
472
+	/**
473
+	 *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
474
+	 *
475
+	 * @param   bool     $save                    Used to indicate whether to save the message queue after sending
476
+	 *                                            (default will save).
477
+	 * @param   mixed    $sending_messenger       (optional) When the sending messenger is different than
478
+	 *                                            what is on the EE_Message object in the queue.
479
+	 *                                            For instance, showing the browser view of an email message,
480
+	 *                                            or giving a pdf generated view of an html document.
481
+	 *                                            This should be an instance of EE_messenger but if you call this
482
+	 *                                            method
483
+	 *                                            intending it to be a sending messenger but a valid one could not be
484
+	 *                                            retrieved then send in an instance of EE_Error that contains the
485
+	 *                                            related error message.
486
+	 * @param   bool|int $by_priority             When set, this indicates that only messages
487
+	 *                                            matching the given priority should be executed.
488
+	 * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
489
+	 *                                            Also, if the messenger is an request type messenger (or a preview),
490
+	 *                                            its entirely possible that the messenger will exit before
491
+	 */
492
+	public function execute($save = true, $sending_messenger = null, $by_priority = false)
493
+	{
494
+		$messages_sent   = 0;
495
+		$this->_did_hook = array();
496
+		$this->_message_repository->rewind();
497
+
498
+		while ($this->_message_repository->valid()) {
499
+			$error_messages = array();
500
+			/** @type EE_Message $message */
501
+			$message = $this->_message_repository->current();
502
+			// only process things that are queued for sending
503
+			if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
504
+				$this->_message_repository->next();
505
+				continue;
506
+			}
507
+			// if $by_priority is set and does not match then continue;
508
+			if ($by_priority && $by_priority != $message->priority()) {
509
+				$this->_message_repository->next();
510
+				continue;
511
+			}
512
+			// error checking
513
+			if (! $message->valid_messenger()) {
514
+				$error_messages[] = sprintf(
515
+					__('The %s messenger is not active at time of sending.', 'event_espresso'),
516
+					$message->messenger()
517
+				);
518
+			}
519
+			if (! $message->valid_message_type()) {
520
+				$error_messages[] = sprintf(
521
+					__('The %s message type is not active at the time of sending.', 'event_espresso'),
522
+					$message->message_type()
523
+				);
524
+			}
525
+			// if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
526
+			// then it will instead be an EE_Error object, so let's check for that
527
+			if ($sending_messenger instanceof EE_Error) {
528
+				$error_messages[] = $sending_messenger->getMessage();
529
+			}
530
+			// if there are no errors, then let's process the message
531
+			if (empty($error_messages)) {
532
+				if ($save) {
533
+					$message->set_messenger_is_executing();
534
+				}
535
+				if ($this->_process_message($message, $sending_messenger)) {
536
+					$messages_sent++;
537
+				}
538
+			}
539
+			$this->_set_error_message($message, $error_messages);
540
+			// add modified time
541
+			$message->set_modified(time());
542
+			// we save each message after its processed to make sure its status persists in case PHP times-out or runs
543
+			// out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
544
+			if ($save) {
545
+				$message->save();
546
+			}
547
+
548
+			$this->_message_repository->next();
549
+		}
550
+		if ($save) {
551
+			$this->save(true);
552
+		}
553
+		return $messages_sent;
554
+	}
555
+
556
+
557
+	/**
558
+	 * _process_message
559
+	 *
560
+	 * @param EE_Message $message
561
+	 * @param mixed      $sending_messenger (optional)
562
+	 * @return bool
563
+	 */
564
+	protected function _process_message(EE_Message $message, $sending_messenger = null)
565
+	{
566
+		// these *should* have been validated in the execute() method above
567
+		$messenger    = $message->messenger_object();
568
+		$message_type = $message->message_type_object();
569
+		// do actions for sending messenger if it differs from generating messenger and swap values.
570
+		if ($sending_messenger instanceof EE_messenger
571
+			&& $messenger instanceof EE_messenger
572
+			&& $sending_messenger->name != $messenger->name
573
+		) {
574
+			$messenger->do_secondary_messenger_hooks($sending_messenger->name);
575
+			$messenger = $sending_messenger;
576
+		}
577
+		// send using messenger, but double check objects
578
+		if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
579
+			// set hook for message type (but only if not using another messenger to send).
580
+			if (! isset($this->_did_hook[ $message_type->name ])) {
581
+				$message_type->do_messenger_hooks($messenger);
582
+				$this->_did_hook[ $message_type->name ] = 1;
583
+			}
584
+			// if preview then use preview method
585
+			return $this->_message_repository->is_preview()
586
+				? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
587
+				: $this->_do_send($message, $messenger, $message_type);
588
+		}
589
+		return false;
590
+	}
591
+
592
+
593
+	/**
594
+	 * The intention of this method is to count how many EE_Message objects
595
+	 * are in the queue with a given status.
596
+	 * Example usage:
597
+	 * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
598
+	 * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
599
+	 *
600
+	 * @param array|string $status Stati to check for in queue
601
+	 * @return int  Count of EE_Message's matching the given status.
602
+	 */
603
+	public function count_STS_in_queue($status)
604
+	{
605
+		$count  = 0;
606
+		$status = is_array($status) ? $status : array($status);
607
+		$this->_message_repository->rewind();
608
+		foreach ($this->_message_repository as $message) {
609
+			if (in_array($message->STS_ID(), $status)) {
610
+				$count++;
611
+			}
612
+		}
613
+		return $count;
614
+	}
615
+
616
+
617
+	/**
618
+	 * Executes the get_preview method on the provided messenger.
619
+	 *
620
+	 * @param EE_Message      $message
621
+	 * @param EE_messenger    $messenger
622
+	 * @param EE_message_type $message_type
623
+	 * @param                 $test_send
624
+	 * @return bool   true means all went well, false means, not so much.
625
+	 */
626
+	protected function _do_preview(
627
+		EE_Message $message,
628
+		EE_messenger $messenger,
629
+		EE_message_type $message_type,
630
+		$test_send
631
+	) {
632
+		if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
633
+			if (! $test_send) {
634
+				$message->set_content($preview);
635
+			}
636
+			$message->set_STS_ID(EEM_Message::status_sent);
637
+			return true;
638
+		} else {
639
+			$message->set_STS_ID(EEM_Message::status_failed);
640
+			return false;
641
+		}
642
+	}
643
+
644
+
645
+	/**
646
+	 * Executes the send method on the provided messenger
647
+	 * EE_Messengers are expected to:
648
+	 * - return true if the send was successful.
649
+	 * - return false if the send was unsuccessful but can be tried again.
650
+	 * - throw an Exception if the send was unsuccessful and cannot be tried again.
651
+	 *
652
+	 * @param EE_Message      $message
653
+	 * @param EE_messenger    $messenger
654
+	 * @param EE_message_type $message_type
655
+	 * @return bool true means all went well, false means, not so much.
656
+	 */
657
+	protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
658
+	{
659
+		try {
660
+			if ($messenger->send_message($message, $message_type)) {
661
+				$message->set_STS_ID(EEM_Message::status_sent);
662
+				return true;
663
+			} else {
664
+				$message->set_STS_ID(EEM_Message::status_retry);
665
+				return false;
666
+			}
667
+		} catch (SendMessageException $e) {
668
+			$message->set_STS_ID(EEM_Message::status_failed);
669
+			$message->set_error_message($e->getMessage());
670
+			return false;
671
+		}
672
+	}
673
+
674
+
675
+	/**
676
+	 * This sets any necessary error messages on the message object and its status to failed.
677
+	 *
678
+	 * @param EE_Message $message
679
+	 * @param array      $error_messages the response from the messenger.
680
+	 */
681
+	protected function _set_error_message(EE_Message $message, $error_messages)
682
+	{
683
+		$error_messages = (array) $error_messages;
684
+		if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
685
+			$notices          = EE_Error::has_notices();
686
+			$error_messages[] = __(
687
+				'Messenger and Message Type were valid and active, but the messenger send method failed.',
688
+				'event_espresso'
689
+			);
690
+			if ($notices === 1) {
691
+				$notices           = EE_Error::get_vanilla_notices();
692
+				$notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array();
693
+				$error_messages[]  = implode("\n", $notices['errors']);
694
+			}
695
+		}
696
+		if (count($error_messages) > 0) {
697
+			$msg = __('Message was not executed successfully.', 'event_espresso');
698
+			$msg = $msg . "\n" . implode("\n", $error_messages);
699
+			$message->set_error_message($msg);
700
+		}
701
+	}
702 702
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -171,9 +171,9 @@  discard block
 block discarded – undo
171 171
             'order_by' => $this->_get_priority_orderby(),
172 172
             'limit'    => $this->_batch_count,
173 173
         );
174
-        $messages   = EEM_Message::instance()->get_all($query_args);
174
+        $messages = EEM_Message::instance()->get_all($query_args);
175 175
 
176
-        if (! $messages) {
176
+        if ( ! $messages) {
177 177
             return false; // nothing to generate
178 178
         }
179 179
 
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
 
227 227
 
228 228
         // any to send?
229
-        if (! $messages_to_send) {
229
+        if ( ! $messages_to_send) {
230 230
             $this->unlock_queue(EE_Messages_Queue::action_sending);
231 231
             return false;
232 232
         }
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
      */
283 283
     protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
284 284
     {
285
-        return '_ee_lock_' . $type;
285
+        return '_ee_lock_'.$type;
286 286
     }
287 287
 
288 288
 
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
             /** @type EE_Message $message */
501 501
             $message = $this->_message_repository->current();
502 502
             // only process things that are queued for sending
503
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
503
+            if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
504 504
                 $this->_message_repository->next();
505 505
                 continue;
506 506
             }
@@ -510,13 +510,13 @@  discard block
 block discarded – undo
510 510
                 continue;
511 511
             }
512 512
             // error checking
513
-            if (! $message->valid_messenger()) {
513
+            if ( ! $message->valid_messenger()) {
514 514
                 $error_messages[] = sprintf(
515 515
                     __('The %s messenger is not active at time of sending.', 'event_espresso'),
516 516
                     $message->messenger()
517 517
                 );
518 518
             }
519
-            if (! $message->valid_message_type()) {
519
+            if ( ! $message->valid_message_type()) {
520 520
                 $error_messages[] = sprintf(
521 521
                     __('The %s message type is not active at the time of sending.', 'event_espresso'),
522 522
                     $message->message_type()
@@ -577,9 +577,9 @@  discard block
 block discarded – undo
577 577
         // send using messenger, but double check objects
578 578
         if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
579 579
             // set hook for message type (but only if not using another messenger to send).
580
-            if (! isset($this->_did_hook[ $message_type->name ])) {
580
+            if ( ! isset($this->_did_hook[$message_type->name])) {
581 581
                 $message_type->do_messenger_hooks($messenger);
582
-                $this->_did_hook[ $message_type->name ] = 1;
582
+                $this->_did_hook[$message_type->name] = 1;
583 583
             }
584 584
             // if preview then use preview method
585 585
             return $this->_message_repository->is_preview()
@@ -630,7 +630,7 @@  discard block
 block discarded – undo
630 630
         $test_send
631 631
     ) {
632 632
         if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
633
-            if (! $test_send) {
633
+            if ( ! $test_send) {
634 634
                 $message->set_content($preview);
635 635
             }
636 636
             $message->set_STS_ID(EEM_Message::status_sent);
@@ -695,7 +695,7 @@  discard block
 block discarded – undo
695 695
         }
696 696
         if (count($error_messages) > 0) {
697 697
             $msg = __('Message was not executed successfully.', 'event_espresso');
698
-            $msg = $msg . "\n" . implode("\n", $error_messages);
698
+            $msg = $msg."\n".implode("\n", $error_messages);
699 699
             $message->set_error_message($msg);
700 700
         }
701 701
     }
Please login to merge, or discard this patch.
admin/extend/registration_form/Extend_Registration_Form_Admin_Page.core.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -504,7 +504,7 @@
 block discarded – undo
504 504
      *
505 505
      * @param int                  $id
506 506
      * @param EEM_Soft_Delete_Base $model
507
-     * @return boolean
507
+     * @return integer
508 508
      */
509 509
     protected function _delete_item($id, $model)
510 510
     {
Please login to merge, or discard this patch.
Indentation   +1176 added lines, -1176 removed lines patch added patch discarded remove patch
@@ -22,1180 +22,1180 @@
 block discarded – undo
22 22
 {
23 23
 
24 24
 
25
-    /**
26
-     * @Constructor
27
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
28
-     * @access public
29
-     */
30
-    public function __construct($routing = true)
31
-    {
32
-        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form' . DS);
33
-        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets' . DS);
34
-        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
35
-        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates' . DS);
36
-        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
37
-        parent::__construct($routing);
38
-    }
39
-
40
-
41
-    protected function _extend_page_config()
42
-    {
43
-        $this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
44
-        $qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
45
-            ? $this->_req_data['QST_ID'] : 0;
46
-        $qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
47
-            ? $this->_req_data['QSG_ID'] : 0;
48
-
49
-        $new_page_routes = array(
50
-            'question_groups'    => array(
51
-                'func'       => '_question_groups_overview_list_table',
52
-                'capability' => 'ee_read_question_groups',
53
-            ),
54
-            'add_question'       => array(
55
-                'func'       => '_edit_question',
56
-                'capability' => 'ee_edit_questions',
57
-            ),
58
-            'insert_question'    => array(
59
-                'func'       => '_insert_or_update_question',
60
-                'args'       => array('new_question' => true),
61
-                'capability' => 'ee_edit_questions',
62
-                'noheader'   => true,
63
-            ),
64
-            'duplicate_question' => array(
65
-                'func'       => '_duplicate_question',
66
-                'capability' => 'ee_edit_questions',
67
-                'noheader'   => true,
68
-            ),
69
-            'trash_question'     => array(
70
-                'func'       => '_trash_question',
71
-                'capability' => 'ee_delete_question',
72
-                'obj_id'     => $qst_id,
73
-                'noheader'   => true,
74
-            ),
75
-
76
-            'restore_question' => array(
77
-                'func'       => '_trash_or_restore_questions',
78
-                'capability' => 'ee_delete_question',
79
-                'obj_id'     => $qst_id,
80
-                'args'       => array('trash' => false),
81
-                'noheader'   => true,
82
-            ),
83
-
84
-            'delete_question' => array(
85
-                'func'       => '_delete_question',
86
-                'capability' => 'ee_delete_question',
87
-                'obj_id'     => $qst_id,
88
-                'noheader'   => true,
89
-            ),
90
-
91
-            'trash_questions' => array(
92
-                'func'       => '_trash_or_restore_questions',
93
-                'capability' => 'ee_delete_questions',
94
-                'args'       => array('trash' => true),
95
-                'noheader'   => true,
96
-            ),
97
-
98
-            'restore_questions' => array(
99
-                'func'       => '_trash_or_restore_questions',
100
-                'capability' => 'ee_delete_questions',
101
-                'args'       => array('trash' => false),
102
-                'noheader'   => true,
103
-            ),
104
-
105
-            'delete_questions' => array(
106
-                'func'       => '_delete_questions',
107
-                'args'       => array(),
108
-                'capability' => 'ee_delete_questions',
109
-                'noheader'   => true,
110
-            ),
111
-
112
-            'add_question_group' => array(
113
-                'func'       => '_edit_question_group',
114
-                'capability' => 'ee_edit_question_groups',
115
-            ),
116
-
117
-            'edit_question_group' => array(
118
-                'func'       => '_edit_question_group',
119
-                'capability' => 'ee_edit_question_group',
120
-                'obj_id'     => $qsg_id,
121
-                'args'       => array('edit'),
122
-            ),
123
-
124
-            'delete_question_groups' => array(
125
-                'func'       => '_delete_question_groups',
126
-                'capability' => 'ee_delete_question_groups',
127
-                'noheader'   => true,
128
-            ),
129
-
130
-            'delete_question_group' => array(
131
-                'func'       => '_delete_question_groups',
132
-                'capability' => 'ee_delete_question_group',
133
-                'obj_id'     => $qsg_id,
134
-                'noheader'   => true,
135
-            ),
136
-
137
-            'trash_question_group' => array(
138
-                'func'       => '_trash_or_restore_question_groups',
139
-                'args'       => array('trash' => true),
140
-                'capability' => 'ee_delete_question_group',
141
-                'obj_id'     => $qsg_id,
142
-                'noheader'   => true,
143
-            ),
144
-
145
-            'restore_question_group' => array(
146
-                'func'       => '_trash_or_restore_question_groups',
147
-                'args'       => array('trash' => false),
148
-                'capability' => 'ee_delete_question_group',
149
-                'obj_id'     => $qsg_id,
150
-                'noheader'   => true,
151
-            ),
152
-
153
-            'insert_question_group' => array(
154
-                'func'       => '_insert_or_update_question_group',
155
-                'args'       => array('new_question_group' => true),
156
-                'capability' => 'ee_edit_question_groups',
157
-                'noheader'   => true,
158
-            ),
159
-
160
-            'update_question_group' => array(
161
-                'func'       => '_insert_or_update_question_group',
162
-                'args'       => array('new_question_group' => false),
163
-                'capability' => 'ee_edit_question_group',
164
-                'obj_id'     => $qsg_id,
165
-                'noheader'   => true,
166
-            ),
167
-
168
-            'trash_question_groups' => array(
169
-                'func'       => '_trash_or_restore_question_groups',
170
-                'args'       => array('trash' => true),
171
-                'capability' => 'ee_delete_question_groups',
172
-                'noheader'   => array('trash' => false),
173
-            ),
174
-
175
-            'restore_question_groups' => array(
176
-                'func'       => '_trash_or_restore_question_groups',
177
-                'args'       => array('trash' => false),
178
-                'capability' => 'ee_delete_question_groups',
179
-                'noheader'   => true,
180
-            ),
181
-
182
-
183
-            'espresso_update_question_group_order' => array(
184
-                'func'       => 'update_question_group_order',
185
-                'capability' => 'ee_edit_question_groups',
186
-                'noheader'   => true,
187
-            ),
188
-
189
-            'view_reg_form_settings' => array(
190
-                'func'       => '_reg_form_settings',
191
-                'capability' => 'manage_options',
192
-            ),
193
-
194
-            'update_reg_form_settings' => array(
195
-                'func'       => '_update_reg_form_settings',
196
-                'capability' => 'manage_options',
197
-                'noheader'   => true,
198
-            ),
199
-        );
200
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
201
-
202
-        $new_page_config = array(
203
-
204
-            'question_groups' => array(
205
-                'nav'           => array(
206
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
207
-                    'order' => 20,
208
-                ),
209
-                'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
210
-                'help_tabs'     => array(
211
-                    'registration_form_question_groups_help_tab'                           => array(
212
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
213
-                        'filename' => 'registration_form_question_groups',
214
-                    ),
215
-                    'registration_form_question_groups_table_column_headings_help_tab'     => array(
216
-                        'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
217
-                        'filename' => 'registration_form_question_groups_table_column_headings',
218
-                    ),
219
-                    'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
220
-                        'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
221
-                        'filename' => 'registration_form_question_groups_views_bulk_actions_search',
222
-                    ),
223
-                ),
224
-                'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
225
-                'metaboxes'     => $this->_default_espresso_metaboxes,
226
-                'require_nonce' => false,
227
-                'qtips'         => array(
228
-                    'EE_Registration_Form_Tips',
229
-                ),
230
-            ),
231
-
232
-            'add_question' => array(
233
-                'nav'           => array(
234
-                    'label'      => esc_html__('Add Question', 'event_espresso'),
235
-                    'order'      => 5,
236
-                    'persistent' => false,
237
-                ),
238
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
239
-                'help_tabs'     => array(
240
-                    'registration_form_add_question_help_tab' => array(
241
-                        'title'    => esc_html__('Add Question', 'event_espresso'),
242
-                        'filename' => 'registration_form_add_question',
243
-                    ),
244
-                ),
245
-                'help_tour'     => array('Registration_Form_Add_Question_Help_Tour'),
246
-                'require_nonce' => false,
247
-            ),
248
-
249
-            'add_question_group' => array(
250
-                'nav'           => array(
251
-                    'label'      => esc_html__('Add Question Group', 'event_espresso'),
252
-                    'order'      => 5,
253
-                    'persistent' => false,
254
-                ),
255
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
256
-                'help_tabs'     => array(
257
-                    'registration_form_add_question_group_help_tab' => array(
258
-                        'title'    => esc_html__('Add Question Group', 'event_espresso'),
259
-                        'filename' => 'registration_form_add_question_group',
260
-                    ),
261
-                ),
262
-                'help_tour'     => array('Registration_Form_Add_Question_Group_Help_Tour'),
263
-                'require_nonce' => false,
264
-            ),
265
-
266
-            'edit_question_group' => array(
267
-                'nav'           => array(
268
-                    'label'      => esc_html__('Edit Question Group', 'event_espresso'),
269
-                    'order'      => 5,
270
-                    'persistent' => false,
271
-                    'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
272
-                        array('question_group_id' => $this->_req_data['question_group_id']),
273
-                        $this->_current_page_view_url
274
-                    ) : $this->_admin_base_url,
275
-                ),
276
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
277
-                'help_tabs'     => array(
278
-                    'registration_form_edit_question_group_help_tab' => array(
279
-                        'title'    => esc_html__('Edit Question Group', 'event_espresso'),
280
-                        'filename' => 'registration_form_edit_question_group',
281
-                    ),
282
-                ),
283
-                'help_tour'     => array('Registration_Form_Edit_Question_Group_Help_Tour'),
284
-                'require_nonce' => false,
285
-            ),
286
-
287
-            'view_reg_form_settings' => array(
288
-                'nav'           => array(
289
-                    'label' => esc_html__('Reg Form Settings', 'event_espresso'),
290
-                    'order' => 40,
291
-                ),
292
-                'labels'        => array(
293
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
294
-                ),
295
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
296
-                'help_tabs'     => array(
297
-                    'registration_form_reg_form_settings_help_tab' => array(
298
-                        'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
299
-                        'filename' => 'registration_form_reg_form_settings',
300
-                    ),
301
-                ),
302
-                'help_tour'     => array('Registration_Form_Settings_Help_Tour'),
303
-                'require_nonce' => false,
304
-            ),
305
-
306
-        );
307
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
308
-
309
-        // change the list table we're going to use so it's the NEW list table!
310
-        $this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
311
-
312
-
313
-        // additional labels
314
-        $new_labels = array(
315
-            'add_question'          => esc_html__('Add New Question', 'event_espresso'),
316
-            'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
317
-            'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
318
-            'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
319
-            'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
320
-        );
321
-        $this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
322
-    }
323
-
324
-
325
-    protected function _ajax_hooks()
326
-    {
327
-        add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
328
-    }
329
-
330
-
331
-    public function load_scripts_styles_question_groups()
332
-    {
333
-        wp_enqueue_script('espresso_ajax_table_sorting');
334
-    }
335
-
336
-
337
-    public function load_scripts_styles_add_question_group()
338
-    {
339
-        $this->load_scripts_styles_forms();
340
-        $this->load_sortable_question_script();
341
-    }
342
-
343
-    public function load_scripts_styles_edit_question_group()
344
-    {
345
-        $this->load_scripts_styles_forms();
346
-        $this->load_sortable_question_script();
347
-    }
348
-
349
-
350
-    /**
351
-     * registers and enqueues script for questions
352
-     *
353
-     * @return void
354
-     */
355
-    public function load_sortable_question_script()
356
-    {
357
-        wp_register_script(
358
-            'ee-question-sortable',
359
-            REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
360
-            array('jquery-ui-sortable'),
361
-            EVENT_ESPRESSO_VERSION,
362
-            true
363
-        );
364
-        wp_enqueue_script('ee-question-sortable');
365
-    }
366
-
367
-
368
-    protected function _set_list_table_views_default()
369
-    {
370
-        $this->_views = array(
371
-            'all' => array(
372
-                'slug'        => 'all',
373
-                'label'       => esc_html__('View All Questions', 'event_espresso'),
374
-                'count'       => 0,
375
-                'bulk_action' => array(
376
-                    'trash_questions' => esc_html__('Trash', 'event_espresso'),
377
-                ),
378
-            ),
379
-        );
380
-
381
-        if (EE_Registry::instance()->CAP->current_user_can(
382
-            'ee_delete_questions',
383
-            'espresso_registration_form_trash_questions'
384
-        )
385
-        ) {
386
-            $this->_views['trash'] = array(
387
-                'slug'        => 'trash',
388
-                'label'       => esc_html__('Trash', 'event_espresso'),
389
-                'count'       => 0,
390
-                'bulk_action' => array(
391
-                    'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
392
-                    'restore_questions' => esc_html__('Restore', 'event_espresso'),
393
-                ),
394
-            );
395
-        }
396
-    }
397
-
398
-
399
-    protected function _set_list_table_views_question_groups()
400
-    {
401
-        $this->_views = array(
402
-            'all' => array(
403
-                'slug'        => 'all',
404
-                'label'       => esc_html__('All', 'event_espresso'),
405
-                'count'       => 0,
406
-                'bulk_action' => array(
407
-                    'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
408
-                ),
409
-            ),
410
-        );
411
-
412
-        if (EE_Registry::instance()->CAP->current_user_can(
413
-            'ee_delete_question_groups',
414
-            'espresso_registration_form_trash_question_groups'
415
-        )
416
-        ) {
417
-            $this->_views['trash'] = array(
418
-                'slug'        => 'trash',
419
-                'label'       => esc_html__('Trash', 'event_espresso'),
420
-                'count'       => 0,
421
-                'bulk_action' => array(
422
-                    'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
423
-                    'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
424
-                ),
425
-            );
426
-        }
427
-    }
428
-
429
-
430
-    protected function _questions_overview_list_table()
431
-    {
432
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
433
-            'add_question',
434
-            'add_question',
435
-            array(),
436
-            'add-new-h2'
437
-        );
438
-        parent::_questions_overview_list_table();
439
-    }
440
-
441
-
442
-    protected function _question_groups_overview_list_table()
443
-    {
444
-        $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
445
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
446
-            'add_question_group',
447
-            'add_question_group',
448
-            array(),
449
-            'add-new-h2'
450
-        );
451
-        $this->display_admin_list_table_page_with_sidebar();
452
-    }
453
-
454
-
455
-    protected function _delete_question()
456
-    {
457
-        $success = $this->_delete_items($this->_question_model);
458
-        $this->_redirect_after_action(
459
-            $success,
460
-            $this->_question_model->item_name($success),
461
-            'deleted',
462
-            array('action' => 'default', 'status' => 'all')
463
-        );
464
-    }
465
-
466
-
467
-    protected function _delete_questions()
468
-    {
469
-        $success = $this->_delete_items($this->_question_model);
470
-        $this->_redirect_after_action(
471
-            $success,
472
-            $this->_question_model->item_name($success),
473
-            'deleted permanently',
474
-            array('action' => 'default', 'status' => 'trash')
475
-        );
476
-    }
477
-
478
-
479
-    /**
480
-     * Performs the deletion of a single or multiple questions or question groups.
481
-     *
482
-     * @param EEM_Soft_Delete_Base $model
483
-     * @return int number of items deleted permanently
484
-     */
485
-    private function _delete_items(EEM_Soft_Delete_Base $model)
486
-    {
487
-        $success = 0;
488
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
489
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
490
-            // if array has more than one element than success message should be plural
491
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
492
-            // cycle thru bulk action checkboxes
493
-            while (list($ID, $value) = each($this->_req_data['checkbox'])) {
494
-                if (! $this->_delete_item($ID, $model)) {
495
-                    $success = 0;
496
-                }
497
-            }
498
-        } elseif (! empty($this->_req_data['QSG_ID'])) {
499
-            $success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
500
-        } elseif (! empty($this->_req_data['QST_ID'])) {
501
-            $success = $this->_delete_item($this->_req_data['QST_ID'], $model);
502
-        } else {
503
-            EE_Error::add_error(
504
-                sprintf(
505
-                    esc_html__(
506
-                        "No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.",
507
-                        "event_espresso"
508
-                    )
509
-                ),
510
-                __FILE__,
511
-                __FUNCTION__,
512
-                __LINE__
513
-            );
514
-        }
515
-        return $success;
516
-    }
517
-
518
-    /**
519
-     * Deletes the specified question (and its associated question options) or question group
520
-     *
521
-     * @param int                  $id
522
-     * @param EEM_Soft_Delete_Base $model
523
-     * @return boolean
524
-     */
525
-    protected function _delete_item($id, $model)
526
-    {
527
-        if ($model instanceof EEM_Question) {
528
-            EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
529
-        }
530
-        return $model->delete_permanently_by_ID(absint($id));
531
-    }
532
-
533
-
534
-    /******************************    QUESTION GROUPS    ******************************/
535
-
536
-
537
-    protected function _edit_question_group($type = 'add')
538
-    {
539
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
540
-        $ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID']) ? absint(
541
-            $this->_req_data['QSG_ID']
542
-        ) : false;
543
-
544
-        switch ($this->_req_action) {
545
-            case 'add_question_group':
546
-                $this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
547
-                break;
548
-            case 'edit_question_group':
549
-                $this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
550
-                break;
551
-            default:
552
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
553
-        }
554
-        // add ID to title if editing
555
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
556
-        if ($ID) {
557
-            /** @var EE_Question_Group $questionGroup */
558
-            $questionGroup = $this->_question_group_model->get_one_by_ID($ID);
559
-            $additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
560
-            $this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
561
-        } else {
562
-            /** @var EE_Question_Group $questionGroup */
563
-            $questionGroup = EEM_Question_Group::instance()->create_default_object();
564
-            $questionGroup->set_order_to_latest();
565
-            $this->_set_add_edit_form_tags('insert_question_group');
566
-        }
567
-        $this->_template_args['values'] = $this->_yes_no_values;
568
-        $this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
569
-        $this->_template_args['QSG_ID'] = $ID ? $ID : true;
570
-        $this->_template_args['question_group'] = $questionGroup;
571
-
572
-        $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
573
-        $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
574
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
575
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
576
-            $this->_template_args,
577
-            true
578
-        );
579
-
580
-        // the details template wrapper
581
-        $this->display_admin_page_with_sidebar();
582
-    }
583
-
584
-
585
-    protected function _delete_question_groups()
586
-    {
587
-        $success = $this->_delete_items($this->_question_group_model);
588
-        $this->_redirect_after_action(
589
-            $success,
590
-            $this->_question_group_model->item_name($success),
591
-            'deleted permanently',
592
-            array('action' => 'question_groups', 'status' => 'trash')
593
-        );
594
-    }
595
-
596
-
597
-    /**
598
-     * @param bool $new_question_group
599
-     */
600
-    protected function _insert_or_update_question_group($new_question_group = true)
601
-    {
602
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
603
-        $set_column_values = $this->_set_column_values_for($this->_question_group_model);
604
-        if ($new_question_group) {
605
-            $QSG_ID = $this->_question_group_model->insert($set_column_values);
606
-            $success = $QSG_ID ? 1 : 0;
607
-        } else {
608
-            $QSG_ID = absint($this->_req_data['QSG_ID']);
609
-            unset($set_column_values['QSG_ID']);
610
-            $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
611
-        }
612
-        $phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
613
-            EEM_Attendee::system_question_phone
614
-        );
615
-        // update the existing related questions
616
-        // BUT FIRST...  delete the phone question from the Question_Group_Question if it is being added to this question group (therefore removed from the existing group)
617
-        if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
618
-            // delete where QST ID = system phone question ID and Question Group ID is NOT this group
619
-            EEM_Question_Group_Question::instance()->delete(
620
-                array(
621
-                    array(
622
-                        'QST_ID' => $phone_question_id,
623
-                        'QSG_ID' => array('!=', $QSG_ID),
624
-                    ),
625
-                )
626
-            );
627
-        }
628
-        /** @type EE_Question_Group $question_group */
629
-        $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
630
-        $questions = $question_group->questions();
631
-        // make sure system phone question is added to list of questions for this group
632
-        if (! isset($questions[ $phone_question_id ])) {
633
-            $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
634
-        }
635
-
636
-        foreach ($questions as $question_ID => $question) {
637
-            // first we always check for order.
638
-            if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
639
-                // update question order
640
-                $question_group->update_question_order(
641
-                    $question_ID,
642
-                    $this->_req_data['question_orders'][ $question_ID ]
643
-                );
644
-            }
645
-
646
-            // then we always check if adding or removing.
647
-            if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
648
-                $question_group->add_question($question_ID);
649
-            } else {
650
-                // not found, remove it (but only if not a system question for the personal group with the exception of lname system question - we allow removal of it)
651
-                if (in_array(
652
-                    $question->system_ID(),
653
-                    EEM_Question::instance()->required_system_questions_in_system_question_group(
654
-                        $question_group->system_group()
655
-                    )
656
-                )) {
657
-                    continue;
658
-                } else {
659
-                    $question_group->remove_question($question_ID);
660
-                }
661
-            }
662
-        }
663
-        // save new related questions
664
-        if (isset($this->_req_data['questions'])) {
665
-            foreach ($this->_req_data['questions'] as $QST_ID) {
666
-                $question_group->add_question($QST_ID);
667
-                if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
668
-                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
669
-                }
670
-            }
671
-        }
672
-
673
-        if ($success !== false) {
674
-            $msg = $new_question_group
675
-                ? sprintf(
676
-                    esc_html__('The %s has been created', 'event_espresso'),
677
-                    $this->_question_group_model->item_name()
678
-                )
679
-                : sprintf(
680
-                    esc_html__(
681
-                        'The %s has been updated',
682
-                        'event_espresso'
683
-                    ),
684
-                    $this->_question_group_model->item_name()
685
-                );
686
-            EE_Error::add_success($msg);
687
-        }
688
-        $this->_redirect_after_action(
689
-            false,
690
-            '',
691
-            '',
692
-            array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
693
-            true
694
-        );
695
-    }
696
-
697
-    /**
698
-     * duplicates a question and all its question options and redirects to the new question.
699
-     */
700
-    public function _duplicate_question()
701
-    {
702
-        $question_ID = (int) $this->_req_data['QST_ID'];
703
-        $question = EEM_Question::instance()->get_one_by_ID($question_ID);
704
-        if ($question instanceof EE_Question) {
705
-            $new_question = $question->duplicate();
706
-            if ($new_question instanceof EE_Question) {
707
-                $this->_redirect_after_action(
708
-                    true,
709
-                    esc_html__('Question', 'event_espresso'),
710
-                    esc_html__('Duplicated', 'event_espresso'),
711
-                    array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
712
-                    true
713
-                );
714
-            } else {
715
-                global $wpdb;
716
-                EE_Error::add_error(
717
-                    sprintf(
718
-                        esc_html__(
719
-                            'Could not duplicate question with ID %1$d because: %2$s',
720
-                            'event_espresso'
721
-                        ),
722
-                        $question_ID,
723
-                        $wpdb->last_error
724
-                    ),
725
-                    __FILE__,
726
-                    __FUNCTION__,
727
-                    __LINE__
728
-                );
729
-                $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
730
-            }
731
-        } else {
732
-            EE_Error::add_error(
733
-                sprintf(
734
-                    esc_html__(
735
-                        'Could not duplicate question with ID %d because it didn\'t exist!',
736
-                        'event_espresso'
737
-                    ),
738
-                    $question_ID
739
-                ),
740
-                __FILE__,
741
-                __FUNCTION__,
742
-                __LINE__
743
-            );
744
-            $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
745
-        }
746
-    }
747
-
748
-
749
-    /**
750
-     * @param bool $trash
751
-     */
752
-    protected function _trash_or_restore_question_groups($trash = true)
753
-    {
754
-        $this->_trash_or_restore_items($this->_question_group_model, $trash);
755
-    }
756
-
757
-
758
-    /**
759
-     *_trash_question
760
-     */
761
-    protected function _trash_question()
762
-    {
763
-        $success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
764
-        $query_args = array('action' => 'default', 'status' => 'all');
765
-        $this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
766
-    }
767
-
768
-
769
-    /**
770
-     * @param bool $trash
771
-     */
772
-    protected function _trash_or_restore_questions($trash = true)
773
-    {
774
-        $this->_trash_or_restore_items($this->_question_model, $trash);
775
-    }
776
-
777
-
778
-    /**
779
-     * Internally used to delete or restore items, using the request data. Meant to be
780
-     * flexible between question or question groups
781
-     *
782
-     * @param EEM_Soft_Delete_Base $model
783
-     * @param boolean              $trash whether to trash or restore
784
-     */
785
-    private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
786
-    {
787
-
788
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
789
-
790
-        $success = 1;
791
-        // Checkboxes
792
-        // echo "trash $trash";
793
-        // var_dump($this->_req_data['checkbox']);die;
794
-        if (isset($this->_req_data['checkbox'])) {
795
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
796
-                // if array has more than one element than success message should be plural
797
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
798
-                // cycle thru bulk action checkboxes
799
-                while (list($ID, $value) = each($this->_req_data['checkbox'])) {
800
-                    if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
801
-                        $success = 0;
802
-                    }
803
-                }
804
-            } else {
805
-                // grab single id and delete
806
-                $ID = absint($this->_req_data['checkbox']);
807
-                if (! $model->delete_or_restore_by_ID($trash, $ID)) {
808
-                    $success = 0;
809
-                }
810
-            }
811
-        } else {
812
-            // delete via trash link
813
-            // grab single id and delete
814
-            $ID = absint($this->_req_data[ $model->primary_key_name() ]);
815
-            if (! $model->delete_or_restore_by_ID($trash, $ID)) {
816
-                $success = 0;
817
-            }
818
-        }
819
-
820
-
821
-        $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
822
-        // echo "action :$action";
823
-        // $action = 'questions' ? 'default' : $action;
824
-        if ($trash) {
825
-            $action_desc = 'trashed';
826
-            $status = 'trash';
827
-        } else {
828
-            $action_desc = 'restored';
829
-            $status = 'all';
830
-        }
831
-        $this->_redirect_after_action(
832
-            $success,
833
-            $model->item_name($success),
834
-            $action_desc,
835
-            array('action' => $action, 'status' => $status)
836
-        );
837
-    }
838
-
839
-
840
-    /**
841
-     * @param            $per_page
842
-     * @param int        $current_page
843
-     * @param bool|false $count
844
-     * @return \EE_Soft_Delete_Base_Class[]|int
845
-     */
846
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
847
-    {
848
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
849
-
850
-        if ($count) {
851
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
852
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
853
-            $results = $this->_question_model->count_deleted($where);
854
-        } else {
855
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
856
-            $results = $this->_question_model->get_all_deleted($query_params);
857
-        }
858
-        return $results;
859
-    }
860
-
861
-
862
-    /**
863
-     * @param            $per_page
864
-     * @param int        $current_page
865
-     * @param bool|false $count
866
-     * @return \EE_Soft_Delete_Base_Class[]
867
-     */
868
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
869
-    {
870
-        $questionGroupModel = EEM_Question_Group::instance();
871
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
872
-        if ($count) {
873
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
874
-            $results = $questionGroupModel->count($where);
875
-        } else {
876
-            $results = $questionGroupModel->get_all($query_params);
877
-        }
878
-        return $results;
879
-    }
880
-
881
-
882
-    /**
883
-     * @param      $per_page
884
-     * @param int  $current_page
885
-     * @param bool $count
886
-     * @return \EE_Soft_Delete_Base_Class[]|int
887
-     */
888
-    public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
889
-    {
890
-        $questionGroupModel = EEM_Question_Group::instance();
891
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
892
-        if ($count) {
893
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
894
-            $query_params['limit'] = null;
895
-            $results = $questionGroupModel->count_deleted($where);
896
-        } else {
897
-            $results = $questionGroupModel->get_all_deleted($query_params);
898
-        }
899
-        return $results;
900
-    }
901
-
902
-
903
-    /**
904
-     * method for performing updates to question order
905
-     *
906
-     * @return array results array
907
-     */
908
-    public function update_question_group_order()
909
-    {
910
-
911
-        $success = esc_html__('Question group order was updated successfully.', 'event_espresso');
912
-
913
-        // grab our row IDs
914
-        $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
915
-            ? explode(',', rtrim($this->_req_data['row_ids'], ','))
916
-            : array();
917
-
918
-        $perpage = ! empty($this->_req_data['perpage'])
919
-            ? (int) $this->_req_data['perpage']
920
-            : null;
921
-        $curpage = ! empty($this->_req_data['curpage'])
922
-            ? (int) $this->_req_data['curpage']
923
-            : null;
924
-
925
-        if (! empty($row_ids)) {
926
-            // figure out where we start the row_id count at for the current page.
927
-            $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
928
-
929
-            $row_count = count($row_ids);
930
-            for ($i = 0; $i < $row_count; $i++) {
931
-                // Update the questions when re-ordering
932
-                $updated = EEM_Question_Group::instance()->update(
933
-                    array('QSG_order' => $qsgcount),
934
-                    array(array('QSG_ID' => $row_ids[ $i ]))
935
-                );
936
-                if ($updated === false) {
937
-                    $success = false;
938
-                }
939
-                $qsgcount++;
940
-            }
941
-        } else {
942
-            $success = false;
943
-        }
944
-
945
-        $errors = ! $success
946
-            ? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
947
-            : false;
948
-
949
-        echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
950
-        die();
951
-    }
952
-
953
-
954
-
955
-    /***************************************        REGISTRATION SETTINGS        ***************************************/
956
-
957
-
958
-    /**
959
-     * _reg_form_settings
960
-     *
961
-     * @throws \EE_Error
962
-     */
963
-    protected function _reg_form_settings()
964
-    {
965
-        $this->_template_args['values'] = $this->_yes_no_values;
966
-        add_action(
967
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
968
-            array($this, 'email_validation_settings_form'),
969
-            2
970
-        );
971
-        $this->_template_args = (array) apply_filters(
972
-            'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
973
-            $this->_template_args
974
-        );
975
-        $this->_set_add_edit_form_tags('update_reg_form_settings');
976
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
977
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
978
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
979
-            $this->_template_args,
980
-            true
981
-        );
982
-        $this->display_admin_page_with_sidebar();
983
-    }
984
-
985
-
986
-    /**
987
-     * _update_reg_form_settings
988
-     */
989
-    protected function _update_reg_form_settings()
990
-    {
991
-        EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
992
-            EE_Registry::instance()->CFG->registration
993
-        );
994
-        EE_Registry::instance()->CFG->registration = apply_filters(
995
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
996
-            EE_Registry::instance()->CFG->registration
997
-        );
998
-        $success = $this->_update_espresso_configuration(
999
-            esc_html__('Registration Form Options', 'event_espresso'),
1000
-            EE_Registry::instance()->CFG,
1001
-            __FILE__,
1002
-            __FUNCTION__,
1003
-            __LINE__
1004
-        );
1005
-        $this->_redirect_after_action(
1006
-            $success,
1007
-            esc_html__('Registration Form Options', 'event_espresso'),
1008
-            'updated',
1009
-            array('action' => 'view_reg_form_settings')
1010
-        );
1011
-    }
1012
-
1013
-
1014
-    /**
1015
-     * email_validation_settings_form
1016
-     *
1017
-     * @access    public
1018
-     * @return    void
1019
-     * @throws \EE_Error
1020
-     */
1021
-    public function email_validation_settings_form()
1022
-    {
1023
-        echo $this->_email_validation_settings_form()->get_html();
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * _email_validation_settings_form
1029
-     *
1030
-     * @access protected
1031
-     * @return EE_Form_Section_Proper
1032
-     * @throws \EE_Error
1033
-     */
1034
-    protected function _email_validation_settings_form()
1035
-    {
1036
-        return new EE_Form_Section_Proper(
1037
-            array(
1038
-                'name'            => 'email_validation_settings',
1039
-                'html_id'         => 'email_validation_settings',
1040
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1041
-                'subsections'     => apply_filters(
1042
-                    'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1043
-                    array(
1044
-                        'email_validation_hdr'   => new EE_Form_Section_HTML(
1045
-                            EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1046
-                        ),
1047
-                        'email_validation_level' => new EE_Select_Input(
1048
-                            array(
1049
-                                'basic'      => esc_html__('Basic', 'event_espresso'),
1050
-                                'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1051
-                                'i18n'       => esc_html__('International', 'event_espresso'),
1052
-                                'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1053
-                            ),
1054
-                            array(
1055
-                                'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1056
-                                                     . EEH_Template::get_help_tab_link('email_validation_info'),
1057
-                                'html_help_text'  => esc_html__(
1058
-                                    'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.',
1059
-                                    'event_espresso'
1060
-                                ),
1061
-                                'default'         => isset(
1062
-                                    EE_Registry::instance()->CFG->registration->email_validation_level
1063
-                                )
1064
-                                    ? EE_Registry::instance()->CFG->registration->email_validation_level
1065
-                                    : 'wp_default',
1066
-                                'required'        => false,
1067
-                            )
1068
-                        ),
1069
-                    )
1070
-                ),
1071
-            )
1072
-        );
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * update_email_validation_settings_form
1078
-     *
1079
-     * @access    public
1080
-     * @param \EE_Registration_Config $EE_Registration_Config
1081
-     * @return \EE_Registration_Config
1082
-     */
1083
-    public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1084
-    {
1085
-        $prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1086
-        try {
1087
-            $email_validation_settings_form = $this->_email_validation_settings_form();
1088
-            // if not displaying a form, then check for form submission
1089
-            if ($email_validation_settings_form->was_submitted()) {
1090
-                // capture form data
1091
-                $email_validation_settings_form->receive_form_submission();
1092
-                // validate form data
1093
-                if ($email_validation_settings_form->is_valid()) {
1094
-                    // grab validated data from form
1095
-                    $valid_data = $email_validation_settings_form->valid_data();
1096
-                    if (isset($valid_data['email_validation_level'])) {
1097
-                        $email_validation_level = $valid_data['email_validation_level'];
1098
-                        // now if they want to use international email addresses
1099
-                        if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1100
-                            // in case we need to reset their email validation level,
1101
-                            // make sure that the previous value wasn't already set to one of the i18n options.
1102
-                            if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1103
-                                // if so, then reset it back to "basic" since that is the only other option that,
1104
-                                // despite offering poor validation, supports i18n email addresses
1105
-                                $prev_email_validation_level = 'basic';
1106
-                            }
1107
-                            // confirm our i18n email validation will work on the server
1108
-                            if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1109
-                                // or reset email validation level to previous value
1110
-                                $email_validation_level = $prev_email_validation_level;
1111
-                            }
1112
-                        }
1113
-                        $EE_Registration_Config->email_validation_level = $email_validation_level;
1114
-                    } else {
1115
-                        EE_Error::add_error(
1116
-                            esc_html__(
1117
-                                'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1118
-                                'event_espresso'
1119
-                            ),
1120
-                            __FILE__,
1121
-                            __FUNCTION__,
1122
-                            __LINE__
1123
-                        );
1124
-                    }
1125
-                } else {
1126
-                    if ($email_validation_settings_form->submission_error_message() !== '') {
1127
-                        EE_Error::add_error(
1128
-                            $email_validation_settings_form->submission_error_message(),
1129
-                            __FILE__,
1130
-                            __FUNCTION__,
1131
-                            __LINE__
1132
-                        );
1133
-                    }
1134
-                }
1135
-            }
1136
-        } catch (EE_Error $e) {
1137
-            $e->get_error();
1138
-        }
1139
-        return $EE_Registration_Config;
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * confirms that the server's PHP version has the PCRE module enabled,
1145
-     * and that the PCRE version works with our i18n email validation
1146
-     *
1147
-     * @param \EE_Registration_Config $EE_Registration_Config
1148
-     * @param string                  $email_validation_level
1149
-     * @return bool
1150
-     */
1151
-    private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1152
-    {
1153
-        // first check that PCRE is enabled
1154
-        if (! defined('PREG_BAD_UTF8_ERROR')) {
1155
-            EE_Error::add_error(
1156
-                sprintf(
1157
-                    esc_html__(
1158
-                        'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.',
1159
-                        'event_espresso'
1160
-                    ),
1161
-                    '<br />'
1162
-                ),
1163
-                __FILE__,
1164
-                __FUNCTION__,
1165
-                __LINE__
1166
-            );
1167
-            return false;
1168
-        } else {
1169
-            // PCRE support is enabled, but let's still
1170
-            // perform a test to see if the server will support it.
1171
-            // but first, save the updated validation level to the config,
1172
-            // so that the validation strategy picks it up.
1173
-            // this will get bumped back down if it doesn't work
1174
-            $EE_Registration_Config->email_validation_level = $email_validation_level;
1175
-            try {
1176
-                $email_validator = new EE_Email_Validation_Strategy();
1177
-                $i18n_email_address = apply_filters(
1178
-                    'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1179
-                    'jägerjü[email protected]'
1180
-                );
1181
-                $email_validator->validate($i18n_email_address);
1182
-            } catch (Exception $e) {
1183
-                EE_Error::add_error(
1184
-                    sprintf(
1185
-                        esc_html__(
1186
-                            'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s',
1187
-                            'event_espresso'
1188
-                        ),
1189
-                        '<br />',
1190
-                        '<a href="http://php.net/manual/en/pcre.installation.php" target="_blank">http://php.net/manual/en/pcre.installation.php</a>'
1191
-                    ),
1192
-                    __FILE__,
1193
-                    __FUNCTION__,
1194
-                    __LINE__
1195
-                );
1196
-                return false;
1197
-            }
1198
-        }
1199
-        return true;
1200
-    }
25
+	/**
26
+	 * @Constructor
27
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
28
+	 * @access public
29
+	 */
30
+	public function __construct($routing = true)
31
+	{
32
+		define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form' . DS);
33
+		define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets' . DS);
34
+		define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
35
+		define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates' . DS);
36
+		define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
37
+		parent::__construct($routing);
38
+	}
39
+
40
+
41
+	protected function _extend_page_config()
42
+	{
43
+		$this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
44
+		$qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
45
+			? $this->_req_data['QST_ID'] : 0;
46
+		$qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
47
+			? $this->_req_data['QSG_ID'] : 0;
48
+
49
+		$new_page_routes = array(
50
+			'question_groups'    => array(
51
+				'func'       => '_question_groups_overview_list_table',
52
+				'capability' => 'ee_read_question_groups',
53
+			),
54
+			'add_question'       => array(
55
+				'func'       => '_edit_question',
56
+				'capability' => 'ee_edit_questions',
57
+			),
58
+			'insert_question'    => array(
59
+				'func'       => '_insert_or_update_question',
60
+				'args'       => array('new_question' => true),
61
+				'capability' => 'ee_edit_questions',
62
+				'noheader'   => true,
63
+			),
64
+			'duplicate_question' => array(
65
+				'func'       => '_duplicate_question',
66
+				'capability' => 'ee_edit_questions',
67
+				'noheader'   => true,
68
+			),
69
+			'trash_question'     => array(
70
+				'func'       => '_trash_question',
71
+				'capability' => 'ee_delete_question',
72
+				'obj_id'     => $qst_id,
73
+				'noheader'   => true,
74
+			),
75
+
76
+			'restore_question' => array(
77
+				'func'       => '_trash_or_restore_questions',
78
+				'capability' => 'ee_delete_question',
79
+				'obj_id'     => $qst_id,
80
+				'args'       => array('trash' => false),
81
+				'noheader'   => true,
82
+			),
83
+
84
+			'delete_question' => array(
85
+				'func'       => '_delete_question',
86
+				'capability' => 'ee_delete_question',
87
+				'obj_id'     => $qst_id,
88
+				'noheader'   => true,
89
+			),
90
+
91
+			'trash_questions' => array(
92
+				'func'       => '_trash_or_restore_questions',
93
+				'capability' => 'ee_delete_questions',
94
+				'args'       => array('trash' => true),
95
+				'noheader'   => true,
96
+			),
97
+
98
+			'restore_questions' => array(
99
+				'func'       => '_trash_or_restore_questions',
100
+				'capability' => 'ee_delete_questions',
101
+				'args'       => array('trash' => false),
102
+				'noheader'   => true,
103
+			),
104
+
105
+			'delete_questions' => array(
106
+				'func'       => '_delete_questions',
107
+				'args'       => array(),
108
+				'capability' => 'ee_delete_questions',
109
+				'noheader'   => true,
110
+			),
111
+
112
+			'add_question_group' => array(
113
+				'func'       => '_edit_question_group',
114
+				'capability' => 'ee_edit_question_groups',
115
+			),
116
+
117
+			'edit_question_group' => array(
118
+				'func'       => '_edit_question_group',
119
+				'capability' => 'ee_edit_question_group',
120
+				'obj_id'     => $qsg_id,
121
+				'args'       => array('edit'),
122
+			),
123
+
124
+			'delete_question_groups' => array(
125
+				'func'       => '_delete_question_groups',
126
+				'capability' => 'ee_delete_question_groups',
127
+				'noheader'   => true,
128
+			),
129
+
130
+			'delete_question_group' => array(
131
+				'func'       => '_delete_question_groups',
132
+				'capability' => 'ee_delete_question_group',
133
+				'obj_id'     => $qsg_id,
134
+				'noheader'   => true,
135
+			),
136
+
137
+			'trash_question_group' => array(
138
+				'func'       => '_trash_or_restore_question_groups',
139
+				'args'       => array('trash' => true),
140
+				'capability' => 'ee_delete_question_group',
141
+				'obj_id'     => $qsg_id,
142
+				'noheader'   => true,
143
+			),
144
+
145
+			'restore_question_group' => array(
146
+				'func'       => '_trash_or_restore_question_groups',
147
+				'args'       => array('trash' => false),
148
+				'capability' => 'ee_delete_question_group',
149
+				'obj_id'     => $qsg_id,
150
+				'noheader'   => true,
151
+			),
152
+
153
+			'insert_question_group' => array(
154
+				'func'       => '_insert_or_update_question_group',
155
+				'args'       => array('new_question_group' => true),
156
+				'capability' => 'ee_edit_question_groups',
157
+				'noheader'   => true,
158
+			),
159
+
160
+			'update_question_group' => array(
161
+				'func'       => '_insert_or_update_question_group',
162
+				'args'       => array('new_question_group' => false),
163
+				'capability' => 'ee_edit_question_group',
164
+				'obj_id'     => $qsg_id,
165
+				'noheader'   => true,
166
+			),
167
+
168
+			'trash_question_groups' => array(
169
+				'func'       => '_trash_or_restore_question_groups',
170
+				'args'       => array('trash' => true),
171
+				'capability' => 'ee_delete_question_groups',
172
+				'noheader'   => array('trash' => false),
173
+			),
174
+
175
+			'restore_question_groups' => array(
176
+				'func'       => '_trash_or_restore_question_groups',
177
+				'args'       => array('trash' => false),
178
+				'capability' => 'ee_delete_question_groups',
179
+				'noheader'   => true,
180
+			),
181
+
182
+
183
+			'espresso_update_question_group_order' => array(
184
+				'func'       => 'update_question_group_order',
185
+				'capability' => 'ee_edit_question_groups',
186
+				'noheader'   => true,
187
+			),
188
+
189
+			'view_reg_form_settings' => array(
190
+				'func'       => '_reg_form_settings',
191
+				'capability' => 'manage_options',
192
+			),
193
+
194
+			'update_reg_form_settings' => array(
195
+				'func'       => '_update_reg_form_settings',
196
+				'capability' => 'manage_options',
197
+				'noheader'   => true,
198
+			),
199
+		);
200
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
201
+
202
+		$new_page_config = array(
203
+
204
+			'question_groups' => array(
205
+				'nav'           => array(
206
+					'label' => esc_html__('Question Groups', 'event_espresso'),
207
+					'order' => 20,
208
+				),
209
+				'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
210
+				'help_tabs'     => array(
211
+					'registration_form_question_groups_help_tab'                           => array(
212
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
213
+						'filename' => 'registration_form_question_groups',
214
+					),
215
+					'registration_form_question_groups_table_column_headings_help_tab'     => array(
216
+						'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
217
+						'filename' => 'registration_form_question_groups_table_column_headings',
218
+					),
219
+					'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
220
+						'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
221
+						'filename' => 'registration_form_question_groups_views_bulk_actions_search',
222
+					),
223
+				),
224
+				'help_tour'     => array('Registration_Form_Question_Groups_Help_Tour'),
225
+				'metaboxes'     => $this->_default_espresso_metaboxes,
226
+				'require_nonce' => false,
227
+				'qtips'         => array(
228
+					'EE_Registration_Form_Tips',
229
+				),
230
+			),
231
+
232
+			'add_question' => array(
233
+				'nav'           => array(
234
+					'label'      => esc_html__('Add Question', 'event_espresso'),
235
+					'order'      => 5,
236
+					'persistent' => false,
237
+				),
238
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
239
+				'help_tabs'     => array(
240
+					'registration_form_add_question_help_tab' => array(
241
+						'title'    => esc_html__('Add Question', 'event_espresso'),
242
+						'filename' => 'registration_form_add_question',
243
+					),
244
+				),
245
+				'help_tour'     => array('Registration_Form_Add_Question_Help_Tour'),
246
+				'require_nonce' => false,
247
+			),
248
+
249
+			'add_question_group' => array(
250
+				'nav'           => array(
251
+					'label'      => esc_html__('Add Question Group', 'event_espresso'),
252
+					'order'      => 5,
253
+					'persistent' => false,
254
+				),
255
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
256
+				'help_tabs'     => array(
257
+					'registration_form_add_question_group_help_tab' => array(
258
+						'title'    => esc_html__('Add Question Group', 'event_espresso'),
259
+						'filename' => 'registration_form_add_question_group',
260
+					),
261
+				),
262
+				'help_tour'     => array('Registration_Form_Add_Question_Group_Help_Tour'),
263
+				'require_nonce' => false,
264
+			),
265
+
266
+			'edit_question_group' => array(
267
+				'nav'           => array(
268
+					'label'      => esc_html__('Edit Question Group', 'event_espresso'),
269
+					'order'      => 5,
270
+					'persistent' => false,
271
+					'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
272
+						array('question_group_id' => $this->_req_data['question_group_id']),
273
+						$this->_current_page_view_url
274
+					) : $this->_admin_base_url,
275
+				),
276
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
277
+				'help_tabs'     => array(
278
+					'registration_form_edit_question_group_help_tab' => array(
279
+						'title'    => esc_html__('Edit Question Group', 'event_espresso'),
280
+						'filename' => 'registration_form_edit_question_group',
281
+					),
282
+				),
283
+				'help_tour'     => array('Registration_Form_Edit_Question_Group_Help_Tour'),
284
+				'require_nonce' => false,
285
+			),
286
+
287
+			'view_reg_form_settings' => array(
288
+				'nav'           => array(
289
+					'label' => esc_html__('Reg Form Settings', 'event_espresso'),
290
+					'order' => 40,
291
+				),
292
+				'labels'        => array(
293
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
294
+				),
295
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
296
+				'help_tabs'     => array(
297
+					'registration_form_reg_form_settings_help_tab' => array(
298
+						'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
299
+						'filename' => 'registration_form_reg_form_settings',
300
+					),
301
+				),
302
+				'help_tour'     => array('Registration_Form_Settings_Help_Tour'),
303
+				'require_nonce' => false,
304
+			),
305
+
306
+		);
307
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
308
+
309
+		// change the list table we're going to use so it's the NEW list table!
310
+		$this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
311
+
312
+
313
+		// additional labels
314
+		$new_labels = array(
315
+			'add_question'          => esc_html__('Add New Question', 'event_espresso'),
316
+			'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
317
+			'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
318
+			'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
319
+			'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
320
+		);
321
+		$this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
322
+	}
323
+
324
+
325
+	protected function _ajax_hooks()
326
+	{
327
+		add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
328
+	}
329
+
330
+
331
+	public function load_scripts_styles_question_groups()
332
+	{
333
+		wp_enqueue_script('espresso_ajax_table_sorting');
334
+	}
335
+
336
+
337
+	public function load_scripts_styles_add_question_group()
338
+	{
339
+		$this->load_scripts_styles_forms();
340
+		$this->load_sortable_question_script();
341
+	}
342
+
343
+	public function load_scripts_styles_edit_question_group()
344
+	{
345
+		$this->load_scripts_styles_forms();
346
+		$this->load_sortable_question_script();
347
+	}
348
+
349
+
350
+	/**
351
+	 * registers and enqueues script for questions
352
+	 *
353
+	 * @return void
354
+	 */
355
+	public function load_sortable_question_script()
356
+	{
357
+		wp_register_script(
358
+			'ee-question-sortable',
359
+			REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
360
+			array('jquery-ui-sortable'),
361
+			EVENT_ESPRESSO_VERSION,
362
+			true
363
+		);
364
+		wp_enqueue_script('ee-question-sortable');
365
+	}
366
+
367
+
368
+	protected function _set_list_table_views_default()
369
+	{
370
+		$this->_views = array(
371
+			'all' => array(
372
+				'slug'        => 'all',
373
+				'label'       => esc_html__('View All Questions', 'event_espresso'),
374
+				'count'       => 0,
375
+				'bulk_action' => array(
376
+					'trash_questions' => esc_html__('Trash', 'event_espresso'),
377
+				),
378
+			),
379
+		);
380
+
381
+		if (EE_Registry::instance()->CAP->current_user_can(
382
+			'ee_delete_questions',
383
+			'espresso_registration_form_trash_questions'
384
+		)
385
+		) {
386
+			$this->_views['trash'] = array(
387
+				'slug'        => 'trash',
388
+				'label'       => esc_html__('Trash', 'event_espresso'),
389
+				'count'       => 0,
390
+				'bulk_action' => array(
391
+					'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
392
+					'restore_questions' => esc_html__('Restore', 'event_espresso'),
393
+				),
394
+			);
395
+		}
396
+	}
397
+
398
+
399
+	protected function _set_list_table_views_question_groups()
400
+	{
401
+		$this->_views = array(
402
+			'all' => array(
403
+				'slug'        => 'all',
404
+				'label'       => esc_html__('All', 'event_espresso'),
405
+				'count'       => 0,
406
+				'bulk_action' => array(
407
+					'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
408
+				),
409
+			),
410
+		);
411
+
412
+		if (EE_Registry::instance()->CAP->current_user_can(
413
+			'ee_delete_question_groups',
414
+			'espresso_registration_form_trash_question_groups'
415
+		)
416
+		) {
417
+			$this->_views['trash'] = array(
418
+				'slug'        => 'trash',
419
+				'label'       => esc_html__('Trash', 'event_espresso'),
420
+				'count'       => 0,
421
+				'bulk_action' => array(
422
+					'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
423
+					'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
424
+				),
425
+			);
426
+		}
427
+	}
428
+
429
+
430
+	protected function _questions_overview_list_table()
431
+	{
432
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
433
+			'add_question',
434
+			'add_question',
435
+			array(),
436
+			'add-new-h2'
437
+		);
438
+		parent::_questions_overview_list_table();
439
+	}
440
+
441
+
442
+	protected function _question_groups_overview_list_table()
443
+	{
444
+		$this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
445
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
446
+			'add_question_group',
447
+			'add_question_group',
448
+			array(),
449
+			'add-new-h2'
450
+		);
451
+		$this->display_admin_list_table_page_with_sidebar();
452
+	}
453
+
454
+
455
+	protected function _delete_question()
456
+	{
457
+		$success = $this->_delete_items($this->_question_model);
458
+		$this->_redirect_after_action(
459
+			$success,
460
+			$this->_question_model->item_name($success),
461
+			'deleted',
462
+			array('action' => 'default', 'status' => 'all')
463
+		);
464
+	}
465
+
466
+
467
+	protected function _delete_questions()
468
+	{
469
+		$success = $this->_delete_items($this->_question_model);
470
+		$this->_redirect_after_action(
471
+			$success,
472
+			$this->_question_model->item_name($success),
473
+			'deleted permanently',
474
+			array('action' => 'default', 'status' => 'trash')
475
+		);
476
+	}
477
+
478
+
479
+	/**
480
+	 * Performs the deletion of a single or multiple questions or question groups.
481
+	 *
482
+	 * @param EEM_Soft_Delete_Base $model
483
+	 * @return int number of items deleted permanently
484
+	 */
485
+	private function _delete_items(EEM_Soft_Delete_Base $model)
486
+	{
487
+		$success = 0;
488
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
489
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
490
+			// if array has more than one element than success message should be plural
491
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
492
+			// cycle thru bulk action checkboxes
493
+			while (list($ID, $value) = each($this->_req_data['checkbox'])) {
494
+				if (! $this->_delete_item($ID, $model)) {
495
+					$success = 0;
496
+				}
497
+			}
498
+		} elseif (! empty($this->_req_data['QSG_ID'])) {
499
+			$success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
500
+		} elseif (! empty($this->_req_data['QST_ID'])) {
501
+			$success = $this->_delete_item($this->_req_data['QST_ID'], $model);
502
+		} else {
503
+			EE_Error::add_error(
504
+				sprintf(
505
+					esc_html__(
506
+						"No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.",
507
+						"event_espresso"
508
+					)
509
+				),
510
+				__FILE__,
511
+				__FUNCTION__,
512
+				__LINE__
513
+			);
514
+		}
515
+		return $success;
516
+	}
517
+
518
+	/**
519
+	 * Deletes the specified question (and its associated question options) or question group
520
+	 *
521
+	 * @param int                  $id
522
+	 * @param EEM_Soft_Delete_Base $model
523
+	 * @return boolean
524
+	 */
525
+	protected function _delete_item($id, $model)
526
+	{
527
+		if ($model instanceof EEM_Question) {
528
+			EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
529
+		}
530
+		return $model->delete_permanently_by_ID(absint($id));
531
+	}
532
+
533
+
534
+	/******************************    QUESTION GROUPS    ******************************/
535
+
536
+
537
+	protected function _edit_question_group($type = 'add')
538
+	{
539
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
540
+		$ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID']) ? absint(
541
+			$this->_req_data['QSG_ID']
542
+		) : false;
543
+
544
+		switch ($this->_req_action) {
545
+			case 'add_question_group':
546
+				$this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
547
+				break;
548
+			case 'edit_question_group':
549
+				$this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
550
+				break;
551
+			default:
552
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
553
+		}
554
+		// add ID to title if editing
555
+		$this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
556
+		if ($ID) {
557
+			/** @var EE_Question_Group $questionGroup */
558
+			$questionGroup = $this->_question_group_model->get_one_by_ID($ID);
559
+			$additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
560
+			$this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
561
+		} else {
562
+			/** @var EE_Question_Group $questionGroup */
563
+			$questionGroup = EEM_Question_Group::instance()->create_default_object();
564
+			$questionGroup->set_order_to_latest();
565
+			$this->_set_add_edit_form_tags('insert_question_group');
566
+		}
567
+		$this->_template_args['values'] = $this->_yes_no_values;
568
+		$this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
569
+		$this->_template_args['QSG_ID'] = $ID ? $ID : true;
570
+		$this->_template_args['question_group'] = $questionGroup;
571
+
572
+		$redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
573
+		$this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
574
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
575
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
576
+			$this->_template_args,
577
+			true
578
+		);
579
+
580
+		// the details template wrapper
581
+		$this->display_admin_page_with_sidebar();
582
+	}
583
+
584
+
585
+	protected function _delete_question_groups()
586
+	{
587
+		$success = $this->_delete_items($this->_question_group_model);
588
+		$this->_redirect_after_action(
589
+			$success,
590
+			$this->_question_group_model->item_name($success),
591
+			'deleted permanently',
592
+			array('action' => 'question_groups', 'status' => 'trash')
593
+		);
594
+	}
595
+
596
+
597
+	/**
598
+	 * @param bool $new_question_group
599
+	 */
600
+	protected function _insert_or_update_question_group($new_question_group = true)
601
+	{
602
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
603
+		$set_column_values = $this->_set_column_values_for($this->_question_group_model);
604
+		if ($new_question_group) {
605
+			$QSG_ID = $this->_question_group_model->insert($set_column_values);
606
+			$success = $QSG_ID ? 1 : 0;
607
+		} else {
608
+			$QSG_ID = absint($this->_req_data['QSG_ID']);
609
+			unset($set_column_values['QSG_ID']);
610
+			$success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
611
+		}
612
+		$phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
613
+			EEM_Attendee::system_question_phone
614
+		);
615
+		// update the existing related questions
616
+		// BUT FIRST...  delete the phone question from the Question_Group_Question if it is being added to this question group (therefore removed from the existing group)
617
+		if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
618
+			// delete where QST ID = system phone question ID and Question Group ID is NOT this group
619
+			EEM_Question_Group_Question::instance()->delete(
620
+				array(
621
+					array(
622
+						'QST_ID' => $phone_question_id,
623
+						'QSG_ID' => array('!=', $QSG_ID),
624
+					),
625
+				)
626
+			);
627
+		}
628
+		/** @type EE_Question_Group $question_group */
629
+		$question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
630
+		$questions = $question_group->questions();
631
+		// make sure system phone question is added to list of questions for this group
632
+		if (! isset($questions[ $phone_question_id ])) {
633
+			$questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
634
+		}
635
+
636
+		foreach ($questions as $question_ID => $question) {
637
+			// first we always check for order.
638
+			if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
639
+				// update question order
640
+				$question_group->update_question_order(
641
+					$question_ID,
642
+					$this->_req_data['question_orders'][ $question_ID ]
643
+				);
644
+			}
645
+
646
+			// then we always check if adding or removing.
647
+			if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
648
+				$question_group->add_question($question_ID);
649
+			} else {
650
+				// not found, remove it (but only if not a system question for the personal group with the exception of lname system question - we allow removal of it)
651
+				if (in_array(
652
+					$question->system_ID(),
653
+					EEM_Question::instance()->required_system_questions_in_system_question_group(
654
+						$question_group->system_group()
655
+					)
656
+				)) {
657
+					continue;
658
+				} else {
659
+					$question_group->remove_question($question_ID);
660
+				}
661
+			}
662
+		}
663
+		// save new related questions
664
+		if (isset($this->_req_data['questions'])) {
665
+			foreach ($this->_req_data['questions'] as $QST_ID) {
666
+				$question_group->add_question($QST_ID);
667
+				if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
668
+					$question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
669
+				}
670
+			}
671
+		}
672
+
673
+		if ($success !== false) {
674
+			$msg = $new_question_group
675
+				? sprintf(
676
+					esc_html__('The %s has been created', 'event_espresso'),
677
+					$this->_question_group_model->item_name()
678
+				)
679
+				: sprintf(
680
+					esc_html__(
681
+						'The %s has been updated',
682
+						'event_espresso'
683
+					),
684
+					$this->_question_group_model->item_name()
685
+				);
686
+			EE_Error::add_success($msg);
687
+		}
688
+		$this->_redirect_after_action(
689
+			false,
690
+			'',
691
+			'',
692
+			array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
693
+			true
694
+		);
695
+	}
696
+
697
+	/**
698
+	 * duplicates a question and all its question options and redirects to the new question.
699
+	 */
700
+	public function _duplicate_question()
701
+	{
702
+		$question_ID = (int) $this->_req_data['QST_ID'];
703
+		$question = EEM_Question::instance()->get_one_by_ID($question_ID);
704
+		if ($question instanceof EE_Question) {
705
+			$new_question = $question->duplicate();
706
+			if ($new_question instanceof EE_Question) {
707
+				$this->_redirect_after_action(
708
+					true,
709
+					esc_html__('Question', 'event_espresso'),
710
+					esc_html__('Duplicated', 'event_espresso'),
711
+					array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
712
+					true
713
+				);
714
+			} else {
715
+				global $wpdb;
716
+				EE_Error::add_error(
717
+					sprintf(
718
+						esc_html__(
719
+							'Could not duplicate question with ID %1$d because: %2$s',
720
+							'event_espresso'
721
+						),
722
+						$question_ID,
723
+						$wpdb->last_error
724
+					),
725
+					__FILE__,
726
+					__FUNCTION__,
727
+					__LINE__
728
+				);
729
+				$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
730
+			}
731
+		} else {
732
+			EE_Error::add_error(
733
+				sprintf(
734
+					esc_html__(
735
+						'Could not duplicate question with ID %d because it didn\'t exist!',
736
+						'event_espresso'
737
+					),
738
+					$question_ID
739
+				),
740
+				__FILE__,
741
+				__FUNCTION__,
742
+				__LINE__
743
+			);
744
+			$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
745
+		}
746
+	}
747
+
748
+
749
+	/**
750
+	 * @param bool $trash
751
+	 */
752
+	protected function _trash_or_restore_question_groups($trash = true)
753
+	{
754
+		$this->_trash_or_restore_items($this->_question_group_model, $trash);
755
+	}
756
+
757
+
758
+	/**
759
+	 *_trash_question
760
+	 */
761
+	protected function _trash_question()
762
+	{
763
+		$success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
764
+		$query_args = array('action' => 'default', 'status' => 'all');
765
+		$this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
766
+	}
767
+
768
+
769
+	/**
770
+	 * @param bool $trash
771
+	 */
772
+	protected function _trash_or_restore_questions($trash = true)
773
+	{
774
+		$this->_trash_or_restore_items($this->_question_model, $trash);
775
+	}
776
+
777
+
778
+	/**
779
+	 * Internally used to delete or restore items, using the request data. Meant to be
780
+	 * flexible between question or question groups
781
+	 *
782
+	 * @param EEM_Soft_Delete_Base $model
783
+	 * @param boolean              $trash whether to trash or restore
784
+	 */
785
+	private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
786
+	{
787
+
788
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
789
+
790
+		$success = 1;
791
+		// Checkboxes
792
+		// echo "trash $trash";
793
+		// var_dump($this->_req_data['checkbox']);die;
794
+		if (isset($this->_req_data['checkbox'])) {
795
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
796
+				// if array has more than one element than success message should be plural
797
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
798
+				// cycle thru bulk action checkboxes
799
+				while (list($ID, $value) = each($this->_req_data['checkbox'])) {
800
+					if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
801
+						$success = 0;
802
+					}
803
+				}
804
+			} else {
805
+				// grab single id and delete
806
+				$ID = absint($this->_req_data['checkbox']);
807
+				if (! $model->delete_or_restore_by_ID($trash, $ID)) {
808
+					$success = 0;
809
+				}
810
+			}
811
+		} else {
812
+			// delete via trash link
813
+			// grab single id and delete
814
+			$ID = absint($this->_req_data[ $model->primary_key_name() ]);
815
+			if (! $model->delete_or_restore_by_ID($trash, $ID)) {
816
+				$success = 0;
817
+			}
818
+		}
819
+
820
+
821
+		$action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
822
+		// echo "action :$action";
823
+		// $action = 'questions' ? 'default' : $action;
824
+		if ($trash) {
825
+			$action_desc = 'trashed';
826
+			$status = 'trash';
827
+		} else {
828
+			$action_desc = 'restored';
829
+			$status = 'all';
830
+		}
831
+		$this->_redirect_after_action(
832
+			$success,
833
+			$model->item_name($success),
834
+			$action_desc,
835
+			array('action' => $action, 'status' => $status)
836
+		);
837
+	}
838
+
839
+
840
+	/**
841
+	 * @param            $per_page
842
+	 * @param int        $current_page
843
+	 * @param bool|false $count
844
+	 * @return \EE_Soft_Delete_Base_Class[]|int
845
+	 */
846
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
847
+	{
848
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
849
+
850
+		if ($count) {
851
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
852
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
853
+			$results = $this->_question_model->count_deleted($where);
854
+		} else {
855
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
856
+			$results = $this->_question_model->get_all_deleted($query_params);
857
+		}
858
+		return $results;
859
+	}
860
+
861
+
862
+	/**
863
+	 * @param            $per_page
864
+	 * @param int        $current_page
865
+	 * @param bool|false $count
866
+	 * @return \EE_Soft_Delete_Base_Class[]
867
+	 */
868
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
869
+	{
870
+		$questionGroupModel = EEM_Question_Group::instance();
871
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
872
+		if ($count) {
873
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
874
+			$results = $questionGroupModel->count($where);
875
+		} else {
876
+			$results = $questionGroupModel->get_all($query_params);
877
+		}
878
+		return $results;
879
+	}
880
+
881
+
882
+	/**
883
+	 * @param      $per_page
884
+	 * @param int  $current_page
885
+	 * @param bool $count
886
+	 * @return \EE_Soft_Delete_Base_Class[]|int
887
+	 */
888
+	public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
889
+	{
890
+		$questionGroupModel = EEM_Question_Group::instance();
891
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
892
+		if ($count) {
893
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
894
+			$query_params['limit'] = null;
895
+			$results = $questionGroupModel->count_deleted($where);
896
+		} else {
897
+			$results = $questionGroupModel->get_all_deleted($query_params);
898
+		}
899
+		return $results;
900
+	}
901
+
902
+
903
+	/**
904
+	 * method for performing updates to question order
905
+	 *
906
+	 * @return array results array
907
+	 */
908
+	public function update_question_group_order()
909
+	{
910
+
911
+		$success = esc_html__('Question group order was updated successfully.', 'event_espresso');
912
+
913
+		// grab our row IDs
914
+		$row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
915
+			? explode(',', rtrim($this->_req_data['row_ids'], ','))
916
+			: array();
917
+
918
+		$perpage = ! empty($this->_req_data['perpage'])
919
+			? (int) $this->_req_data['perpage']
920
+			: null;
921
+		$curpage = ! empty($this->_req_data['curpage'])
922
+			? (int) $this->_req_data['curpage']
923
+			: null;
924
+
925
+		if (! empty($row_ids)) {
926
+			// figure out where we start the row_id count at for the current page.
927
+			$qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
928
+
929
+			$row_count = count($row_ids);
930
+			for ($i = 0; $i < $row_count; $i++) {
931
+				// Update the questions when re-ordering
932
+				$updated = EEM_Question_Group::instance()->update(
933
+					array('QSG_order' => $qsgcount),
934
+					array(array('QSG_ID' => $row_ids[ $i ]))
935
+				);
936
+				if ($updated === false) {
937
+					$success = false;
938
+				}
939
+				$qsgcount++;
940
+			}
941
+		} else {
942
+			$success = false;
943
+		}
944
+
945
+		$errors = ! $success
946
+			? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
947
+			: false;
948
+
949
+		echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
950
+		die();
951
+	}
952
+
953
+
954
+
955
+	/***************************************        REGISTRATION SETTINGS        ***************************************/
956
+
957
+
958
+	/**
959
+	 * _reg_form_settings
960
+	 *
961
+	 * @throws \EE_Error
962
+	 */
963
+	protected function _reg_form_settings()
964
+	{
965
+		$this->_template_args['values'] = $this->_yes_no_values;
966
+		add_action(
967
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
968
+			array($this, 'email_validation_settings_form'),
969
+			2
970
+		);
971
+		$this->_template_args = (array) apply_filters(
972
+			'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
973
+			$this->_template_args
974
+		);
975
+		$this->_set_add_edit_form_tags('update_reg_form_settings');
976
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
977
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
978
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
979
+			$this->_template_args,
980
+			true
981
+		);
982
+		$this->display_admin_page_with_sidebar();
983
+	}
984
+
985
+
986
+	/**
987
+	 * _update_reg_form_settings
988
+	 */
989
+	protected function _update_reg_form_settings()
990
+	{
991
+		EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
992
+			EE_Registry::instance()->CFG->registration
993
+		);
994
+		EE_Registry::instance()->CFG->registration = apply_filters(
995
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
996
+			EE_Registry::instance()->CFG->registration
997
+		);
998
+		$success = $this->_update_espresso_configuration(
999
+			esc_html__('Registration Form Options', 'event_espresso'),
1000
+			EE_Registry::instance()->CFG,
1001
+			__FILE__,
1002
+			__FUNCTION__,
1003
+			__LINE__
1004
+		);
1005
+		$this->_redirect_after_action(
1006
+			$success,
1007
+			esc_html__('Registration Form Options', 'event_espresso'),
1008
+			'updated',
1009
+			array('action' => 'view_reg_form_settings')
1010
+		);
1011
+	}
1012
+
1013
+
1014
+	/**
1015
+	 * email_validation_settings_form
1016
+	 *
1017
+	 * @access    public
1018
+	 * @return    void
1019
+	 * @throws \EE_Error
1020
+	 */
1021
+	public function email_validation_settings_form()
1022
+	{
1023
+		echo $this->_email_validation_settings_form()->get_html();
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * _email_validation_settings_form
1029
+	 *
1030
+	 * @access protected
1031
+	 * @return EE_Form_Section_Proper
1032
+	 * @throws \EE_Error
1033
+	 */
1034
+	protected function _email_validation_settings_form()
1035
+	{
1036
+		return new EE_Form_Section_Proper(
1037
+			array(
1038
+				'name'            => 'email_validation_settings',
1039
+				'html_id'         => 'email_validation_settings',
1040
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1041
+				'subsections'     => apply_filters(
1042
+					'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1043
+					array(
1044
+						'email_validation_hdr'   => new EE_Form_Section_HTML(
1045
+							EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1046
+						),
1047
+						'email_validation_level' => new EE_Select_Input(
1048
+							array(
1049
+								'basic'      => esc_html__('Basic', 'event_espresso'),
1050
+								'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1051
+								'i18n'       => esc_html__('International', 'event_espresso'),
1052
+								'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1053
+							),
1054
+							array(
1055
+								'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1056
+													 . EEH_Template::get_help_tab_link('email_validation_info'),
1057
+								'html_help_text'  => esc_html__(
1058
+									'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.',
1059
+									'event_espresso'
1060
+								),
1061
+								'default'         => isset(
1062
+									EE_Registry::instance()->CFG->registration->email_validation_level
1063
+								)
1064
+									? EE_Registry::instance()->CFG->registration->email_validation_level
1065
+									: 'wp_default',
1066
+								'required'        => false,
1067
+							)
1068
+						),
1069
+					)
1070
+				),
1071
+			)
1072
+		);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * update_email_validation_settings_form
1078
+	 *
1079
+	 * @access    public
1080
+	 * @param \EE_Registration_Config $EE_Registration_Config
1081
+	 * @return \EE_Registration_Config
1082
+	 */
1083
+	public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1084
+	{
1085
+		$prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1086
+		try {
1087
+			$email_validation_settings_form = $this->_email_validation_settings_form();
1088
+			// if not displaying a form, then check for form submission
1089
+			if ($email_validation_settings_form->was_submitted()) {
1090
+				// capture form data
1091
+				$email_validation_settings_form->receive_form_submission();
1092
+				// validate form data
1093
+				if ($email_validation_settings_form->is_valid()) {
1094
+					// grab validated data from form
1095
+					$valid_data = $email_validation_settings_form->valid_data();
1096
+					if (isset($valid_data['email_validation_level'])) {
1097
+						$email_validation_level = $valid_data['email_validation_level'];
1098
+						// now if they want to use international email addresses
1099
+						if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1100
+							// in case we need to reset their email validation level,
1101
+							// make sure that the previous value wasn't already set to one of the i18n options.
1102
+							if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1103
+								// if so, then reset it back to "basic" since that is the only other option that,
1104
+								// despite offering poor validation, supports i18n email addresses
1105
+								$prev_email_validation_level = 'basic';
1106
+							}
1107
+							// confirm our i18n email validation will work on the server
1108
+							if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1109
+								// or reset email validation level to previous value
1110
+								$email_validation_level = $prev_email_validation_level;
1111
+							}
1112
+						}
1113
+						$EE_Registration_Config->email_validation_level = $email_validation_level;
1114
+					} else {
1115
+						EE_Error::add_error(
1116
+							esc_html__(
1117
+								'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1118
+								'event_espresso'
1119
+							),
1120
+							__FILE__,
1121
+							__FUNCTION__,
1122
+							__LINE__
1123
+						);
1124
+					}
1125
+				} else {
1126
+					if ($email_validation_settings_form->submission_error_message() !== '') {
1127
+						EE_Error::add_error(
1128
+							$email_validation_settings_form->submission_error_message(),
1129
+							__FILE__,
1130
+							__FUNCTION__,
1131
+							__LINE__
1132
+						);
1133
+					}
1134
+				}
1135
+			}
1136
+		} catch (EE_Error $e) {
1137
+			$e->get_error();
1138
+		}
1139
+		return $EE_Registration_Config;
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * confirms that the server's PHP version has the PCRE module enabled,
1145
+	 * and that the PCRE version works with our i18n email validation
1146
+	 *
1147
+	 * @param \EE_Registration_Config $EE_Registration_Config
1148
+	 * @param string                  $email_validation_level
1149
+	 * @return bool
1150
+	 */
1151
+	private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1152
+	{
1153
+		// first check that PCRE is enabled
1154
+		if (! defined('PREG_BAD_UTF8_ERROR')) {
1155
+			EE_Error::add_error(
1156
+				sprintf(
1157
+					esc_html__(
1158
+						'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.',
1159
+						'event_espresso'
1160
+					),
1161
+					'<br />'
1162
+				),
1163
+				__FILE__,
1164
+				__FUNCTION__,
1165
+				__LINE__
1166
+			);
1167
+			return false;
1168
+		} else {
1169
+			// PCRE support is enabled, but let's still
1170
+			// perform a test to see if the server will support it.
1171
+			// but first, save the updated validation level to the config,
1172
+			// so that the validation strategy picks it up.
1173
+			// this will get bumped back down if it doesn't work
1174
+			$EE_Registration_Config->email_validation_level = $email_validation_level;
1175
+			try {
1176
+				$email_validator = new EE_Email_Validation_Strategy();
1177
+				$i18n_email_address = apply_filters(
1178
+					'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1179
+					'jägerjü[email protected]'
1180
+				);
1181
+				$email_validator->validate($i18n_email_address);
1182
+			} catch (Exception $e) {
1183
+				EE_Error::add_error(
1184
+					sprintf(
1185
+						esc_html__(
1186
+							'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s',
1187
+							'event_espresso'
1188
+						),
1189
+						'<br />',
1190
+						'<a href="http://php.net/manual/en/pcre.installation.php" target="_blank">http://php.net/manual/en/pcre.installation.php</a>'
1191
+					),
1192
+					__FILE__,
1193
+					__FUNCTION__,
1194
+					__LINE__
1195
+				);
1196
+				return false;
1197
+			}
1198
+		}
1199
+		return true;
1200
+	}
1201 1201
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -29,11 +29,11 @@  discard block
 block discarded – undo
29 29
      */
30 30
     public function __construct($routing = true)
31 31
     {
32
-        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form' . DS);
33
-        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets' . DS);
34
-        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
35
-        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates' . DS);
36
-        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
32
+        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND.'registration_form'.DS);
33
+        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN.'assets'.DS);
34
+        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registration_form/assets/');
35
+        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN.'templates'.DS);
36
+        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registration_form/templates/');
37 37
         parent::__construct($routing);
38 38
     }
39 39
 
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
     {
357 357
         wp_register_script(
358 358
             'ee-question-sortable',
359
-            REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
359
+            REGISTRATION_FORM_CAF_ASSETS_URL.'ee_question_order.js',
360 360
             array('jquery-ui-sortable'),
361 361
             EVENT_ESPRESSO_VERSION,
362 362
             true
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
 
430 430
     protected function _questions_overview_list_table()
431 431
     {
432
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
432
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
433 433
             'add_question',
434 434
             'add_question',
435 435
             array(),
@@ -442,7 +442,7 @@  discard block
 block discarded – undo
442 442
     protected function _question_groups_overview_list_table()
443 443
     {
444 444
         $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
445
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
445
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
446 446
             'add_question_group',
447 447
             'add_question_group',
448 448
             array(),
@@ -486,18 +486,18 @@  discard block
 block discarded – undo
486 486
     {
487 487
         $success = 0;
488 488
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
489
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
489
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
490 490
             // if array has more than one element than success message should be plural
491 491
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
492 492
             // cycle thru bulk action checkboxes
493 493
             while (list($ID, $value) = each($this->_req_data['checkbox'])) {
494
-                if (! $this->_delete_item($ID, $model)) {
494
+                if ( ! $this->_delete_item($ID, $model)) {
495 495
                     $success = 0;
496 496
                 }
497 497
             }
498
-        } elseif (! empty($this->_req_data['QSG_ID'])) {
498
+        } elseif ( ! empty($this->_req_data['QSG_ID'])) {
499 499
             $success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
500
-        } elseif (! empty($this->_req_data['QST_ID'])) {
500
+        } elseif ( ! empty($this->_req_data['QST_ID'])) {
501 501
             $success = $this->_delete_item($this->_req_data['QST_ID'], $model);
502 502
         } else {
503 503
             EE_Error::add_error(
@@ -552,7 +552,7 @@  discard block
 block discarded – undo
552 552
                 $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
553 553
         }
554 554
         // add ID to title if editing
555
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
555
+        $this->_admin_page_title = $ID ? $this->_admin_page_title.' # '.$ID : $this->_admin_page_title;
556 556
         if ($ID) {
557 557
             /** @var EE_Question_Group $questionGroup */
558 558
             $questionGroup = $this->_question_group_model->get_one_by_ID($ID);
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
         $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
573 573
         $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
574 574
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
575
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
575
+            REGISTRATION_FORM_CAF_TEMPLATE_PATH.'question_groups_main_meta_box.template.php',
576 576
             $this->_template_args,
577 577
             true
578 578
         );
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
         );
615 615
         // update the existing related questions
616 616
         // BUT FIRST...  delete the phone question from the Question_Group_Question if it is being added to this question group (therefore removed from the existing group)
617
-        if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
617
+        if (isset($this->_req_data['questions'], $this->_req_data['questions'][$phone_question_id])) {
618 618
             // delete where QST ID = system phone question ID and Question Group ID is NOT this group
619 619
             EEM_Question_Group_Question::instance()->delete(
620 620
                 array(
@@ -629,22 +629,22 @@  discard block
 block discarded – undo
629 629
         $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
630 630
         $questions = $question_group->questions();
631 631
         // make sure system phone question is added to list of questions for this group
632
-        if (! isset($questions[ $phone_question_id ])) {
633
-            $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
632
+        if ( ! isset($questions[$phone_question_id])) {
633
+            $questions[$phone_question_id] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
634 634
         }
635 635
 
636 636
         foreach ($questions as $question_ID => $question) {
637 637
             // first we always check for order.
638
-            if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
638
+            if ( ! empty($this->_req_data['question_orders'][$question_ID])) {
639 639
                 // update question order
640 640
                 $question_group->update_question_order(
641 641
                     $question_ID,
642
-                    $this->_req_data['question_orders'][ $question_ID ]
642
+                    $this->_req_data['question_orders'][$question_ID]
643 643
                 );
644 644
             }
645 645
 
646 646
             // then we always check if adding or removing.
647
-            if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
647
+            if (isset($this->_req_data['questions'], $this->_req_data['questions'][$question_ID])) {
648 648
                 $question_group->add_question($question_ID);
649 649
             } else {
650 650
                 // not found, remove it (but only if not a system question for the personal group with the exception of lname system question - we allow removal of it)
@@ -664,8 +664,8 @@  discard block
 block discarded – undo
664 664
         if (isset($this->_req_data['questions'])) {
665 665
             foreach ($this->_req_data['questions'] as $QST_ID) {
666 666
                 $question_group->add_question($QST_ID);
667
-                if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
668
-                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
667
+                if (isset($this->_req_data['question_orders'][$QST_ID])) {
668
+                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][$QST_ID]);
669 669
                 }
670 670
             }
671 671
         }
@@ -792,33 +792,33 @@  discard block
 block discarded – undo
792 792
         // echo "trash $trash";
793 793
         // var_dump($this->_req_data['checkbox']);die;
794 794
         if (isset($this->_req_data['checkbox'])) {
795
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
795
+            if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
796 796
                 // if array has more than one element than success message should be plural
797 797
                 $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
798 798
                 // cycle thru bulk action checkboxes
799 799
                 while (list($ID, $value) = each($this->_req_data['checkbox'])) {
800
-                    if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
800
+                    if ( ! $model->delete_or_restore_by_ID($trash, absint($ID))) {
801 801
                         $success = 0;
802 802
                     }
803 803
                 }
804 804
             } else {
805 805
                 // grab single id and delete
806 806
                 $ID = absint($this->_req_data['checkbox']);
807
-                if (! $model->delete_or_restore_by_ID($trash, $ID)) {
807
+                if ( ! $model->delete_or_restore_by_ID($trash, $ID)) {
808 808
                     $success = 0;
809 809
                 }
810 810
             }
811 811
         } else {
812 812
             // delete via trash link
813 813
             // grab single id and delete
814
-            $ID = absint($this->_req_data[ $model->primary_key_name() ]);
815
-            if (! $model->delete_or_restore_by_ID($trash, $ID)) {
814
+            $ID = absint($this->_req_data[$model->primary_key_name()]);
815
+            if ( ! $model->delete_or_restore_by_ID($trash, $ID)) {
816 816
                 $success = 0;
817 817
             }
818 818
         }
819 819
 
820 820
 
821
-        $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
821
+        $action = $model instanceof EEM_Question ? 'default' : 'question_groups'; // strtolower( $model->item_name(2) );
822 822
         // echo "action :$action";
823 823
         // $action = 'questions' ? 'default' : $action;
824 824
         if ($trash) {
@@ -922,7 +922,7 @@  discard block
 block discarded – undo
922 922
             ? (int) $this->_req_data['curpage']
923 923
             : null;
924 924
 
925
-        if (! empty($row_ids)) {
925
+        if ( ! empty($row_ids)) {
926 926
             // figure out where we start the row_id count at for the current page.
927 927
             $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
928 928
 
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
                 // Update the questions when re-ordering
932 932
                 $updated = EEM_Question_Group::instance()->update(
933 933
                     array('QSG_order' => $qsgcount),
934
-                    array(array('QSG_ID' => $row_ids[ $i ]))
934
+                    array(array('QSG_ID' => $row_ids[$i]))
935 935
                 );
936 936
                 if ($updated === false) {
937 937
                     $success = false;
@@ -975,7 +975,7 @@  discard block
 block discarded – undo
975 975
         $this->_set_add_edit_form_tags('update_reg_form_settings');
976 976
         $this->_set_publish_post_box_vars(null, false, false, null, false);
977 977
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
978
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
978
+            REGISTRATION_FORM_CAF_TEMPLATE_PATH.'reg_form_settings.template.php',
979 979
             $this->_template_args,
980 980
             true
981 981
         );
@@ -1105,7 +1105,7 @@  discard block
 block discarded – undo
1105 1105
                                 $prev_email_validation_level = 'basic';
1106 1106
                             }
1107 1107
                             // confirm our i18n email validation will work on the server
1108
-                            if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1108
+                            if ( ! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1109 1109
                                 // or reset email validation level to previous value
1110 1110
                                 $email_validation_level = $prev_email_validation_level;
1111 1111
                             }
@@ -1151,7 +1151,7 @@  discard block
 block discarded – undo
1151 1151
     private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1152 1152
     {
1153 1153
         // first check that PCRE is enabled
1154
-        if (! defined('PREG_BAD_UTF8_ERROR')) {
1154
+        if ( ! defined('PREG_BAD_UTF8_ERROR')) {
1155 1155
             EE_Error::add_error(
1156 1156
                 sprintf(
1157 1157
                     esc_html__(
Please login to merge, or discard this patch.