Completed
Branch updates-from-cafe (bae82c)
by
unknown
24:44 queued 16:55
created
core/EE_Registry.core.php 2 patches
Indentation   +1716 added lines, -1716 removed lines patch added patch discarded remove patch
@@ -22,1720 +22,1720 @@
 block discarded – undo
22 22
  */
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25
-    /**
26
-     * @var EE_Registry $_instance
27
-     */
28
-    private static $_instance;
29
-
30
-    /**
31
-     * @var EE_Dependency_Map $_dependency_map
32
-     */
33
-    protected $_dependency_map;
34
-
35
-    /**
36
-     * @var Mirror
37
-     */
38
-    private $mirror;
39
-
40
-    /**
41
-     * @var ClassInterfaceCache $class_cache
42
-     */
43
-    private $class_cache;
44
-
45
-    /**
46
-     * @var array $_class_abbreviations
47
-     */
48
-    protected $_class_abbreviations = [];
49
-
50
-    /**
51
-     * @var CommandBusInterface $BUS
52
-     */
53
-    public $BUS;
54
-
55
-    /**
56
-     * @var EE_Cart $CART
57
-     */
58
-    public $CART;
59
-
60
-    /**
61
-     * @var EE_Config $CFG
62
-     */
63
-    public $CFG;
64
-
65
-    /**
66
-     * @var EE_Network_Config $NET_CFG
67
-     */
68
-    public $NET_CFG;
69
-
70
-    /**
71
-     * RegistryContainer for storing library classes in
72
-     *
73
-     * @var RegistryContainer $LIB
74
-     */
75
-    public $LIB;
76
-
77
-    /**
78
-     * @var EE_Request_Handler $REQ
79
-     * @deprecated 4.10.14.p
80
-     */
81
-    public $REQ;
82
-
83
-    /**
84
-     * @var EE_Session $SSN
85
-     */
86
-    public $SSN;
87
-
88
-    /**
89
-     * @since 4.5.0
90
-     * @var EE_Capabilities $CAP
91
-     */
92
-    public $CAP;
93
-
94
-    /**
95
-     * @since 4.9.0
96
-     * @var EE_Message_Resource_Manager $MRM
97
-     */
98
-    public $MRM;
99
-
100
-    /**
101
-     * @var Registry $AssetsRegistry
102
-     */
103
-    public $AssetsRegistry;
104
-
105
-    /**
106
-     * RegistryContainer for holding addons which have registered themselves to work with EE core
107
-     *
108
-     * @var RegistryContainer|EE_Addon[] $addons
109
-     */
110
-    public $addons;
111
-
112
-    /**
113
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
-     *
115
-     * @var EEM_Base[] $models
116
-     */
117
-    public $models = [];
118
-
119
-    /**
120
-     * @var RegistryContainer|EED_Module[] $modules
121
-     */
122
-    public $modules;
123
-
124
-    /**
125
-     * @var RegistryContainer|EES_Shortcode[] $shortcodes
126
-     */
127
-    public $shortcodes;
128
-
129
-    /**
130
-     * @var RegistryContainer|WP_Widget[] $widgets
131
-     */
132
-    public $widgets;
133
-
134
-    /**
135
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
-     * classnames (eg "EEM_Event")
139
-     *
140
-     * @var array $non_abstract_db_models
141
-     */
142
-    public $non_abstract_db_models = [];
143
-
144
-    /**
145
-     * internationalization for JS strings
146
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
-     *    in js file:  var translatedString = eei18n.string_key;
148
-     *
149
-     * @var array $i18n_js_strings
150
-     */
151
-    public static $i18n_js_strings = [];
152
-
153
-    /**
154
-     * $main_file - path to espresso.php
155
-     *
156
-     * @var array $main_file
157
-     */
158
-    public $main_file;
159
-
160
-    /**
161
-     * array of ReflectionClass objects where the key is the class name
162
-     *
163
-     * @deprecated 4.9.62.p
164
-     * @var ReflectionClass[] $_reflectors
165
-     */
166
-    public $_reflectors;
167
-
168
-    /**
169
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
-     *
171
-     * @var boolean $_cache_on
172
-     */
173
-    protected $_cache_on = true;
174
-
175
-    /**
176
-     * @var ObjectIdentifier
177
-     */
178
-    private $object_identifier;
179
-
180
-
181
-    /**
182
-     * @singleton method used to instantiate class object
183
-     * @param EE_Dependency_Map|null   $dependency_map
184
-     * @param Mirror|null              $mirror
185
-     * @param ClassInterfaceCache|null $class_cache
186
-     * @param ObjectIdentifier|null    $object_identifier
187
-     * @return EE_Registry instance
188
-     */
189
-    public static function instance(
190
-        EE_Dependency_Map $dependency_map = null,
191
-        Mirror $mirror = null,
192
-        ClassInterfaceCache $class_cache = null,
193
-        ObjectIdentifier $object_identifier = null
194
-    ): EE_Registry {
195
-        // check if class object is instantiated
196
-        if (
197
-            ! self::$_instance instanceof EE_Registry
198
-            && $dependency_map instanceof EE_Dependency_Map
199
-            && $mirror instanceof Mirror
200
-            && $class_cache instanceof ClassInterfaceCache
201
-            && $object_identifier instanceof ObjectIdentifier
202
-        ) {
203
-            self::$_instance = new self(
204
-                $dependency_map,
205
-                $mirror,
206
-                $class_cache,
207
-                $object_identifier
208
-            );
209
-        }
210
-        return self::$_instance;
211
-    }
212
-
213
-
214
-    /**
215
-     * protected constructor to prevent direct creation
216
-     *
217
-     * @Constructor
218
-     * @param EE_Dependency_Map   $dependency_map
219
-     * @param Mirror              $mirror
220
-     * @param ClassInterfaceCache $class_cache
221
-     * @param ObjectIdentifier    $object_identifier
222
-     */
223
-    protected function __construct(
224
-        EE_Dependency_Map $dependency_map,
225
-        Mirror $mirror,
226
-        ClassInterfaceCache $class_cache,
227
-        ObjectIdentifier $object_identifier
228
-    ) {
229
-        $this->_dependency_map   = $dependency_map;
230
-        $this->mirror            = $mirror;
231
-        $this->class_cache       = $class_cache;
232
-        $this->object_identifier = $object_identifier;
233
-        // $registry_container = new RegistryContainer();
234
-        $this->LIB        = new RegistryContainer();
235
-        $this->addons     = new RegistryContainer();
236
-        $this->modules    = new RegistryContainer();
237
-        $this->shortcodes = new RegistryContainer();
238
-        $this->widgets    = new RegistryContainer();
239
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
240
-    }
241
-
242
-
243
-    /**
244
-     * initialize
245
-     *
246
-     * @throws OutOfBoundsException
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidInterfaceException
249
-     * @throws InvalidDataTypeException
250
-     * @throws EE_Error
251
-     * @throws ReflectionException
252
-     */
253
-    public function initialize()
254
-    {
255
-        $this->_class_abbreviations = apply_filters(
256
-            'FHEE__EE_Registry____construct___class_abbreviations',
257
-            [
258
-                'EE_Config'                                       => 'CFG',
259
-                'EE_Session'                                      => 'SSN',
260
-                'EE_Capabilities'                                 => 'CAP',
261
-                'EE_Cart'                                         => 'CART',
262
-                'EE_Network_Config'                               => 'NET_CFG',
263
-                'EE_Request_Handler'                              => 'REQ',
264
-                'EE_Message_Resource_Manager'                     => 'MRM',
265
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
266
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
267
-            ]
268
-        );
269
-        $this->load_core('Base', [], true);
270
-        // add our request and response objects to the cache
271
-        $request_loader = $this->_dependency_map->class_loader(
272
-            'EventEspresso\core\services\request\Request'
273
-        );
274
-        $this->_set_cached_class(
275
-            $request_loader(),
276
-            'EventEspresso\core\services\request\Request'
277
-        );
278
-        $response_loader = $this->_dependency_map->class_loader(
279
-            'EventEspresso\core\services\request\Response'
280
-        );
281
-        $this->_set_cached_class(
282
-            $response_loader(),
283
-            'EventEspresso\core\services\request\Response'
284
-        );
285
-        add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
286
-    }
287
-
288
-
289
-    /**
290
-     * @return void
291
-     */
292
-    public function init()
293
-    {
294
-        // Get current page protocol
295
-        $protocol = is_ssl() ? 'https://' : 'http://';
296
-        // Output admin-ajax.php URL with same protocol as current page
297
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
298
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
299
-    }
300
-
301
-
302
-    /**
303
-     * @return array
304
-     */
305
-    public static function sanitize_i18n_js_strings(): array
306
-    {
307
-        $i18n_js_strings = (array) self::$i18n_js_strings;
308
-        foreach ($i18n_js_strings as $key => $value) {
309
-            if (is_scalar($value)) {
310
-                $i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
-            }
312
-        }
313
-        return $i18n_js_strings;
314
-    }
315
-
316
-
317
-    /**
318
-     * localize_i18n_js_strings
319
-     *
320
-     * @return string
321
-     */
322
-    public static function localize_i18n_js_strings(): string
323
-    {
324
-        $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
325
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
326
-    }
327
-
328
-
329
-    /**
330
-     * @param mixed string | EED_Module $module
331
-     * @throws OutOfBoundsException
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidInterfaceException
334
-     * @throws InvalidDataTypeException
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    public function add_module($module)
339
-    {
340
-        if ($module instanceof EED_Module) {
341
-            $module_class = get_class($module);
342
-            $this->modules->add($module_class, $module);
343
-        } else {
344
-            if (! class_exists('EE_Module_Request_Router', false)) {
345
-                $this->load_core('Module_Request_Router');
346
-            }
347
-            EE_Module_Request_Router::module_factory($module);
348
-        }
349
-    }
350
-
351
-
352
-    /**
353
-     * @param string $module_name
354
-     * @return mixed EED_Module | NULL
355
-     */
356
-    public function get_module(string $module_name = '')
357
-    {
358
-        return $this->modules->get($module_name);
359
-    }
360
-
361
-
362
-    /**
363
-     * loads core classes - must be singletons
364
-     *
365
-     * @param string $class_name - simple class name ie: session
366
-     * @param mixed  $arguments
367
-     * @param bool   $load_only
368
-     * @return bool|null|object
369
-     * @throws InvalidInterfaceException
370
-     * @throws InvalidDataTypeException
371
-     * @throws EE_Error
372
-     * @throws ReflectionException
373
-     * @throws InvalidArgumentException
374
-     */
375
-    public function load_core(string $class_name, $arguments = [], bool $load_only = false)
376
-    {
377
-        $core_paths = (array) apply_filters(
378
-            'FHEE__EE_Registry__load_core__core_paths',
379
-            [
380
-                EE_CORE,
381
-                EE_ADMIN,
382
-                EE_CPTS,
383
-                EE_CORE . 'CPTs/',
384
-                EE_CORE . 'data_migration_scripts/',
385
-                EE_CORE . 'request_stack/',
386
-                EE_CORE . 'middleware/',
387
-            ]
388
-        );
389
-        // retrieve instantiated class
390
-        return $this->_load(
391
-            $core_paths,
392
-            'EE_',
393
-            $class_name,
394
-            'core',
395
-            $arguments,
396
-            false,
397
-            true,
398
-            $load_only
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * loads service classes
405
-     *
406
-     * @param string $class_name - simple class name ie: session
407
-     * @param mixed  $arguments
408
-     * @param bool   $load_only
409
-     * @return bool|null|object
410
-     * @throws InvalidInterfaceException
411
-     * @throws InvalidDataTypeException
412
-     * @throws EE_Error
413
-     * @throws ReflectionException
414
-     * @throws InvalidArgumentException
415
-     * @deprecated  4.10.33.p
416
-     */
417
-    public function load_service(string $class_name, $arguments = [], bool $load_only = false)
418
-    {
419
-        $service_paths = (array) apply_filters(
420
-            'FHEE__EE_Registry__load_service__service_paths',
421
-            [
422
-                EE_CORE . 'services/',
423
-            ]
424
-        );
425
-        // retrieve instantiated class
426
-        return $this->_load(
427
-            $service_paths,
428
-            'EE_',
429
-            $class_name,
430
-            'class',
431
-            $arguments,
432
-            false,
433
-            true,
434
-            $load_only
435
-        );
436
-    }
437
-
438
-
439
-    /**
440
-     * loads data_migration_scripts
441
-     *
442
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
443
-     * @param mixed  $arguments
444
-     * @return bool|null|object
445
-     * @throws InvalidInterfaceException
446
-     * @throws InvalidDataTypeException
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     * @throws InvalidArgumentException
450
-     */
451
-    public function load_dms(string $class_name, $arguments = [])
452
-    {
453
-        // retrieve instantiated class
454
-        return $this->_load(
455
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
456
-            'EE_DMS_',
457
-            $class_name,
458
-            'dms',
459
-            $arguments,
460
-            false,
461
-            false
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * loads object creating classes - must be singletons
468
-     *
469
-     * @param string $class_name - simple class name ie: attendee
470
-     * @param mixed  $arguments  - an array of arguments to pass to the class
471
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
472
-     *                           instantiate
473
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
474
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
475
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
476
-     *                           (default)
477
-     * @return bool|null|object
478
-     * @throws InvalidInterfaceException
479
-     * @throws InvalidDataTypeException
480
-     * @throws EE_Error
481
-     * @throws ReflectionException
482
-     * @throws InvalidArgumentException
483
-     */
484
-    public function load_class(
485
-        string $class_name,
486
-        $arguments = [],
487
-        bool $from_db = false,
488
-        bool $cache = true,
489
-        bool $load_only = false
490
-    ) {
491
-        $paths = (array) apply_filters(
492
-            'FHEE__EE_Registry__load_class__paths',
493
-            [
494
-                EE_CORE,
495
-                EE_CLASSES,
496
-                EE_BUSINESS,
497
-            ]
498
-        );
499
-        // retrieve instantiated class
500
-        return $this->_load(
501
-            $paths,
502
-            'EE_',
503
-            $class_name,
504
-            'class',
505
-            $arguments,
506
-            $from_db,
507
-            $cache,
508
-            $load_only
509
-        );
510
-    }
511
-
512
-
513
-    /**
514
-     * loads helper classes - must be singletons
515
-     *
516
-     * @param string $class_name - simple class name ie: price
517
-     * @param mixed  $arguments
518
-     * @param bool   $load_only
519
-     * @return bool|null|object
520
-     * @throws InvalidInterfaceException
521
-     * @throws InvalidDataTypeException
522
-     * @throws EE_Error
523
-     * @throws ReflectionException
524
-     * @throws InvalidArgumentException
525
-     */
526
-    public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
527
-    {
528
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
529
-        $helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
530
-        // retrieve instantiated class
531
-        return $this->_load(
532
-            $helper_paths,
533
-            'EEH_',
534
-            $class_name,
535
-            'helper',
536
-            $arguments,
537
-            false,
538
-            true,
539
-            $load_only
540
-        );
541
-    }
542
-
543
-
544
-    /**
545
-     * loads core classes - must be singletons
546
-     *
547
-     * @param string $class_name - simple class name ie: session
548
-     * @param mixed  $arguments
549
-     * @param bool   $load_only
550
-     * @param bool   $cache      whether to cache the object or not.
551
-     * @return bool|null|object
552
-     * @throws InvalidInterfaceException
553
-     * @throws InvalidDataTypeException
554
-     * @throws EE_Error
555
-     * @throws ReflectionException
556
-     * @throws InvalidArgumentException
557
-     */
558
-    public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
559
-    {
560
-        $paths = [
561
-            EE_LIBRARIES,
562
-            EE_LIBRARIES . 'messages/',
563
-            EE_LIBRARIES . 'shortcodes/',
564
-            EE_LIBRARIES . 'qtips/',
565
-            EE_LIBRARIES . 'payment_methods/',
566
-        ];
567
-        // retrieve instantiated class
568
-        return $this->_load(
569
-            $paths,
570
-            'EE_',
571
-            $class_name,
572
-            'lib',
573
-            $arguments,
574
-            false,
575
-            $cache,
576
-            $load_only
577
-        );
578
-    }
579
-
580
-
581
-    /**
582
-     * loads model classes - must be singletons
583
-     *
584
-     * @param string $class_name - simple class name ie: price
585
-     * @param mixed  $arguments
586
-     * @param bool   $load_only
587
-     * @return bool|null|object
588
-     * @throws InvalidInterfaceException
589
-     * @throws InvalidDataTypeException
590
-     * @throws EE_Error
591
-     * @throws ReflectionException
592
-     * @throws InvalidArgumentException
593
-     */
594
-    public function load_model(string $class_name, $arguments = [], bool $load_only = false)
595
-    {
596
-        $paths = (array) apply_filters(
597
-            'FHEE__EE_Registry__load_model__paths',
598
-            [
599
-                EE_MODELS,
600
-                EE_CORE,
601
-            ]
602
-        );
603
-        // retrieve instantiated class
604
-        return $this->_load(
605
-            $paths,
606
-            'EEM_',
607
-            $class_name,
608
-            'model',
609
-            $arguments,
610
-            false,
611
-            true,
612
-            $load_only
613
-        );
614
-    }
615
-
616
-
617
-    /**
618
-     * loads model classes - must be singletons
619
-     *
620
-     * @param string $class_name - simple class name ie: price
621
-     * @param mixed  $arguments
622
-     * @param bool   $load_only
623
-     * @return bool|null|object
624
-     * @throws InvalidInterfaceException
625
-     * @throws InvalidDataTypeException
626
-     * @throws EE_Error
627
-     * @throws ReflectionException
628
-     * @throws InvalidArgumentException
629
-     * @deprecated  4.10.33.p
630
-     */
631
-    public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
632
-    {
633
-        $paths = [
634
-            EE_MODELS . 'fields/',
635
-            EE_MODELS . 'helpers/',
636
-            EE_MODELS . 'relations/',
637
-            EE_MODELS . 'strategies/',
638
-        ];
639
-        // retrieve instantiated class
640
-        return $this->_load(
641
-            $paths,
642
-            'EE_',
643
-            $class_name,
644
-            '',
645
-            $arguments,
646
-            false,
647
-            true,
648
-            $load_only
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * Determines if $model_name is the name of an actual EE model.
655
-     *
656
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
657
-     * @return boolean
658
-     */
659
-    public function is_model_name(string $model_name): bool
660
-    {
661
-        return isset($this->models[ $model_name ]);
662
-    }
663
-
664
-
665
-    /**
666
-     * generic class loader
667
-     *
668
-     * @param string $path_to_file - directory path to file location, not including filename
669
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
670
-     * @param string $type         - file type - core? class? helper? model?
671
-     * @param mixed  $arguments
672
-     * @param bool   $load_only
673
-     * @return bool|null|object
674
-     * @throws InvalidInterfaceException
675
-     * @throws InvalidDataTypeException
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     * @throws InvalidArgumentException
679
-     */
680
-    public function load_file(
681
-        string $path_to_file,
682
-        string $file_name,
683
-        string $type = '',
684
-        $arguments = [],
685
-        bool $load_only = true
686
-    ) {
687
-        // retrieve instantiated class
688
-        return $this->_load(
689
-            (array) $path_to_file,
690
-            '',
691
-            $file_name,
692
-            $type,
693
-            $arguments,
694
-            false,
695
-            true,
696
-            $load_only
697
-        );
698
-    }
699
-
700
-
701
-    /**
702
-     * @param string $path_to_file - directory path to file location, not including filename
703
-     * @param string $class_name   - full class name  ie:  My_Class
704
-     * @param string $type         - file type - core? class? helper? model?
705
-     * @param mixed  $arguments
706
-     * @param bool   $load_only
707
-     * @return bool|null|object
708
-     * @throws InvalidInterfaceException
709
-     * @throws InvalidDataTypeException
710
-     * @throws EE_Error
711
-     * @throws ReflectionException
712
-     * @throws InvalidArgumentException
713
-     * @deprecated  4.10.33.p
714
-     */
715
-    public function load_addon(
716
-        string $path_to_file,
717
-        string $class_name,
718
-        string $type = 'class',
719
-        $arguments = [],
720
-        bool $load_only = false
721
-    ) {
722
-        // retrieve instantiated class
723
-        return $this->_load(
724
-            (array) $path_to_file,
725
-            'addon',
726
-            $class_name,
727
-            $type,
728
-            $arguments,
729
-            false,
730
-            true,
731
-            $load_only
732
-        );
733
-    }
734
-
735
-
736
-    /**
737
-     * instantiates, caches, and automatically resolves dependencies
738
-     * for classes that use a Fully Qualified Class Name.
739
-     * if the class is not capable of being loaded using PSR-4 autoloading,
740
-     * then you need to use one of the existing load_*() methods
741
-     * which can resolve the classname and filepath from the passed arguments
742
-     *
743
-     * @param string      $class_name Fully Qualified Class Name
744
-     * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
745
-     * @param bool        $cache      whether to cache the instantiated object for reuse
746
-     * @param bool        $from_db    some classes are instantiated from the db
747
-     *                                and thus call a different method to instantiate
748
-     * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
749
-     * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
750
-     * @return bool|null|mixed     null = failure to load or instantiate class object.
751
-     *                                object = class loaded and instantiated successfully.
752
-     *                                bool = fail or success when $load_only is true
753
-     * @throws InvalidInterfaceException
754
-     * @throws InvalidDataTypeException
755
-     * @throws EE_Error
756
-     * @throws ReflectionException
757
-     * @throws InvalidArgumentException
758
-     */
759
-    public function create(
760
-        string $class_name = '',
761
-        array $arguments = [],
762
-        bool $cache = false,
763
-        bool $from_db = false,
764
-        bool $load_only = false,
765
-        bool $addon = false
766
-    ) {
767
-        $class_name   = ltrim($class_name, '\\');
768
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
769
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
770
-        // if a non-FQCN was passed, then
771
-        // verifyClassExists() might return an object
772
-        // or it could return null if the class just could not be found anywhere
773
-        if ($class_exists instanceof $class_name || $class_exists === null) {
774
-            // either way, return the results
775
-            return $class_exists;
776
-        }
777
-        $class_name = $class_exists;
778
-        // if we're only loading the class and it already exists, then let's just return true immediately
779
-        if ($load_only) {
780
-            return true;
781
-        }
782
-        $addon = $addon ? 'addon' : '';
783
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
784
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
785
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
786
-        if ($this->_cache_on && $cache) {
787
-            // return object if it's already cached
788
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
789
-            if ($cached_class !== null) {
790
-                return $cached_class;
791
-            }
792
-        }                                                           // obtain the loader method from the dependency map
793
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
794
-        if ($loader instanceof Closure) {
795
-            $class_obj = $loader($arguments);
796
-        } else {
797
-            if ($loader && method_exists($this, $loader)) {
798
-                $class_obj = $this->{$loader}($class_name, $arguments);
799
-            } else {
800
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
801
-            }
802
-        }
803
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
804
-            // save it for later... kinda like gum  { : $
805
-            $this->_set_cached_class(
806
-                $class_obj,
807
-                $class_name,
808
-                $addon,
809
-                $from_db,
810
-                $arguments
811
-            );
812
-        }
813
-        $this->_cache_on = true;
814
-        return $class_obj;
815
-    }
816
-
817
-
818
-    /**
819
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
820
-     *
821
-     * @param string|mixed $class_name
822
-     * @param array        $arguments
823
-     * @param int          $attempt
824
-     * @return mixed
825
-     */
826
-    private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
827
-    {
828
-        if (is_object($class_name) || class_exists($class_name)) {
829
-            return $class_name;
830
-        }
831
-        switch ($attempt) {
832
-            case 1:
833
-                // if it's a FQCN then maybe the class is registered with a preceding \
834
-                $class_name = strpos($class_name, '\\') !== false
835
-                    ? '\\' . ltrim($class_name, '\\')
836
-                    : $class_name;
837
-                break;
838
-            case 2:
839
-                //
840
-                $loader = $this->_dependency_map->class_loader($class_name);
841
-                if ($loader && method_exists($this, $loader)) {
842
-                    return $this->{$loader}($class_name, $arguments);
843
-                }
844
-                break;
845
-            case 3:
846
-            default:
847
-                return null;
848
-        }
849
-        $attempt++;
850
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
851
-    }
852
-
853
-
854
-    /**
855
-     * instantiates, caches, and injects dependencies for classes
856
-     *
857
-     * @param array  $file_paths         an array of paths to folders to look in
858
-     * @param string $class_prefix       EE  or EEM or... ???
859
-     * @param string $class_name         $class name
860
-     * @param string $type               file type - core? class? helper? model?
861
-     * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
862
-     * @param bool   $from_db            some classes are instantiated from the db
863
-     *                                   and thus call a different method to instantiate
864
-     * @param bool   $cache              whether to cache the instantiated object for reuse
865
-     * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
866
-     * @return bool|null|object          null   = failure to load or instantiate class object.
867
-     *                                   object = class loaded and instantiated successfully.
868
-     *                                   bool   = fail or success when $load_only is true
869
-     * @throws EE_Error
870
-     * @throws ReflectionException
871
-     * @throws InvalidInterfaceException
872
-     * @throws InvalidDataTypeException
873
-     * @throws InvalidArgumentException
874
-     */
875
-    protected function _load(
876
-        array $file_paths = [],
877
-        string $class_prefix = 'EE_',
878
-        string $class_name = '',
879
-        string $type = 'class',
880
-        array $arguments = [],
881
-        bool $from_db = false,
882
-        bool $cache = true,
883
-        bool $load_only = false
884
-    ) {
885
-        $class_name = ltrim($class_name, '\\');
886
-        // strip php file extension
887
-        $class_name = str_replace('.php', '', trim($class_name));
888
-        // does the class have a prefix ?
889
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
890
-            // make sure $class_prefix is uppercase
891
-            $class_prefix = strtoupper(trim($class_prefix));
892
-            // add class prefix ONCE!!!
893
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
894
-        }
895
-        $class_name   = $this->class_cache->getFqnForAlias($class_name);
896
-        $class_exists = class_exists($class_name, false);
897
-        // if we're only loading the class and it already exists, then let's just return true immediately
898
-        if ($load_only && $class_exists) {
899
-            return true;
900
-        }
901
-        $arguments = is_array($arguments) ? $arguments : [$arguments];
902
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
903
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
904
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
905
-        if ($this->_cache_on && $cache && ! $load_only) {
906
-            // return object if it's already cached
907
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
908
-            if ($cached_class !== null) {
909
-                return $cached_class;
910
-            }
911
-        }
912
-        // if the class doesn't already exist.. then we need to try and find the file and load it
913
-        if (! $class_exists) {
914
-            // get full path to file
915
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
916
-            // load the file
917
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
918
-            // if we are only loading a file but NOT instantiating an object
919
-            // then return boolean for whether class was loaded or not
920
-            if ($load_only) {
921
-                return $loaded;
922
-            }
923
-            // if an object was expected but loading failed, then return nothing
924
-            if (! $loaded) {
925
-                return null;
926
-            }
927
-        }
928
-        // instantiate the requested object
929
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
930
-        if ($this->_cache_on && $cache) {
931
-            // save it for later... kinda like gum  { : $
932
-            $this->_set_cached_class(
933
-                $class_obj,
934
-                $class_name,
935
-                $class_prefix,
936
-                $from_db,
937
-                $arguments
938
-            );
939
-        }
940
-        $this->_cache_on = true;
941
-        return $class_obj;
942
-    }
943
-
944
-
945
-    /**
946
-     * @param string $class_name
947
-     * @param string $default have to specify something, but not anything that will conflict
948
-     * @return mixed|string
949
-     */
950
-    protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
951
-    {
952
-        return $this->_class_abbreviations[ $class_name ] ?? $default;
953
-    }
954
-
955
-
956
-    /**
957
-     * attempts to find a cached version of the requested class
958
-     * by looking in the following places:
959
-     *        $this->{$class_abbreviation}            ie:    $this->CART
960
-     *        $this->{$class_name}                        ie:    $this->Some_Class
961
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
962
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
963
-     *
964
-     * @param string $class_name
965
-     * @param string $class_prefix
966
-     * @param array  $arguments
967
-     * @return mixed
968
-     */
969
-    protected function _get_cached_class(
970
-        string $class_name,
971
-        string $class_prefix = '',
972
-        array $arguments = []
973
-    ) {
974
-        if ($class_name === 'EE_Registry') {
975
-            return $this;
976
-        }
977
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
978
-        // check if class has already been loaded, and return it if it has been
979
-        if (isset($this->{$class_abbreviation})) {
980
-            return $this->{$class_abbreviation};
981
-        }
982
-        $class_name = str_replace('\\', '_', $class_name);
983
-        if (isset($this->{$class_name})) {
984
-            return $this->{$class_name};
985
-        }
986
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
987
-            return $this->addons->get($class_name);
988
-        }
989
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
990
-        if ($this->LIB->has($object_identifier)) {
991
-            return $this->LIB->get($object_identifier);
992
-        }
993
-        foreach ($this->LIB as $key => $object) {
994
-            if (
995
-                // request does not contain new arguments and therefore no args identifier
996
-                ! $this->object_identifier->hasArguments($object_identifier)
997
-                // but previously cached class with args was found
998
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
999
-            ) {
1000
-                return $object;
1001
-            }
1002
-        }
1003
-        return null;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * removes a cached version of the requested class
1009
-     *
1010
-     * @param string  $class_name
1011
-     * @param boolean $addon
1012
-     * @param array   $arguments
1013
-     * @return boolean
1014
-     */
1015
-    public function clear_cached_class(
1016
-        string $class_name,
1017
-        bool $addon = false,
1018
-        array $arguments = []
1019
-    ): bool {
1020
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
1021
-        // check if class has already been loaded, and return it if it has been
1022
-        if (isset($this->{$class_abbreviation})) {
1023
-            $this->{$class_abbreviation} = null;
1024
-            return true;
1025
-        }
1026
-        $class_name = str_replace('\\', '_', $class_name);
1027
-        if (isset($this->{$class_name})) {
1028
-            $this->{$class_name} = null;
1029
-            return true;
1030
-        }
1031
-        if ($addon && $this->addons->has($class_name)) {
1032
-            $this->addons->remove($class_name);
1033
-            return true;
1034
-        }
1035
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1036
-        if ($this->LIB->has($class_name)) {
1037
-            $this->LIB->remove($class_name);
1038
-            return true;
1039
-        }
1040
-        return false;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * _set_cached_class
1046
-     * attempts to cache the instantiated class locally
1047
-     * in one of the following places, in the following order:
1048
-     *        $this->{class_abbreviation}   ie:    $this->CART
1049
-     *        $this->{$class_name}          ie:    $this->Some_Class
1050
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1051
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1052
-     *
1053
-     * @param object $class_obj
1054
-     * @param string $class_name
1055
-     * @param string $class_prefix
1056
-     * @param bool   $from_db
1057
-     * @param array  $arguments
1058
-     * @return void
1059
-     */
1060
-    protected function _set_cached_class(
1061
-        $class_obj,
1062
-        string $class_name,
1063
-        string $class_prefix = '',
1064
-        bool $from_db = false,
1065
-        array $arguments = []
1066
-    ) {
1067
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1068
-            return;
1069
-        }
1070
-        // return newly instantiated class
1071
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1072
-        if ($class_abbreviation) {
1073
-            $this->{$class_abbreviation} = $class_obj;
1074
-            return;
1075
-        }
1076
-        $class_name = str_replace('\\', '_', $class_name);
1077
-        if (property_exists($this, $class_name)) {
1078
-            $this->{$class_name} = $class_obj;
1079
-            return;
1080
-        }
1081
-        if ($class_prefix === 'addon') {
1082
-            $this->addons->add($class_name, $class_obj);
1083
-            return;
1084
-        }
1085
-        if (! $from_db) {
1086
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1087
-            $this->LIB->add($class_name, $class_obj);
1088
-        }
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * attempts to find a full valid filepath for the requested class.
1094
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1095
-     * then returns that path if the target file has been found and is readable
1096
-     *
1097
-     * @param string $class_name
1098
-     * @param string $type
1099
-     * @param array  $file_paths
1100
-     * @return string | bool
1101
-     */
1102
-    protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1103
-    {
1104
-        // make sure $file_paths is an array
1105
-        $file_paths = is_array($file_paths)
1106
-            ? $file_paths
1107
-            : [$file_paths];
1108
-        // cycle thru paths
1109
-        foreach ($file_paths as $key => $file_path) {
1110
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1111
-            $file_path = $file_path
1112
-                ? str_replace(['/', '\\'], '/', $file_path)
1113
-                : EE_CLASSES;
1114
-            // prep file type
1115
-            $type = ! empty($type)
1116
-                ? trim($type, '.') . '.'
1117
-                : '';
1118
-            // build full file path
1119
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1120
-            // does the file exist and can be read ?
1121
-            if (is_readable($file_paths[ $key ])) {
1122
-                return $file_paths[ $key ];
1123
-            }
1124
-        }
1125
-        return false;
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * basically just performs a require_once()
1131
-     * but with some error handling
1132
-     *
1133
-     * @param string $path
1134
-     * @param string $class_name
1135
-     * @param string $type
1136
-     * @param array  $file_paths
1137
-     * @return bool
1138
-     * @throws EE_Error
1139
-     * @throws ReflectionException
1140
-     */
1141
-    protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1142
-    {
1143
-        $this->resolve_legacy_class_parent($class_name);
1144
-        // don't give up! you gotta...
1145
-        try {
1146
-            // does the file exist and can it be read ?
1147
-            if (! $path) {
1148
-                // just in case the file has already been autoloaded,
1149
-                // but discrepancies in the naming schema are preventing it from
1150
-                // being loaded via one of the EE_Registry::load_*() methods,
1151
-                // then let's try one last hail mary before throwing an exception
1152
-                // and call class_exists() again, but with autoloading turned ON
1153
-                if (class_exists($class_name)) {
1154
-                    return true;
1155
-                }
1156
-                // so sorry, can't find the file
1157
-                throw new EE_Error(
1158
-                    sprintf(
1159
-                        esc_html__(
1160
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1161
-                            'event_espresso'
1162
-                        ),
1163
-                        trim($type, '.'),
1164
-                        $class_name,
1165
-                        '<br />' . implode(',<br />', $file_paths)
1166
-                    )
1167
-                );
1168
-            }
1169
-            // get the file
1170
-            require_once($path);
1171
-            // if the class isn't already declared somewhere
1172
-            if (class_exists($class_name, false) === false) {
1173
-                // so sorry, not a class
1174
-                throw new EE_Error(
1175
-                    sprintf(
1176
-                        esc_html__(
1177
-                            'The %s file %s does not appear to contain the %s Class.',
1178
-                            'event_espresso'
1179
-                        ),
1180
-                        $type,
1181
-                        $path,
1182
-                        $class_name
1183
-                    )
1184
-                );
1185
-            }
1186
-        } catch (EE_Error $e) {
1187
-            $e->get_error();
1188
-            return false;
1189
-        }
1190
-        return true;
1191
-    }
1192
-
1193
-
1194
-    /**
1195
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1196
-     * before their class declaration in order to ensure that the parent class was loaded.
1197
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1198
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1199
-     *
1200
-     * @param string $class_name
1201
-     */
1202
-    protected function resolve_legacy_class_parent(string $class_name = '')
1203
-    {
1204
-        try {
1205
-            $legacy_parent_class_map = [
1206
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1207
-            ];
1208
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1209
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1210
-            }
1211
-        } catch (Exception $exception) {
1212
-        }
1213
-    }
1214
-
1215
-
1216
-    /**
1217
-     * _create_object
1218
-     * Attempts to instantiate the requested class via any of the
1219
-     * commonly used instantiation methods employed throughout EE.
1220
-     * The priority for instantiation is as follows:
1221
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1222
-     *        - model objects via their 'new_instance_from_db' method
1223
-     *        - model objects via their 'new_instance' method
1224
-     *        - "singleton" classes" via their 'instance' method
1225
-     *    - standard instantiable classes via their __constructor
1226
-     * Prior to instantiation, if the classname exists in the dependency_map,
1227
-     * then the constructor for the requested class will be examined to determine
1228
-     * if any dependencies exist, and if they can be injected.
1229
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1230
-     *
1231
-     * @param string $class_name
1232
-     * @param array  $arguments
1233
-     * @param string $type
1234
-     * @param bool   $from_db
1235
-     * @return null|object|bool
1236
-     * @throws InvalidArgumentException
1237
-     * @throws InvalidInterfaceException
1238
-     * @throws EE_Error
1239
-     * @throws ReflectionException
1240
-     * @throws InvalidDataTypeException
1241
-     */
1242
-    protected function _create_object(
1243
-        string $class_name,
1244
-        array $arguments = [],
1245
-        string $type = '',
1246
-        bool $from_db = false
1247
-    ) {
1248
-        // create reflection
1249
-        $reflector = $this->mirror->getReflectionClass($class_name);
1250
-        // make sure arguments are an array
1251
-        $arguments = is_array($arguments)
1252
-            ? $arguments
1253
-            : [$arguments];
1254
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1255
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1256
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1257
-            ? $arguments
1258
-            : [$arguments];
1259
-        // attempt to inject dependencies ?
1260
-        if ($this->_dependency_map->has($class_name)) {
1261
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1262
-        }
1263
-        // instantiate the class if possible
1264
-        if ($reflector->isAbstract()) {
1265
-            // nothing to instantiate, loading file was enough
1266
-            // does not throw an exception so $instantiation_mode is unused
1267
-            // $instantiation_mode = "1) no constructor abstract class";
1268
-            return true;
1269
-        }
1270
-        if (
1271
-            empty($arguments)
1272
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1273
-            && $reflector->isInstantiable()
1274
-        ) {
1275
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1276
-            // $instantiation_mode = "2) no constructor but instantiable";
1277
-            return $reflector->newInstance();
1278
-        }
1279
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1280
-            // $instantiation_mode = "3) new_instance_from_db()";
1281
-            return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1282
-        }
1283
-        if (method_exists($class_name, 'new_instance')) {
1284
-            // $instantiation_mode = "4) new_instance()";
1285
-            return call_user_func_array([$class_name, 'new_instance'], $arguments);
1286
-        }
1287
-        if (method_exists($class_name, 'instance')) {
1288
-            // $instantiation_mode = "5) instance()";
1289
-            return call_user_func_array([$class_name, 'instance'], $arguments);
1290
-        }
1291
-        if ($reflector->isInstantiable()) {
1292
-            // $instantiation_mode = "6) constructor";
1293
-            return $reflector->newInstanceArgs($arguments);
1294
-        }
1295
-        // heh ? something's not right !
1296
-        throw new EE_Error(
1297
-            sprintf(
1298
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1299
-                $type,
1300
-                $class_name
1301
-            )
1302
-        );
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1308
-     * @param array $array
1309
-     * @return bool
1310
-     */
1311
-    protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1312
-    {
1313
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * _resolve_dependencies
1319
-     * examines the constructor for the requested class to determine
1320
-     * if any dependencies exist, and if they can be injected.
1321
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1322
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1323
-     * For example:
1324
-     *        if attempting to load a class "Foo" with the following constructor:
1325
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1326
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1327
-     *        but only IF they are NOT already present in the incoming arguments array,
1328
-     *        and the correct classes can be loaded
1329
-     *
1330
-     * @param ReflectionClass $reflector
1331
-     * @param string          $class_name
1332
-     * @param array           $arguments
1333
-     * @return array
1334
-     * @throws InvalidArgumentException
1335
-     * @throws InvalidDataTypeException
1336
-     * @throws InvalidInterfaceException
1337
-     * @throws ReflectionException
1338
-     */
1339
-    protected function _resolve_dependencies(
1340
-        ReflectionClass $reflector,
1341
-        string $class_name,
1342
-        array $arguments = []
1343
-    ): array {
1344
-        // let's examine the constructor
1345
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1346
-        // whu? huh? nothing?
1347
-        if (! $constructor) {
1348
-            return $arguments;
1349
-        }
1350
-        // get constructor parameters
1351
-        $params = $this->mirror->getParametersFromReflection($reflector);
1352
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1353
-        $argument_keys = array_keys($arguments);
1354
-        // now loop thru all of the constructors expected parameters
1355
-        foreach ($params as $index => $param) {
1356
-            try {
1357
-                // is this a dependency for a specific class ?
1358
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1359
-            } catch (ReflectionException $exception) {
1360
-                // uh-oh... most likely a legacy class that has not been autoloaded
1361
-                // let's try to derive the classname from what we have now
1362
-                // and hope that the property var name is close to the class name
1363
-                $param_class = $param->getName();
1364
-                $param_class = str_replace('_', ' ', $param_class);
1365
-                $param_class = ucwords($param_class);
1366
-                $param_class = str_replace(' ', '_', $param_class);
1367
-            }
1368
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1369
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1370
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1371
-                : $param_class;
1372
-            // param is not even a class
1373
-            if (
1374
-                ! empty($param_class)
1375
-                && ! class_exists($param_class, false)
1376
-                // and something already exists in the incoming arguments for this param
1377
-                && array_key_exists($index, $argument_keys)
1378
-                && isset($arguments[ $argument_keys[ $index ] ])
1379
-            ) {
1380
-                // so let's skip this argument and move on to the next
1381
-                continue;
1382
-            }
1383
-            // parameter is type hinted as a class
1384
-            if ($param_class !== null) {
1385
-                // parameter exists as an incoming argument, AND it's the correct class
1386
-                if (
1387
-                    array_key_exists($index, $argument_keys)
1388
-                    && isset($arguments[ $argument_keys[ $index ] ])
1389
-                    && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1390
-                ) {
1391
-                    // skip this argument and move on to the next
1392
-                    continue;
1393
-                }
1394
-                // parameter should be injected
1395
-                if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1396
-                    $arguments = $this->_resolve_dependency(
1397
-                        $class_name,
1398
-                        $param_class,
1399
-                        $arguments,
1400
-                        $index
1401
-                    );
1402
-                }
1403
-            }
1404
-            if (empty($arguments[ $index ])) {
1405
-                $default_value = $this->mirror->getParameterDefaultValue(
1406
-                    $param,
1407
-                    $class_name,
1408
-                    $index
1409
-                );
1410
-                // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1411
-                $arguments[ $index ] = $default_value === null
1412
-                                       && isset($arguments[ $index ])
1413
-                                       && is_array($arguments[ $index ])
1414
-                    ? $arguments[ $index ]
1415
-                    : $default_value;
1416
-            }
1417
-        }
1418
-        return $arguments;
1419
-    }
1420
-
1421
-
1422
-    /**
1423
-     * @param string $class_name
1424
-     * @param string $param_class
1425
-     * @param array  $arguments
1426
-     * @param mixed  $index
1427
-     * @return array
1428
-     * @throws InvalidArgumentException
1429
-     * @throws InvalidInterfaceException
1430
-     * @throws InvalidDataTypeException
1431
-     */
1432
-    protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1433
-    {
1434
-        $dependency = null;
1435
-        // should dependency be loaded from cache ?
1436
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1437
-            $class_name,
1438
-            $param_class
1439
-        );
1440
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1441
-        // we might have a dependency...
1442
-        // let's MAYBE try and find it in our cache if that's what's been requested
1443
-        $cached_class = $cache_on
1444
-            ? $this->_get_cached_class($param_class)
1445
-            : null;
1446
-        // and grab it if it exists
1447
-        if ($cached_class instanceof $param_class) {
1448
-            $dependency = $cached_class;
1449
-        } elseif ($param_class !== $class_name) {
1450
-            // obtain the loader method from the dependency map
1451
-            $loader = $this->_dependency_map->class_loader($param_class);
1452
-            // is loader a custom closure ?
1453
-            if ($loader instanceof Closure) {
1454
-                $dependency = $loader($arguments);
1455
-            } else {
1456
-                // set the cache on property for the recursive loading call
1457
-                $this->_cache_on = $cache_on;
1458
-                // if not, then let's try and load it via the registry
1459
-                if ($loader && method_exists($this, $loader)) {
1460
-                    $dependency = $this->{$loader}($param_class);
1461
-                } else {
1462
-                    $dependency = LoaderFactory::getLoader()->load(
1463
-                        $param_class,
1464
-                        [],
1465
-                        $cache_on
1466
-                    );
1467
-                }
1468
-            }
1469
-        }
1470
-        // did we successfully find the correct dependency ?
1471
-        if ($dependency instanceof $param_class) {
1472
-            // then let's inject it into the incoming array of arguments at the correct location
1473
-            $arguments[ $index ] = $dependency;
1474
-        }
1475
-        return $arguments;
1476
-    }
1477
-
1478
-
1479
-    /**
1480
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1481
-     *
1482
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1483
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1484
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1485
-     * @param array  $arguments
1486
-     * @return object
1487
-     */
1488
-    public static function factory(string $classname, array $arguments = [])
1489
-    {
1490
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1491
-        if ($loader instanceof Closure) {
1492
-            return $loader($arguments);
1493
-        }
1494
-        if (method_exists(self::instance(), $loader)) {
1495
-            return self::instance()->{$loader}($classname, $arguments);
1496
-        }
1497
-        return null;
1498
-    }
1499
-
1500
-
1501
-    /**
1502
-     * Gets the addon by its class name
1503
-     *
1504
-     * @param string $class_name
1505
-     * @return EE_Addon
1506
-     */
1507
-    public function getAddon(string $class_name): ?EE_Addon
1508
-    {
1509
-        $class_name = str_replace('\\', '_', $class_name);
1510
-        return $this->addons->{$class_name} ?? null;
1511
-    }
1512
-
1513
-
1514
-    /**
1515
-     * removes the addon from the internal cache
1516
-     *
1517
-     * @param string $class_name
1518
-     * @return void
1519
-     */
1520
-    public function removeAddon(string $class_name)
1521
-    {
1522
-        $class_name = str_replace('\\', '_', $class_name);
1523
-        $this->addons->remove($class_name);
1524
-    }
1525
-
1526
-
1527
-    /**
1528
-     * Gets the addon by its name/slug (not classname. For that, just
1529
-     * use the get_addon() method above
1530
-     *
1531
-     * @param string $name
1532
-     * @return EE_Addon
1533
-     */
1534
-    public function get_addon_by_name(string $name): ?EE_Addon
1535
-    {
1536
-        foreach ($this->addons as $addon) {
1537
-            if ($addon->name() === $name) {
1538
-                return $addon;
1539
-            }
1540
-        }
1541
-        return null;
1542
-    }
1543
-
1544
-
1545
-    /**
1546
-     * Gets an array of all the registered addons, where the keys are their names.
1547
-     * (ie, what each returns for their name() function)
1548
-     * They're already available on EE_Registry::instance()->addons as properties,
1549
-     * where each property's name is the addon's classname,
1550
-     * So if you just want to get the addon by classname,
1551
-     * OR use the get_addon() method above.
1552
-     * PLEASE  NOTE:
1553
-     * addons with Fully Qualified Class Names
1554
-     * have had the namespace separators converted to underscores,
1555
-     * so a classname like Fully\Qualified\ClassName
1556
-     * would have been converted to Fully_Qualified_ClassName
1557
-     *
1558
-     * @return EE_Addon[] where the KEYS are the addon's name()
1559
-     */
1560
-    public function get_addons_by_name(): array
1561
-    {
1562
-        $addons = [];
1563
-        foreach ($this->addons as $addon) {
1564
-            $addons[ $addon->name() ] = $addon;
1565
-        }
1566
-        return $addons;
1567
-    }
1568
-
1569
-
1570
-    /**
1571
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1572
-     * a stale copy of it around
1573
-     *
1574
-     * @param string $model_name
1575
-     * @return EEM_Base
1576
-     * @throws EE_Error
1577
-     * @throws ReflectionException
1578
-     */
1579
-    public function reset_model(string $model_name): ?EEM_Base
1580
-    {
1581
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1582
-            ? "EEM_$model_name"
1583
-            : $model_name;
1584
-        if (! $this->LIB->has($model_class_name)) {
1585
-            return null;
1586
-        }
1587
-        $model = $this->LIB->get($model_class_name);
1588
-        if (! $model instanceof EEM_Base) {
1589
-            return null;
1590
-        }
1591
-        // get that model reset it and make sure we nuke the old reference to it
1592
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1593
-            $this->LIB->remove($model_class_name);
1594
-            $this->LIB->add($model_class_name, $model->reset());
1595
-        } else {
1596
-            throw new EE_Error(
1597
-                sprintf(
1598
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1599
-                    $model_name
1600
-                )
1601
-            );
1602
-        }
1603
-        return $model;
1604
-    }
1605
-
1606
-
1607
-    /**
1608
-     * Resets the registry.
1609
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1610
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1611
-     * - $_dependency_map
1612
-     * - $_class_abbreviations
1613
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1614
-     * - $REQ:  Still on the same request so no need to change.
1615
-     * - $CAP: There is no site specific state in the EE_Capability class.
1616
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1617
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1618
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1619
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1620
-     *             switch or on the restore.
1621
-     * - $modules
1622
-     * - $shortcodes
1623
-     * - $widgets
1624
-     *
1625
-     * @param boolean $hard             [deprecated]
1626
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1627
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1628
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1629
-     * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1630
-     *                                  client
1631
-     *                                  code instead can just change the model context to a different blog id if
1632
-     *                                  necessary
1633
-     * @return EE_Registry
1634
-     * @throws EE_Error
1635
-     * @throws ReflectionException
1636
-     */
1637
-    public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1638
-    {
1639
-        $instance            = self::instance();
1640
-        $instance->_cache_on = true;
1641
-        // reset some "special" classes
1642
-        EEH_Activation::reset();
1643
-        $hard                     = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1644
-        $instance->CFG            = EE_Config::reset($hard, $reinstantiate);
1645
-        $instance->CART           = null;
1646
-        $instance->MRM            = null;
1647
-        $instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1648
-            'EventEspresso\core\services\assets\Registry'
1649
-        );
1650
-        // messages reset
1651
-        EED_Messages::reset();
1652
-        // handle of objects cached on LIB
1653
-        foreach (['LIB', 'modules'] as $cache) {
1654
-            foreach ($instance->{$cache} as $class_name => $class) {
1655
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1656
-                    unset($instance->{$cache}->{$class_name});
1657
-                }
1658
-            }
1659
-        }
1660
-        return $instance;
1661
-    }
1662
-
1663
-
1664
-    /**
1665
-     * if passed object implements ResettableInterface, then call it's reset() method
1666
-     * if passed object implements InterminableInterface, then return false,
1667
-     * to indicate that it should NOT be cleared from the Registry cache
1668
-     *
1669
-     * @param      $object
1670
-     * @param bool $reset_models
1671
-     * @return bool returns true if cached object should be unset
1672
-     * @throws EE_Error
1673
-     * @throws ReflectionException
1674
-     */
1675
-    private static function _reset_and_unset_object($object, bool $reset_models): bool
1676
-    {
1677
-        if (! is_object($object)) {
1678
-            // don't unset anything that's not an object
1679
-            return false;
1680
-        }
1681
-        if ($object instanceof EED_Module) {
1682
-            $object::reset();
1683
-            // don't unset modules
1684
-            return false;
1685
-        }
1686
-        if ($object instanceof ResettableInterface) {
1687
-            if ($object instanceof EEM_Base) {
1688
-                if ($reset_models) {
1689
-                    $object->reset();
1690
-                    return true;
1691
-                }
1692
-                return false;
1693
-            }
1694
-            $object->reset();
1695
-            return true;
1696
-        }
1697
-        if (! $object instanceof InterminableInterface) {
1698
-            return true;
1699
-        }
1700
-        return false;
1701
-    }
1702
-
1703
-
1704
-    /**
1705
-     * Gets all the custom post type models defined
1706
-     *
1707
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1708
-     */
1709
-    public function cpt_models(): array
1710
-    {
1711
-        $cpt_models = [];
1712
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1713
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1714
-                $cpt_models[ $short_name ] = $classname;
1715
-            }
1716
-        }
1717
-        return $cpt_models;
1718
-    }
1719
-
1720
-
1721
-    /**
1722
-     * @return EE_Config
1723
-     */
1724
-    public static function CFG(): EE_Config
1725
-    {
1726
-        return self::instance()->CFG;
1727
-    }
1728
-
1729
-
1730
-    /**
1731
-     * @param string $class_name
1732
-     * @return ReflectionClass
1733
-     * @throws ReflectionException
1734
-     * @throws InvalidDataTypeException
1735
-     * @deprecated 4.9.62.p
1736
-     */
1737
-    public function get_ReflectionClass(string $class_name): ReflectionClass
1738
-    {
1739
-        return $this->mirror->getReflectionClass($class_name);
1740
-    }
25
+	/**
26
+	 * @var EE_Registry $_instance
27
+	 */
28
+	private static $_instance;
29
+
30
+	/**
31
+	 * @var EE_Dependency_Map $_dependency_map
32
+	 */
33
+	protected $_dependency_map;
34
+
35
+	/**
36
+	 * @var Mirror
37
+	 */
38
+	private $mirror;
39
+
40
+	/**
41
+	 * @var ClassInterfaceCache $class_cache
42
+	 */
43
+	private $class_cache;
44
+
45
+	/**
46
+	 * @var array $_class_abbreviations
47
+	 */
48
+	protected $_class_abbreviations = [];
49
+
50
+	/**
51
+	 * @var CommandBusInterface $BUS
52
+	 */
53
+	public $BUS;
54
+
55
+	/**
56
+	 * @var EE_Cart $CART
57
+	 */
58
+	public $CART;
59
+
60
+	/**
61
+	 * @var EE_Config $CFG
62
+	 */
63
+	public $CFG;
64
+
65
+	/**
66
+	 * @var EE_Network_Config $NET_CFG
67
+	 */
68
+	public $NET_CFG;
69
+
70
+	/**
71
+	 * RegistryContainer for storing library classes in
72
+	 *
73
+	 * @var RegistryContainer $LIB
74
+	 */
75
+	public $LIB;
76
+
77
+	/**
78
+	 * @var EE_Request_Handler $REQ
79
+	 * @deprecated 4.10.14.p
80
+	 */
81
+	public $REQ;
82
+
83
+	/**
84
+	 * @var EE_Session $SSN
85
+	 */
86
+	public $SSN;
87
+
88
+	/**
89
+	 * @since 4.5.0
90
+	 * @var EE_Capabilities $CAP
91
+	 */
92
+	public $CAP;
93
+
94
+	/**
95
+	 * @since 4.9.0
96
+	 * @var EE_Message_Resource_Manager $MRM
97
+	 */
98
+	public $MRM;
99
+
100
+	/**
101
+	 * @var Registry $AssetsRegistry
102
+	 */
103
+	public $AssetsRegistry;
104
+
105
+	/**
106
+	 * RegistryContainer for holding addons which have registered themselves to work with EE core
107
+	 *
108
+	 * @var RegistryContainer|EE_Addon[] $addons
109
+	 */
110
+	public $addons;
111
+
112
+	/**
113
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
+	 *
115
+	 * @var EEM_Base[] $models
116
+	 */
117
+	public $models = [];
118
+
119
+	/**
120
+	 * @var RegistryContainer|EED_Module[] $modules
121
+	 */
122
+	public $modules;
123
+
124
+	/**
125
+	 * @var RegistryContainer|EES_Shortcode[] $shortcodes
126
+	 */
127
+	public $shortcodes;
128
+
129
+	/**
130
+	 * @var RegistryContainer|WP_Widget[] $widgets
131
+	 */
132
+	public $widgets;
133
+
134
+	/**
135
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
+	 * classnames (eg "EEM_Event")
139
+	 *
140
+	 * @var array $non_abstract_db_models
141
+	 */
142
+	public $non_abstract_db_models = [];
143
+
144
+	/**
145
+	 * internationalization for JS strings
146
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
+	 *    in js file:  var translatedString = eei18n.string_key;
148
+	 *
149
+	 * @var array $i18n_js_strings
150
+	 */
151
+	public static $i18n_js_strings = [];
152
+
153
+	/**
154
+	 * $main_file - path to espresso.php
155
+	 *
156
+	 * @var array $main_file
157
+	 */
158
+	public $main_file;
159
+
160
+	/**
161
+	 * array of ReflectionClass objects where the key is the class name
162
+	 *
163
+	 * @deprecated 4.9.62.p
164
+	 * @var ReflectionClass[] $_reflectors
165
+	 */
166
+	public $_reflectors;
167
+
168
+	/**
169
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
+	 *
171
+	 * @var boolean $_cache_on
172
+	 */
173
+	protected $_cache_on = true;
174
+
175
+	/**
176
+	 * @var ObjectIdentifier
177
+	 */
178
+	private $object_identifier;
179
+
180
+
181
+	/**
182
+	 * @singleton method used to instantiate class object
183
+	 * @param EE_Dependency_Map|null   $dependency_map
184
+	 * @param Mirror|null              $mirror
185
+	 * @param ClassInterfaceCache|null $class_cache
186
+	 * @param ObjectIdentifier|null    $object_identifier
187
+	 * @return EE_Registry instance
188
+	 */
189
+	public static function instance(
190
+		EE_Dependency_Map $dependency_map = null,
191
+		Mirror $mirror = null,
192
+		ClassInterfaceCache $class_cache = null,
193
+		ObjectIdentifier $object_identifier = null
194
+	): EE_Registry {
195
+		// check if class object is instantiated
196
+		if (
197
+			! self::$_instance instanceof EE_Registry
198
+			&& $dependency_map instanceof EE_Dependency_Map
199
+			&& $mirror instanceof Mirror
200
+			&& $class_cache instanceof ClassInterfaceCache
201
+			&& $object_identifier instanceof ObjectIdentifier
202
+		) {
203
+			self::$_instance = new self(
204
+				$dependency_map,
205
+				$mirror,
206
+				$class_cache,
207
+				$object_identifier
208
+			);
209
+		}
210
+		return self::$_instance;
211
+	}
212
+
213
+
214
+	/**
215
+	 * protected constructor to prevent direct creation
216
+	 *
217
+	 * @Constructor
218
+	 * @param EE_Dependency_Map   $dependency_map
219
+	 * @param Mirror              $mirror
220
+	 * @param ClassInterfaceCache $class_cache
221
+	 * @param ObjectIdentifier    $object_identifier
222
+	 */
223
+	protected function __construct(
224
+		EE_Dependency_Map $dependency_map,
225
+		Mirror $mirror,
226
+		ClassInterfaceCache $class_cache,
227
+		ObjectIdentifier $object_identifier
228
+	) {
229
+		$this->_dependency_map   = $dependency_map;
230
+		$this->mirror            = $mirror;
231
+		$this->class_cache       = $class_cache;
232
+		$this->object_identifier = $object_identifier;
233
+		// $registry_container = new RegistryContainer();
234
+		$this->LIB        = new RegistryContainer();
235
+		$this->addons     = new RegistryContainer();
236
+		$this->modules    = new RegistryContainer();
237
+		$this->shortcodes = new RegistryContainer();
238
+		$this->widgets    = new RegistryContainer();
239
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', [$this, 'initialize']);
240
+	}
241
+
242
+
243
+	/**
244
+	 * initialize
245
+	 *
246
+	 * @throws OutOfBoundsException
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidInterfaceException
249
+	 * @throws InvalidDataTypeException
250
+	 * @throws EE_Error
251
+	 * @throws ReflectionException
252
+	 */
253
+	public function initialize()
254
+	{
255
+		$this->_class_abbreviations = apply_filters(
256
+			'FHEE__EE_Registry____construct___class_abbreviations',
257
+			[
258
+				'EE_Config'                                       => 'CFG',
259
+				'EE_Session'                                      => 'SSN',
260
+				'EE_Capabilities'                                 => 'CAP',
261
+				'EE_Cart'                                         => 'CART',
262
+				'EE_Network_Config'                               => 'NET_CFG',
263
+				'EE_Request_Handler'                              => 'REQ',
264
+				'EE_Message_Resource_Manager'                     => 'MRM',
265
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
266
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
267
+			]
268
+		);
269
+		$this->load_core('Base', [], true);
270
+		// add our request and response objects to the cache
271
+		$request_loader = $this->_dependency_map->class_loader(
272
+			'EventEspresso\core\services\request\Request'
273
+		);
274
+		$this->_set_cached_class(
275
+			$request_loader(),
276
+			'EventEspresso\core\services\request\Request'
277
+		);
278
+		$response_loader = $this->_dependency_map->class_loader(
279
+			'EventEspresso\core\services\request\Response'
280
+		);
281
+		$this->_set_cached_class(
282
+			$response_loader(),
283
+			'EventEspresso\core\services\request\Response'
284
+		);
285
+		add_action('AHEE__EE_System__set_hooks_for_core', [$this, 'init']);
286
+	}
287
+
288
+
289
+	/**
290
+	 * @return void
291
+	 */
292
+	public function init()
293
+	{
294
+		// Get current page protocol
295
+		$protocol = is_ssl() ? 'https://' : 'http://';
296
+		// Output admin-ajax.php URL with same protocol as current page
297
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
298
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
299
+	}
300
+
301
+
302
+	/**
303
+	 * @return array
304
+	 */
305
+	public static function sanitize_i18n_js_strings(): array
306
+	{
307
+		$i18n_js_strings = (array) self::$i18n_js_strings;
308
+		foreach ($i18n_js_strings as $key => $value) {
309
+			if (is_scalar($value)) {
310
+				$i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
+			}
312
+		}
313
+		return $i18n_js_strings;
314
+	}
315
+
316
+
317
+	/**
318
+	 * localize_i18n_js_strings
319
+	 *
320
+	 * @return string
321
+	 */
322
+	public static function localize_i18n_js_strings(): string
323
+	{
324
+		$i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
325
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
326
+	}
327
+
328
+
329
+	/**
330
+	 * @param mixed string | EED_Module $module
331
+	 * @throws OutOfBoundsException
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidInterfaceException
334
+	 * @throws InvalidDataTypeException
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	public function add_module($module)
339
+	{
340
+		if ($module instanceof EED_Module) {
341
+			$module_class = get_class($module);
342
+			$this->modules->add($module_class, $module);
343
+		} else {
344
+			if (! class_exists('EE_Module_Request_Router', false)) {
345
+				$this->load_core('Module_Request_Router');
346
+			}
347
+			EE_Module_Request_Router::module_factory($module);
348
+		}
349
+	}
350
+
351
+
352
+	/**
353
+	 * @param string $module_name
354
+	 * @return mixed EED_Module | NULL
355
+	 */
356
+	public function get_module(string $module_name = '')
357
+	{
358
+		return $this->modules->get($module_name);
359
+	}
360
+
361
+
362
+	/**
363
+	 * loads core classes - must be singletons
364
+	 *
365
+	 * @param string $class_name - simple class name ie: session
366
+	 * @param mixed  $arguments
367
+	 * @param bool   $load_only
368
+	 * @return bool|null|object
369
+	 * @throws InvalidInterfaceException
370
+	 * @throws InvalidDataTypeException
371
+	 * @throws EE_Error
372
+	 * @throws ReflectionException
373
+	 * @throws InvalidArgumentException
374
+	 */
375
+	public function load_core(string $class_name, $arguments = [], bool $load_only = false)
376
+	{
377
+		$core_paths = (array) apply_filters(
378
+			'FHEE__EE_Registry__load_core__core_paths',
379
+			[
380
+				EE_CORE,
381
+				EE_ADMIN,
382
+				EE_CPTS,
383
+				EE_CORE . 'CPTs/',
384
+				EE_CORE . 'data_migration_scripts/',
385
+				EE_CORE . 'request_stack/',
386
+				EE_CORE . 'middleware/',
387
+			]
388
+		);
389
+		// retrieve instantiated class
390
+		return $this->_load(
391
+			$core_paths,
392
+			'EE_',
393
+			$class_name,
394
+			'core',
395
+			$arguments,
396
+			false,
397
+			true,
398
+			$load_only
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * loads service classes
405
+	 *
406
+	 * @param string $class_name - simple class name ie: session
407
+	 * @param mixed  $arguments
408
+	 * @param bool   $load_only
409
+	 * @return bool|null|object
410
+	 * @throws InvalidInterfaceException
411
+	 * @throws InvalidDataTypeException
412
+	 * @throws EE_Error
413
+	 * @throws ReflectionException
414
+	 * @throws InvalidArgumentException
415
+	 * @deprecated  4.10.33.p
416
+	 */
417
+	public function load_service(string $class_name, $arguments = [], bool $load_only = false)
418
+	{
419
+		$service_paths = (array) apply_filters(
420
+			'FHEE__EE_Registry__load_service__service_paths',
421
+			[
422
+				EE_CORE . 'services/',
423
+			]
424
+		);
425
+		// retrieve instantiated class
426
+		return $this->_load(
427
+			$service_paths,
428
+			'EE_',
429
+			$class_name,
430
+			'class',
431
+			$arguments,
432
+			false,
433
+			true,
434
+			$load_only
435
+		);
436
+	}
437
+
438
+
439
+	/**
440
+	 * loads data_migration_scripts
441
+	 *
442
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
443
+	 * @param mixed  $arguments
444
+	 * @return bool|null|object
445
+	 * @throws InvalidInterfaceException
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 * @throws InvalidArgumentException
450
+	 */
451
+	public function load_dms(string $class_name, $arguments = [])
452
+	{
453
+		// retrieve instantiated class
454
+		return $this->_load(
455
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
456
+			'EE_DMS_',
457
+			$class_name,
458
+			'dms',
459
+			$arguments,
460
+			false,
461
+			false
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * loads object creating classes - must be singletons
468
+	 *
469
+	 * @param string $class_name - simple class name ie: attendee
470
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
471
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
472
+	 *                           instantiate
473
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
474
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
475
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
476
+	 *                           (default)
477
+	 * @return bool|null|object
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws EE_Error
481
+	 * @throws ReflectionException
482
+	 * @throws InvalidArgumentException
483
+	 */
484
+	public function load_class(
485
+		string $class_name,
486
+		$arguments = [],
487
+		bool $from_db = false,
488
+		bool $cache = true,
489
+		bool $load_only = false
490
+	) {
491
+		$paths = (array) apply_filters(
492
+			'FHEE__EE_Registry__load_class__paths',
493
+			[
494
+				EE_CORE,
495
+				EE_CLASSES,
496
+				EE_BUSINESS,
497
+			]
498
+		);
499
+		// retrieve instantiated class
500
+		return $this->_load(
501
+			$paths,
502
+			'EE_',
503
+			$class_name,
504
+			'class',
505
+			$arguments,
506
+			$from_db,
507
+			$cache,
508
+			$load_only
509
+		);
510
+	}
511
+
512
+
513
+	/**
514
+	 * loads helper classes - must be singletons
515
+	 *
516
+	 * @param string $class_name - simple class name ie: price
517
+	 * @param mixed  $arguments
518
+	 * @param bool   $load_only
519
+	 * @return bool|null|object
520
+	 * @throws InvalidInterfaceException
521
+	 * @throws InvalidDataTypeException
522
+	 * @throws EE_Error
523
+	 * @throws ReflectionException
524
+	 * @throws InvalidArgumentException
525
+	 */
526
+	public function load_helper(string $class_name, $arguments = [], bool $load_only = true)
527
+	{
528
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
529
+		$helper_paths = (array) apply_filters('FHEE__EE_Registry__load_helper__helper_paths', [EE_HELPERS]);
530
+		// retrieve instantiated class
531
+		return $this->_load(
532
+			$helper_paths,
533
+			'EEH_',
534
+			$class_name,
535
+			'helper',
536
+			$arguments,
537
+			false,
538
+			true,
539
+			$load_only
540
+		);
541
+	}
542
+
543
+
544
+	/**
545
+	 * loads core classes - must be singletons
546
+	 *
547
+	 * @param string $class_name - simple class name ie: session
548
+	 * @param mixed  $arguments
549
+	 * @param bool   $load_only
550
+	 * @param bool   $cache      whether to cache the object or not.
551
+	 * @return bool|null|object
552
+	 * @throws InvalidInterfaceException
553
+	 * @throws InvalidDataTypeException
554
+	 * @throws EE_Error
555
+	 * @throws ReflectionException
556
+	 * @throws InvalidArgumentException
557
+	 */
558
+	public function load_lib(string $class_name, $arguments = [], bool $load_only = false, bool $cache = true)
559
+	{
560
+		$paths = [
561
+			EE_LIBRARIES,
562
+			EE_LIBRARIES . 'messages/',
563
+			EE_LIBRARIES . 'shortcodes/',
564
+			EE_LIBRARIES . 'qtips/',
565
+			EE_LIBRARIES . 'payment_methods/',
566
+		];
567
+		// retrieve instantiated class
568
+		return $this->_load(
569
+			$paths,
570
+			'EE_',
571
+			$class_name,
572
+			'lib',
573
+			$arguments,
574
+			false,
575
+			$cache,
576
+			$load_only
577
+		);
578
+	}
579
+
580
+
581
+	/**
582
+	 * loads model classes - must be singletons
583
+	 *
584
+	 * @param string $class_name - simple class name ie: price
585
+	 * @param mixed  $arguments
586
+	 * @param bool   $load_only
587
+	 * @return bool|null|object
588
+	 * @throws InvalidInterfaceException
589
+	 * @throws InvalidDataTypeException
590
+	 * @throws EE_Error
591
+	 * @throws ReflectionException
592
+	 * @throws InvalidArgumentException
593
+	 */
594
+	public function load_model(string $class_name, $arguments = [], bool $load_only = false)
595
+	{
596
+		$paths = (array) apply_filters(
597
+			'FHEE__EE_Registry__load_model__paths',
598
+			[
599
+				EE_MODELS,
600
+				EE_CORE,
601
+			]
602
+		);
603
+		// retrieve instantiated class
604
+		return $this->_load(
605
+			$paths,
606
+			'EEM_',
607
+			$class_name,
608
+			'model',
609
+			$arguments,
610
+			false,
611
+			true,
612
+			$load_only
613
+		);
614
+	}
615
+
616
+
617
+	/**
618
+	 * loads model classes - must be singletons
619
+	 *
620
+	 * @param string $class_name - simple class name ie: price
621
+	 * @param mixed  $arguments
622
+	 * @param bool   $load_only
623
+	 * @return bool|null|object
624
+	 * @throws InvalidInterfaceException
625
+	 * @throws InvalidDataTypeException
626
+	 * @throws EE_Error
627
+	 * @throws ReflectionException
628
+	 * @throws InvalidArgumentException
629
+	 * @deprecated  4.10.33.p
630
+	 */
631
+	public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
632
+	{
633
+		$paths = [
634
+			EE_MODELS . 'fields/',
635
+			EE_MODELS . 'helpers/',
636
+			EE_MODELS . 'relations/',
637
+			EE_MODELS . 'strategies/',
638
+		];
639
+		// retrieve instantiated class
640
+		return $this->_load(
641
+			$paths,
642
+			'EE_',
643
+			$class_name,
644
+			'',
645
+			$arguments,
646
+			false,
647
+			true,
648
+			$load_only
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * Determines if $model_name is the name of an actual EE model.
655
+	 *
656
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
657
+	 * @return boolean
658
+	 */
659
+	public function is_model_name(string $model_name): bool
660
+	{
661
+		return isset($this->models[ $model_name ]);
662
+	}
663
+
664
+
665
+	/**
666
+	 * generic class loader
667
+	 *
668
+	 * @param string $path_to_file - directory path to file location, not including filename
669
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
670
+	 * @param string $type         - file type - core? class? helper? model?
671
+	 * @param mixed  $arguments
672
+	 * @param bool   $load_only
673
+	 * @return bool|null|object
674
+	 * @throws InvalidInterfaceException
675
+	 * @throws InvalidDataTypeException
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 * @throws InvalidArgumentException
679
+	 */
680
+	public function load_file(
681
+		string $path_to_file,
682
+		string $file_name,
683
+		string $type = '',
684
+		$arguments = [],
685
+		bool $load_only = true
686
+	) {
687
+		// retrieve instantiated class
688
+		return $this->_load(
689
+			(array) $path_to_file,
690
+			'',
691
+			$file_name,
692
+			$type,
693
+			$arguments,
694
+			false,
695
+			true,
696
+			$load_only
697
+		);
698
+	}
699
+
700
+
701
+	/**
702
+	 * @param string $path_to_file - directory path to file location, not including filename
703
+	 * @param string $class_name   - full class name  ie:  My_Class
704
+	 * @param string $type         - file type - core? class? helper? model?
705
+	 * @param mixed  $arguments
706
+	 * @param bool   $load_only
707
+	 * @return bool|null|object
708
+	 * @throws InvalidInterfaceException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws EE_Error
711
+	 * @throws ReflectionException
712
+	 * @throws InvalidArgumentException
713
+	 * @deprecated  4.10.33.p
714
+	 */
715
+	public function load_addon(
716
+		string $path_to_file,
717
+		string $class_name,
718
+		string $type = 'class',
719
+		$arguments = [],
720
+		bool $load_only = false
721
+	) {
722
+		// retrieve instantiated class
723
+		return $this->_load(
724
+			(array) $path_to_file,
725
+			'addon',
726
+			$class_name,
727
+			$type,
728
+			$arguments,
729
+			false,
730
+			true,
731
+			$load_only
732
+		);
733
+	}
734
+
735
+
736
+	/**
737
+	 * instantiates, caches, and automatically resolves dependencies
738
+	 * for classes that use a Fully Qualified Class Name.
739
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
740
+	 * then you need to use one of the existing load_*() methods
741
+	 * which can resolve the classname and filepath from the passed arguments
742
+	 *
743
+	 * @param string      $class_name Fully Qualified Class Name
744
+	 * @param array       $arguments  an argument, or array of arguments to pass to the class upon instantiation
745
+	 * @param bool        $cache      whether to cache the instantiated object for reuse
746
+	 * @param bool        $from_db    some classes are instantiated from the db
747
+	 *                                and thus call a different method to instantiate
748
+	 * @param bool        $load_only  if true, will only load the file, but will NOT instantiate an object
749
+	 * @param bool|string $addon      if true, will cache the object in the EE_Registry->$addons array
750
+	 * @return bool|null|mixed     null = failure to load or instantiate class object.
751
+	 *                                object = class loaded and instantiated successfully.
752
+	 *                                bool = fail or success when $load_only is true
753
+	 * @throws InvalidInterfaceException
754
+	 * @throws InvalidDataTypeException
755
+	 * @throws EE_Error
756
+	 * @throws ReflectionException
757
+	 * @throws InvalidArgumentException
758
+	 */
759
+	public function create(
760
+		string $class_name = '',
761
+		array $arguments = [],
762
+		bool $cache = false,
763
+		bool $from_db = false,
764
+		bool $load_only = false,
765
+		bool $addon = false
766
+	) {
767
+		$class_name   = ltrim($class_name, '\\');
768
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
769
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
770
+		// if a non-FQCN was passed, then
771
+		// verifyClassExists() might return an object
772
+		// or it could return null if the class just could not be found anywhere
773
+		if ($class_exists instanceof $class_name || $class_exists === null) {
774
+			// either way, return the results
775
+			return $class_exists;
776
+		}
777
+		$class_name = $class_exists;
778
+		// if we're only loading the class and it already exists, then let's just return true immediately
779
+		if ($load_only) {
780
+			return true;
781
+		}
782
+		$addon = $addon ? 'addon' : '';
783
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
784
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
785
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
786
+		if ($this->_cache_on && $cache) {
787
+			// return object if it's already cached
788
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
789
+			if ($cached_class !== null) {
790
+				return $cached_class;
791
+			}
792
+		}                                                           // obtain the loader method from the dependency map
793
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
794
+		if ($loader instanceof Closure) {
795
+			$class_obj = $loader($arguments);
796
+		} else {
797
+			if ($loader && method_exists($this, $loader)) {
798
+				$class_obj = $this->{$loader}($class_name, $arguments);
799
+			} else {
800
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
801
+			}
802
+		}
803
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
804
+			// save it for later... kinda like gum  { : $
805
+			$this->_set_cached_class(
806
+				$class_obj,
807
+				$class_name,
808
+				$addon,
809
+				$from_db,
810
+				$arguments
811
+			);
812
+		}
813
+		$this->_cache_on = true;
814
+		return $class_obj;
815
+	}
816
+
817
+
818
+	/**
819
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
820
+	 *
821
+	 * @param string|mixed $class_name
822
+	 * @param array        $arguments
823
+	 * @param int          $attempt
824
+	 * @return mixed
825
+	 */
826
+	private function loadOrVerifyClassExists($class_name, array $arguments, int $attempt = 1)
827
+	{
828
+		if (is_object($class_name) || class_exists($class_name)) {
829
+			return $class_name;
830
+		}
831
+		switch ($attempt) {
832
+			case 1:
833
+				// if it's a FQCN then maybe the class is registered with a preceding \
834
+				$class_name = strpos($class_name, '\\') !== false
835
+					? '\\' . ltrim($class_name, '\\')
836
+					: $class_name;
837
+				break;
838
+			case 2:
839
+				//
840
+				$loader = $this->_dependency_map->class_loader($class_name);
841
+				if ($loader && method_exists($this, $loader)) {
842
+					return $this->{$loader}($class_name, $arguments);
843
+				}
844
+				break;
845
+			case 3:
846
+			default:
847
+				return null;
848
+		}
849
+		$attempt++;
850
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
851
+	}
852
+
853
+
854
+	/**
855
+	 * instantiates, caches, and injects dependencies for classes
856
+	 *
857
+	 * @param array  $file_paths         an array of paths to folders to look in
858
+	 * @param string $class_prefix       EE  or EEM or... ???
859
+	 * @param string $class_name         $class name
860
+	 * @param string $type               file type - core? class? helper? model?
861
+	 * @param mixed  $arguments          an argument or array of arguments to pass to the class upon instantiation
862
+	 * @param bool   $from_db            some classes are instantiated from the db
863
+	 *                                   and thus call a different method to instantiate
864
+	 * @param bool   $cache              whether to cache the instantiated object for reuse
865
+	 * @param bool   $load_only          if true, will only load the file, but will NOT instantiate an object
866
+	 * @return bool|null|object          null   = failure to load or instantiate class object.
867
+	 *                                   object = class loaded and instantiated successfully.
868
+	 *                                   bool   = fail or success when $load_only is true
869
+	 * @throws EE_Error
870
+	 * @throws ReflectionException
871
+	 * @throws InvalidInterfaceException
872
+	 * @throws InvalidDataTypeException
873
+	 * @throws InvalidArgumentException
874
+	 */
875
+	protected function _load(
876
+		array $file_paths = [],
877
+		string $class_prefix = 'EE_',
878
+		string $class_name = '',
879
+		string $type = 'class',
880
+		array $arguments = [],
881
+		bool $from_db = false,
882
+		bool $cache = true,
883
+		bool $load_only = false
884
+	) {
885
+		$class_name = ltrim($class_name, '\\');
886
+		// strip php file extension
887
+		$class_name = str_replace('.php', '', trim($class_name));
888
+		// does the class have a prefix ?
889
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
890
+			// make sure $class_prefix is uppercase
891
+			$class_prefix = strtoupper(trim($class_prefix));
892
+			// add class prefix ONCE!!!
893
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
894
+		}
895
+		$class_name   = $this->class_cache->getFqnForAlias($class_name);
896
+		$class_exists = class_exists($class_name, false);
897
+		// if we're only loading the class and it already exists, then let's just return true immediately
898
+		if ($load_only && $class_exists) {
899
+			return true;
900
+		}
901
+		$arguments = is_array($arguments) ? $arguments : [$arguments];
902
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
903
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
904
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
905
+		if ($this->_cache_on && $cache && ! $load_only) {
906
+			// return object if it's already cached
907
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
908
+			if ($cached_class !== null) {
909
+				return $cached_class;
910
+			}
911
+		}
912
+		// if the class doesn't already exist.. then we need to try and find the file and load it
913
+		if (! $class_exists) {
914
+			// get full path to file
915
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
916
+			// load the file
917
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
918
+			// if we are only loading a file but NOT instantiating an object
919
+			// then return boolean for whether class was loaded or not
920
+			if ($load_only) {
921
+				return $loaded;
922
+			}
923
+			// if an object was expected but loading failed, then return nothing
924
+			if (! $loaded) {
925
+				return null;
926
+			}
927
+		}
928
+		// instantiate the requested object
929
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
930
+		if ($this->_cache_on && $cache) {
931
+			// save it for later... kinda like gum  { : $
932
+			$this->_set_cached_class(
933
+				$class_obj,
934
+				$class_name,
935
+				$class_prefix,
936
+				$from_db,
937
+				$arguments
938
+			);
939
+		}
940
+		$this->_cache_on = true;
941
+		return $class_obj;
942
+	}
943
+
944
+
945
+	/**
946
+	 * @param string $class_name
947
+	 * @param string $default have to specify something, but not anything that will conflict
948
+	 * @return mixed|string
949
+	 */
950
+	protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
951
+	{
952
+		return $this->_class_abbreviations[ $class_name ] ?? $default;
953
+	}
954
+
955
+
956
+	/**
957
+	 * attempts to find a cached version of the requested class
958
+	 * by looking in the following places:
959
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
960
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
961
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
962
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
963
+	 *
964
+	 * @param string $class_name
965
+	 * @param string $class_prefix
966
+	 * @param array  $arguments
967
+	 * @return mixed
968
+	 */
969
+	protected function _get_cached_class(
970
+		string $class_name,
971
+		string $class_prefix = '',
972
+		array $arguments = []
973
+	) {
974
+		if ($class_name === 'EE_Registry') {
975
+			return $this;
976
+		}
977
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
978
+		// check if class has already been loaded, and return it if it has been
979
+		if (isset($this->{$class_abbreviation})) {
980
+			return $this->{$class_abbreviation};
981
+		}
982
+		$class_name = str_replace('\\', '_', $class_name);
983
+		if (isset($this->{$class_name})) {
984
+			return $this->{$class_name};
985
+		}
986
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
987
+			return $this->addons->get($class_name);
988
+		}
989
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
990
+		if ($this->LIB->has($object_identifier)) {
991
+			return $this->LIB->get($object_identifier);
992
+		}
993
+		foreach ($this->LIB as $key => $object) {
994
+			if (
995
+				// request does not contain new arguments and therefore no args identifier
996
+				! $this->object_identifier->hasArguments($object_identifier)
997
+				// but previously cached class with args was found
998
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
999
+			) {
1000
+				return $object;
1001
+			}
1002
+		}
1003
+		return null;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * removes a cached version of the requested class
1009
+	 *
1010
+	 * @param string  $class_name
1011
+	 * @param boolean $addon
1012
+	 * @param array   $arguments
1013
+	 * @return boolean
1014
+	 */
1015
+	public function clear_cached_class(
1016
+		string $class_name,
1017
+		bool $addon = false,
1018
+		array $arguments = []
1019
+	): bool {
1020
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
1021
+		// check if class has already been loaded, and return it if it has been
1022
+		if (isset($this->{$class_abbreviation})) {
1023
+			$this->{$class_abbreviation} = null;
1024
+			return true;
1025
+		}
1026
+		$class_name = str_replace('\\', '_', $class_name);
1027
+		if (isset($this->{$class_name})) {
1028
+			$this->{$class_name} = null;
1029
+			return true;
1030
+		}
1031
+		if ($addon && $this->addons->has($class_name)) {
1032
+			$this->addons->remove($class_name);
1033
+			return true;
1034
+		}
1035
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1036
+		if ($this->LIB->has($class_name)) {
1037
+			$this->LIB->remove($class_name);
1038
+			return true;
1039
+		}
1040
+		return false;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * _set_cached_class
1046
+	 * attempts to cache the instantiated class locally
1047
+	 * in one of the following places, in the following order:
1048
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1049
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1050
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1051
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1052
+	 *
1053
+	 * @param object $class_obj
1054
+	 * @param string $class_name
1055
+	 * @param string $class_prefix
1056
+	 * @param bool   $from_db
1057
+	 * @param array  $arguments
1058
+	 * @return void
1059
+	 */
1060
+	protected function _set_cached_class(
1061
+		$class_obj,
1062
+		string $class_name,
1063
+		string $class_prefix = '',
1064
+		bool $from_db = false,
1065
+		array $arguments = []
1066
+	) {
1067
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1068
+			return;
1069
+		}
1070
+		// return newly instantiated class
1071
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1072
+		if ($class_abbreviation) {
1073
+			$this->{$class_abbreviation} = $class_obj;
1074
+			return;
1075
+		}
1076
+		$class_name = str_replace('\\', '_', $class_name);
1077
+		if (property_exists($this, $class_name)) {
1078
+			$this->{$class_name} = $class_obj;
1079
+			return;
1080
+		}
1081
+		if ($class_prefix === 'addon') {
1082
+			$this->addons->add($class_name, $class_obj);
1083
+			return;
1084
+		}
1085
+		if (! $from_db) {
1086
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1087
+			$this->LIB->add($class_name, $class_obj);
1088
+		}
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * attempts to find a full valid filepath for the requested class.
1094
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1095
+	 * then returns that path if the target file has been found and is readable
1096
+	 *
1097
+	 * @param string $class_name
1098
+	 * @param string $type
1099
+	 * @param array  $file_paths
1100
+	 * @return string | bool
1101
+	 */
1102
+	protected function _resolve_path(string $class_name, string $type = '', array $file_paths = [])
1103
+	{
1104
+		// make sure $file_paths is an array
1105
+		$file_paths = is_array($file_paths)
1106
+			? $file_paths
1107
+			: [$file_paths];
1108
+		// cycle thru paths
1109
+		foreach ($file_paths as $key => $file_path) {
1110
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1111
+			$file_path = $file_path
1112
+				? str_replace(['/', '\\'], '/', $file_path)
1113
+				: EE_CLASSES;
1114
+			// prep file type
1115
+			$type = ! empty($type)
1116
+				? trim($type, '.') . '.'
1117
+				: '';
1118
+			// build full file path
1119
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1120
+			// does the file exist and can be read ?
1121
+			if (is_readable($file_paths[ $key ])) {
1122
+				return $file_paths[ $key ];
1123
+			}
1124
+		}
1125
+		return false;
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * basically just performs a require_once()
1131
+	 * but with some error handling
1132
+	 *
1133
+	 * @param string $path
1134
+	 * @param string $class_name
1135
+	 * @param string $type
1136
+	 * @param array  $file_paths
1137
+	 * @return bool
1138
+	 * @throws EE_Error
1139
+	 * @throws ReflectionException
1140
+	 */
1141
+	protected function _require_file(string $path, string $class_name, string $type = '', array $file_paths = []): bool
1142
+	{
1143
+		$this->resolve_legacy_class_parent($class_name);
1144
+		// don't give up! you gotta...
1145
+		try {
1146
+			// does the file exist and can it be read ?
1147
+			if (! $path) {
1148
+				// just in case the file has already been autoloaded,
1149
+				// but discrepancies in the naming schema are preventing it from
1150
+				// being loaded via one of the EE_Registry::load_*() methods,
1151
+				// then let's try one last hail mary before throwing an exception
1152
+				// and call class_exists() again, but with autoloading turned ON
1153
+				if (class_exists($class_name)) {
1154
+					return true;
1155
+				}
1156
+				// so sorry, can't find the file
1157
+				throw new EE_Error(
1158
+					sprintf(
1159
+						esc_html__(
1160
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1161
+							'event_espresso'
1162
+						),
1163
+						trim($type, '.'),
1164
+						$class_name,
1165
+						'<br />' . implode(',<br />', $file_paths)
1166
+					)
1167
+				);
1168
+			}
1169
+			// get the file
1170
+			require_once($path);
1171
+			// if the class isn't already declared somewhere
1172
+			if (class_exists($class_name, false) === false) {
1173
+				// so sorry, not a class
1174
+				throw new EE_Error(
1175
+					sprintf(
1176
+						esc_html__(
1177
+							'The %s file %s does not appear to contain the %s Class.',
1178
+							'event_espresso'
1179
+						),
1180
+						$type,
1181
+						$path,
1182
+						$class_name
1183
+					)
1184
+				);
1185
+			}
1186
+		} catch (EE_Error $e) {
1187
+			$e->get_error();
1188
+			return false;
1189
+		}
1190
+		return true;
1191
+	}
1192
+
1193
+
1194
+	/**
1195
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1196
+	 * before their class declaration in order to ensure that the parent class was loaded.
1197
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1198
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1199
+	 *
1200
+	 * @param string $class_name
1201
+	 */
1202
+	protected function resolve_legacy_class_parent(string $class_name = '')
1203
+	{
1204
+		try {
1205
+			$legacy_parent_class_map = [
1206
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1207
+			];
1208
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1209
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1210
+			}
1211
+		} catch (Exception $exception) {
1212
+		}
1213
+	}
1214
+
1215
+
1216
+	/**
1217
+	 * _create_object
1218
+	 * Attempts to instantiate the requested class via any of the
1219
+	 * commonly used instantiation methods employed throughout EE.
1220
+	 * The priority for instantiation is as follows:
1221
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1222
+	 *        - model objects via their 'new_instance_from_db' method
1223
+	 *        - model objects via their 'new_instance' method
1224
+	 *        - "singleton" classes" via their 'instance' method
1225
+	 *    - standard instantiable classes via their __constructor
1226
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1227
+	 * then the constructor for the requested class will be examined to determine
1228
+	 * if any dependencies exist, and if they can be injected.
1229
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1230
+	 *
1231
+	 * @param string $class_name
1232
+	 * @param array  $arguments
1233
+	 * @param string $type
1234
+	 * @param bool   $from_db
1235
+	 * @return null|object|bool
1236
+	 * @throws InvalidArgumentException
1237
+	 * @throws InvalidInterfaceException
1238
+	 * @throws EE_Error
1239
+	 * @throws ReflectionException
1240
+	 * @throws InvalidDataTypeException
1241
+	 */
1242
+	protected function _create_object(
1243
+		string $class_name,
1244
+		array $arguments = [],
1245
+		string $type = '',
1246
+		bool $from_db = false
1247
+	) {
1248
+		// create reflection
1249
+		$reflector = $this->mirror->getReflectionClass($class_name);
1250
+		// make sure arguments are an array
1251
+		$arguments = is_array($arguments)
1252
+			? $arguments
1253
+			: [$arguments];
1254
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1255
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1256
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1257
+			? $arguments
1258
+			: [$arguments];
1259
+		// attempt to inject dependencies ?
1260
+		if ($this->_dependency_map->has($class_name)) {
1261
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1262
+		}
1263
+		// instantiate the class if possible
1264
+		if ($reflector->isAbstract()) {
1265
+			// nothing to instantiate, loading file was enough
1266
+			// does not throw an exception so $instantiation_mode is unused
1267
+			// $instantiation_mode = "1) no constructor abstract class";
1268
+			return true;
1269
+		}
1270
+		if (
1271
+			empty($arguments)
1272
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1273
+			&& $reflector->isInstantiable()
1274
+		) {
1275
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1276
+			// $instantiation_mode = "2) no constructor but instantiable";
1277
+			return $reflector->newInstance();
1278
+		}
1279
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1280
+			// $instantiation_mode = "3) new_instance_from_db()";
1281
+			return call_user_func_array([$class_name, 'new_instance_from_db'], $arguments);
1282
+		}
1283
+		if (method_exists($class_name, 'new_instance')) {
1284
+			// $instantiation_mode = "4) new_instance()";
1285
+			return call_user_func_array([$class_name, 'new_instance'], $arguments);
1286
+		}
1287
+		if (method_exists($class_name, 'instance')) {
1288
+			// $instantiation_mode = "5) instance()";
1289
+			return call_user_func_array([$class_name, 'instance'], $arguments);
1290
+		}
1291
+		if ($reflector->isInstantiable()) {
1292
+			// $instantiation_mode = "6) constructor";
1293
+			return $reflector->newInstanceArgs($arguments);
1294
+		}
1295
+		// heh ? something's not right !
1296
+		throw new EE_Error(
1297
+			sprintf(
1298
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1299
+				$type,
1300
+				$class_name
1301
+			)
1302
+		);
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1308
+	 * @param array $array
1309
+	 * @return bool
1310
+	 */
1311
+	protected function _array_is_numerically_and_sequentially_indexed(array $array): bool
1312
+	{
1313
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * _resolve_dependencies
1319
+	 * examines the constructor for the requested class to determine
1320
+	 * if any dependencies exist, and if they can be injected.
1321
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1322
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1323
+	 * For example:
1324
+	 *        if attempting to load a class "Foo" with the following constructor:
1325
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1326
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1327
+	 *        but only IF they are NOT already present in the incoming arguments array,
1328
+	 *        and the correct classes can be loaded
1329
+	 *
1330
+	 * @param ReflectionClass $reflector
1331
+	 * @param string          $class_name
1332
+	 * @param array           $arguments
1333
+	 * @return array
1334
+	 * @throws InvalidArgumentException
1335
+	 * @throws InvalidDataTypeException
1336
+	 * @throws InvalidInterfaceException
1337
+	 * @throws ReflectionException
1338
+	 */
1339
+	protected function _resolve_dependencies(
1340
+		ReflectionClass $reflector,
1341
+		string $class_name,
1342
+		array $arguments = []
1343
+	): array {
1344
+		// let's examine the constructor
1345
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1346
+		// whu? huh? nothing?
1347
+		if (! $constructor) {
1348
+			return $arguments;
1349
+		}
1350
+		// get constructor parameters
1351
+		$params = $this->mirror->getParametersFromReflection($reflector);
1352
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1353
+		$argument_keys = array_keys($arguments);
1354
+		// now loop thru all of the constructors expected parameters
1355
+		foreach ($params as $index => $param) {
1356
+			try {
1357
+				// is this a dependency for a specific class ?
1358
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1359
+			} catch (ReflectionException $exception) {
1360
+				// uh-oh... most likely a legacy class that has not been autoloaded
1361
+				// let's try to derive the classname from what we have now
1362
+				// and hope that the property var name is close to the class name
1363
+				$param_class = $param->getName();
1364
+				$param_class = str_replace('_', ' ', $param_class);
1365
+				$param_class = ucwords($param_class);
1366
+				$param_class = str_replace(' ', '_', $param_class);
1367
+			}
1368
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1369
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1370
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1371
+				: $param_class;
1372
+			// param is not even a class
1373
+			if (
1374
+				! empty($param_class)
1375
+				&& ! class_exists($param_class, false)
1376
+				// and something already exists in the incoming arguments for this param
1377
+				&& array_key_exists($index, $argument_keys)
1378
+				&& isset($arguments[ $argument_keys[ $index ] ])
1379
+			) {
1380
+				// so let's skip this argument and move on to the next
1381
+				continue;
1382
+			}
1383
+			// parameter is type hinted as a class
1384
+			if ($param_class !== null) {
1385
+				// parameter exists as an incoming argument, AND it's the correct class
1386
+				if (
1387
+					array_key_exists($index, $argument_keys)
1388
+					&& isset($arguments[ $argument_keys[ $index ] ])
1389
+					&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1390
+				) {
1391
+					// skip this argument and move on to the next
1392
+					continue;
1393
+				}
1394
+				// parameter should be injected
1395
+				if ($this->_dependency_map->has_dependency_for_class($class_name, $param_class)) {
1396
+					$arguments = $this->_resolve_dependency(
1397
+						$class_name,
1398
+						$param_class,
1399
+						$arguments,
1400
+						$index
1401
+					);
1402
+				}
1403
+			}
1404
+			if (empty($arguments[ $index ])) {
1405
+				$default_value = $this->mirror->getParameterDefaultValue(
1406
+					$param,
1407
+					$class_name,
1408
+					$index
1409
+				);
1410
+				// if there's no default value, and the incoming argument is an array (albeit empty), then use that
1411
+				$arguments[ $index ] = $default_value === null
1412
+									   && isset($arguments[ $index ])
1413
+									   && is_array($arguments[ $index ])
1414
+					? $arguments[ $index ]
1415
+					: $default_value;
1416
+			}
1417
+		}
1418
+		return $arguments;
1419
+	}
1420
+
1421
+
1422
+	/**
1423
+	 * @param string $class_name
1424
+	 * @param string $param_class
1425
+	 * @param array  $arguments
1426
+	 * @param mixed  $index
1427
+	 * @return array
1428
+	 * @throws InvalidArgumentException
1429
+	 * @throws InvalidInterfaceException
1430
+	 * @throws InvalidDataTypeException
1431
+	 */
1432
+	protected function _resolve_dependency(string $class_name, string $param_class, array $arguments, $index): array
1433
+	{
1434
+		$dependency = null;
1435
+		// should dependency be loaded from cache ?
1436
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1437
+			$class_name,
1438
+			$param_class
1439
+		);
1440
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1441
+		// we might have a dependency...
1442
+		// let's MAYBE try and find it in our cache if that's what's been requested
1443
+		$cached_class = $cache_on
1444
+			? $this->_get_cached_class($param_class)
1445
+			: null;
1446
+		// and grab it if it exists
1447
+		if ($cached_class instanceof $param_class) {
1448
+			$dependency = $cached_class;
1449
+		} elseif ($param_class !== $class_name) {
1450
+			// obtain the loader method from the dependency map
1451
+			$loader = $this->_dependency_map->class_loader($param_class);
1452
+			// is loader a custom closure ?
1453
+			if ($loader instanceof Closure) {
1454
+				$dependency = $loader($arguments);
1455
+			} else {
1456
+				// set the cache on property for the recursive loading call
1457
+				$this->_cache_on = $cache_on;
1458
+				// if not, then let's try and load it via the registry
1459
+				if ($loader && method_exists($this, $loader)) {
1460
+					$dependency = $this->{$loader}($param_class);
1461
+				} else {
1462
+					$dependency = LoaderFactory::getLoader()->load(
1463
+						$param_class,
1464
+						[],
1465
+						$cache_on
1466
+					);
1467
+				}
1468
+			}
1469
+		}
1470
+		// did we successfully find the correct dependency ?
1471
+		if ($dependency instanceof $param_class) {
1472
+			// then let's inject it into the incoming array of arguments at the correct location
1473
+			$arguments[ $index ] = $dependency;
1474
+		}
1475
+		return $arguments;
1476
+	}
1477
+
1478
+
1479
+	/**
1480
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1481
+	 *
1482
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1483
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1484
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1485
+	 * @param array  $arguments
1486
+	 * @return object
1487
+	 */
1488
+	public static function factory(string $classname, array $arguments = [])
1489
+	{
1490
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1491
+		if ($loader instanceof Closure) {
1492
+			return $loader($arguments);
1493
+		}
1494
+		if (method_exists(self::instance(), $loader)) {
1495
+			return self::instance()->{$loader}($classname, $arguments);
1496
+		}
1497
+		return null;
1498
+	}
1499
+
1500
+
1501
+	/**
1502
+	 * Gets the addon by its class name
1503
+	 *
1504
+	 * @param string $class_name
1505
+	 * @return EE_Addon
1506
+	 */
1507
+	public function getAddon(string $class_name): ?EE_Addon
1508
+	{
1509
+		$class_name = str_replace('\\', '_', $class_name);
1510
+		return $this->addons->{$class_name} ?? null;
1511
+	}
1512
+
1513
+
1514
+	/**
1515
+	 * removes the addon from the internal cache
1516
+	 *
1517
+	 * @param string $class_name
1518
+	 * @return void
1519
+	 */
1520
+	public function removeAddon(string $class_name)
1521
+	{
1522
+		$class_name = str_replace('\\', '_', $class_name);
1523
+		$this->addons->remove($class_name);
1524
+	}
1525
+
1526
+
1527
+	/**
1528
+	 * Gets the addon by its name/slug (not classname. For that, just
1529
+	 * use the get_addon() method above
1530
+	 *
1531
+	 * @param string $name
1532
+	 * @return EE_Addon
1533
+	 */
1534
+	public function get_addon_by_name(string $name): ?EE_Addon
1535
+	{
1536
+		foreach ($this->addons as $addon) {
1537
+			if ($addon->name() === $name) {
1538
+				return $addon;
1539
+			}
1540
+		}
1541
+		return null;
1542
+	}
1543
+
1544
+
1545
+	/**
1546
+	 * Gets an array of all the registered addons, where the keys are their names.
1547
+	 * (ie, what each returns for their name() function)
1548
+	 * They're already available on EE_Registry::instance()->addons as properties,
1549
+	 * where each property's name is the addon's classname,
1550
+	 * So if you just want to get the addon by classname,
1551
+	 * OR use the get_addon() method above.
1552
+	 * PLEASE  NOTE:
1553
+	 * addons with Fully Qualified Class Names
1554
+	 * have had the namespace separators converted to underscores,
1555
+	 * so a classname like Fully\Qualified\ClassName
1556
+	 * would have been converted to Fully_Qualified_ClassName
1557
+	 *
1558
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1559
+	 */
1560
+	public function get_addons_by_name(): array
1561
+	{
1562
+		$addons = [];
1563
+		foreach ($this->addons as $addon) {
1564
+			$addons[ $addon->name() ] = $addon;
1565
+		}
1566
+		return $addons;
1567
+	}
1568
+
1569
+
1570
+	/**
1571
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1572
+	 * a stale copy of it around
1573
+	 *
1574
+	 * @param string $model_name
1575
+	 * @return EEM_Base
1576
+	 * @throws EE_Error
1577
+	 * @throws ReflectionException
1578
+	 */
1579
+	public function reset_model(string $model_name): ?EEM_Base
1580
+	{
1581
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1582
+			? "EEM_$model_name"
1583
+			: $model_name;
1584
+		if (! $this->LIB->has($model_class_name)) {
1585
+			return null;
1586
+		}
1587
+		$model = $this->LIB->get($model_class_name);
1588
+		if (! $model instanceof EEM_Base) {
1589
+			return null;
1590
+		}
1591
+		// get that model reset it and make sure we nuke the old reference to it
1592
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1593
+			$this->LIB->remove($model_class_name);
1594
+			$this->LIB->add($model_class_name, $model->reset());
1595
+		} else {
1596
+			throw new EE_Error(
1597
+				sprintf(
1598
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1599
+					$model_name
1600
+				)
1601
+			);
1602
+		}
1603
+		return $model;
1604
+	}
1605
+
1606
+
1607
+	/**
1608
+	 * Resets the registry.
1609
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1610
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1611
+	 * - $_dependency_map
1612
+	 * - $_class_abbreviations
1613
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1614
+	 * - $REQ:  Still on the same request so no need to change.
1615
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1616
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1617
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1618
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1619
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1620
+	 *             switch or on the restore.
1621
+	 * - $modules
1622
+	 * - $shortcodes
1623
+	 * - $widgets
1624
+	 *
1625
+	 * @param boolean $hard             [deprecated]
1626
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1627
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1628
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1629
+	 * @param bool    $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1630
+	 *                                  client
1631
+	 *                                  code instead can just change the model context to a different blog id if
1632
+	 *                                  necessary
1633
+	 * @return EE_Registry
1634
+	 * @throws EE_Error
1635
+	 * @throws ReflectionException
1636
+	 */
1637
+	public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry
1638
+	{
1639
+		$instance            = self::instance();
1640
+		$instance->_cache_on = true;
1641
+		// reset some "special" classes
1642
+		EEH_Activation::reset();
1643
+		$hard                     = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1644
+		$instance->CFG            = EE_Config::reset($hard, $reinstantiate);
1645
+		$instance->CART           = null;
1646
+		$instance->MRM            = null;
1647
+		$instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1648
+			'EventEspresso\core\services\assets\Registry'
1649
+		);
1650
+		// messages reset
1651
+		EED_Messages::reset();
1652
+		// handle of objects cached on LIB
1653
+		foreach (['LIB', 'modules'] as $cache) {
1654
+			foreach ($instance->{$cache} as $class_name => $class) {
1655
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1656
+					unset($instance->{$cache}->{$class_name});
1657
+				}
1658
+			}
1659
+		}
1660
+		return $instance;
1661
+	}
1662
+
1663
+
1664
+	/**
1665
+	 * if passed object implements ResettableInterface, then call it's reset() method
1666
+	 * if passed object implements InterminableInterface, then return false,
1667
+	 * to indicate that it should NOT be cleared from the Registry cache
1668
+	 *
1669
+	 * @param      $object
1670
+	 * @param bool $reset_models
1671
+	 * @return bool returns true if cached object should be unset
1672
+	 * @throws EE_Error
1673
+	 * @throws ReflectionException
1674
+	 */
1675
+	private static function _reset_and_unset_object($object, bool $reset_models): bool
1676
+	{
1677
+		if (! is_object($object)) {
1678
+			// don't unset anything that's not an object
1679
+			return false;
1680
+		}
1681
+		if ($object instanceof EED_Module) {
1682
+			$object::reset();
1683
+			// don't unset modules
1684
+			return false;
1685
+		}
1686
+		if ($object instanceof ResettableInterface) {
1687
+			if ($object instanceof EEM_Base) {
1688
+				if ($reset_models) {
1689
+					$object->reset();
1690
+					return true;
1691
+				}
1692
+				return false;
1693
+			}
1694
+			$object->reset();
1695
+			return true;
1696
+		}
1697
+		if (! $object instanceof InterminableInterface) {
1698
+			return true;
1699
+		}
1700
+		return false;
1701
+	}
1702
+
1703
+
1704
+	/**
1705
+	 * Gets all the custom post type models defined
1706
+	 *
1707
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1708
+	 */
1709
+	public function cpt_models(): array
1710
+	{
1711
+		$cpt_models = [];
1712
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1713
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1714
+				$cpt_models[ $short_name ] = $classname;
1715
+			}
1716
+		}
1717
+		return $cpt_models;
1718
+	}
1719
+
1720
+
1721
+	/**
1722
+	 * @return EE_Config
1723
+	 */
1724
+	public static function CFG(): EE_Config
1725
+	{
1726
+		return self::instance()->CFG;
1727
+	}
1728
+
1729
+
1730
+	/**
1731
+	 * @param string $class_name
1732
+	 * @return ReflectionClass
1733
+	 * @throws ReflectionException
1734
+	 * @throws InvalidDataTypeException
1735
+	 * @deprecated 4.9.62.p
1736
+	 */
1737
+	public function get_ReflectionClass(string $class_name): ReflectionClass
1738
+	{
1739
+		return $this->mirror->getReflectionClass($class_name);
1740
+	}
1741 1741
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
         $i18n_js_strings = (array) self::$i18n_js_strings;
308 308
         foreach ($i18n_js_strings as $key => $value) {
309 309
             if (is_scalar($value)) {
310
-                $i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
310
+                $i18n_js_strings[$key] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311 311
             }
312 312
         }
313 313
         return $i18n_js_strings;
@@ -322,7 +322,7 @@  discard block
 block discarded – undo
322 322
     public static function localize_i18n_js_strings(): string
323 323
     {
324 324
         $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
325
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
325
+        return '/* <![CDATA[ */ var eei18n = '.wp_json_encode($i18n_js_strings).'; /* ]]> */';
326 326
     }
327 327
 
328 328
 
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
             $module_class = get_class($module);
342 342
             $this->modules->add($module_class, $module);
343 343
         } else {
344
-            if (! class_exists('EE_Module_Request_Router', false)) {
344
+            if ( ! class_exists('EE_Module_Request_Router', false)) {
345 345
                 $this->load_core('Module_Request_Router');
346 346
             }
347 347
             EE_Module_Request_Router::module_factory($module);
@@ -380,10 +380,10 @@  discard block
 block discarded – undo
380 380
                 EE_CORE,
381 381
                 EE_ADMIN,
382 382
                 EE_CPTS,
383
-                EE_CORE . 'CPTs/',
384
-                EE_CORE . 'data_migration_scripts/',
385
-                EE_CORE . 'request_stack/',
386
-                EE_CORE . 'middleware/',
383
+                EE_CORE.'CPTs/',
384
+                EE_CORE.'data_migration_scripts/',
385
+                EE_CORE.'request_stack/',
386
+                EE_CORE.'middleware/',
387 387
             ]
388 388
         );
389 389
         // retrieve instantiated class
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
         $service_paths = (array) apply_filters(
420 420
             'FHEE__EE_Registry__load_service__service_paths',
421 421
             [
422
-                EE_CORE . 'services/',
422
+                EE_CORE.'services/',
423 423
             ]
424 424
         );
425 425
         // retrieve instantiated class
@@ -559,10 +559,10 @@  discard block
 block discarded – undo
559 559
     {
560 560
         $paths = [
561 561
             EE_LIBRARIES,
562
-            EE_LIBRARIES . 'messages/',
563
-            EE_LIBRARIES . 'shortcodes/',
564
-            EE_LIBRARIES . 'qtips/',
565
-            EE_LIBRARIES . 'payment_methods/',
562
+            EE_LIBRARIES.'messages/',
563
+            EE_LIBRARIES.'shortcodes/',
564
+            EE_LIBRARIES.'qtips/',
565
+            EE_LIBRARIES.'payment_methods/',
566 566
         ];
567 567
         // retrieve instantiated class
568 568
         return $this->_load(
@@ -631,10 +631,10 @@  discard block
 block discarded – undo
631 631
     public function load_model_class(string $class_name, $arguments = [], bool $load_only = true)
632 632
     {
633 633
         $paths = [
634
-            EE_MODELS . 'fields/',
635
-            EE_MODELS . 'helpers/',
636
-            EE_MODELS . 'relations/',
637
-            EE_MODELS . 'strategies/',
634
+            EE_MODELS.'fields/',
635
+            EE_MODELS.'helpers/',
636
+            EE_MODELS.'relations/',
637
+            EE_MODELS.'strategies/',
638 638
         ];
639 639
         // retrieve instantiated class
640 640
         return $this->_load(
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
      */
659 659
     public function is_model_name(string $model_name): bool
660 660
     {
661
-        return isset($this->models[ $model_name ]);
661
+        return isset($this->models[$model_name]);
662 662
     }
663 663
 
664 664
 
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
                 return $cached_class;
791 791
             }
792 792
         }                                                           // obtain the loader method from the dependency map
793
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
793
+        $loader = $this->_dependency_map->class_loader($class_name); // instantiate the requested object
794 794
         if ($loader instanceof Closure) {
795 795
             $class_obj = $loader($arguments);
796 796
         } else {
@@ -832,7 +832,7 @@  discard block
 block discarded – undo
832 832
             case 1:
833 833
                 // if it's a FQCN then maybe the class is registered with a preceding \
834 834
                 $class_name = strpos($class_name, '\\') !== false
835
-                    ? '\\' . ltrim($class_name, '\\')
835
+                    ? '\\'.ltrim($class_name, '\\')
836 836
                     : $class_name;
837 837
                 break;
838 838
             case 2:
@@ -886,11 +886,11 @@  discard block
 block discarded – undo
886 886
         // strip php file extension
887 887
         $class_name = str_replace('.php', '', trim($class_name));
888 888
         // does the class have a prefix ?
889
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
889
+        if ( ! empty($class_prefix) && $class_prefix !== 'addon') {
890 890
             // make sure $class_prefix is uppercase
891 891
             $class_prefix = strtoupper(trim($class_prefix));
892 892
             // add class prefix ONCE!!!
893
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
893
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
894 894
         }
895 895
         $class_name   = $this->class_cache->getFqnForAlias($class_name);
896 896
         $class_exists = class_exists($class_name, false);
@@ -910,7 +910,7 @@  discard block
 block discarded – undo
910 910
             }
911 911
         }
912 912
         // if the class doesn't already exist.. then we need to try and find the file and load it
913
-        if (! $class_exists) {
913
+        if ( ! $class_exists) {
914 914
             // get full path to file
915 915
             $path = $this->_resolve_path($class_name, $type, $file_paths);
916 916
             // load the file
@@ -921,7 +921,7 @@  discard block
 block discarded – undo
921 921
                 return $loaded;
922 922
             }
923 923
             // if an object was expected but loading failed, then return nothing
924
-            if (! $loaded) {
924
+            if ( ! $loaded) {
925 925
                 return null;
926 926
             }
927 927
         }
@@ -949,7 +949,7 @@  discard block
 block discarded – undo
949 949
      */
950 950
     protected function get_class_abbreviation(string $class_name, string $default = 'FANCY_BATMAN_PANTS')
951 951
     {
952
-        return $this->_class_abbreviations[ $class_name ] ?? $default;
952
+        return $this->_class_abbreviations[$class_name] ?? $default;
953 953
     }
954 954
 
955 955
 
@@ -1082,7 +1082,7 @@  discard block
 block discarded – undo
1082 1082
             $this->addons->add($class_name, $class_obj);
1083 1083
             return;
1084 1084
         }
1085
-        if (! $from_db) {
1085
+        if ( ! $from_db) {
1086 1086
             $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1087 1087
             $this->LIB->add($class_name, $class_obj);
1088 1088
         }
@@ -1113,13 +1113,13 @@  discard block
 block discarded – undo
1113 1113
                 : EE_CLASSES;
1114 1114
             // prep file type
1115 1115
             $type = ! empty($type)
1116
-                ? trim($type, '.') . '.'
1116
+                ? trim($type, '.').'.'
1117 1117
                 : '';
1118 1118
             // build full file path
1119
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1119
+            $file_paths[$key] = rtrim($file_path, '/').'/'.$class_name.'.'.$type.'php';
1120 1120
             // does the file exist and can be read ?
1121
-            if (is_readable($file_paths[ $key ])) {
1122
-                return $file_paths[ $key ];
1121
+            if (is_readable($file_paths[$key])) {
1122
+                return $file_paths[$key];
1123 1123
             }
1124 1124
         }
1125 1125
         return false;
@@ -1144,7 +1144,7 @@  discard block
 block discarded – undo
1144 1144
         // don't give up! you gotta...
1145 1145
         try {
1146 1146
             // does the file exist and can it be read ?
1147
-            if (! $path) {
1147
+            if ( ! $path) {
1148 1148
                 // just in case the file has already been autoloaded,
1149 1149
                 // but discrepancies in the naming schema are preventing it from
1150 1150
                 // being loaded via one of the EE_Registry::load_*() methods,
@@ -1162,7 +1162,7 @@  discard block
 block discarded – undo
1162 1162
                         ),
1163 1163
                         trim($type, '.'),
1164 1164
                         $class_name,
1165
-                        '<br />' . implode(',<br />', $file_paths)
1165
+                        '<br />'.implode(',<br />', $file_paths)
1166 1166
                     )
1167 1167
                 );
1168 1168
             }
@@ -1205,8 +1205,8 @@  discard block
 block discarded – undo
1205 1205
             $legacy_parent_class_map = [
1206 1206
                 'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1207 1207
             ];
1208
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1209
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1208
+            if (isset($legacy_parent_class_map[$class_name])) {
1209
+                require_once EE_PLUGIN_DIR_PATH.$legacy_parent_class_map[$class_name];
1210 1210
             }
1211 1211
         } catch (Exception $exception) {
1212 1212
         }
@@ -1344,7 +1344,7 @@  discard block
 block discarded – undo
1344 1344
         // let's examine the constructor
1345 1345
         $constructor = $this->mirror->getConstructorFromReflection($reflector);
1346 1346
         // whu? huh? nothing?
1347
-        if (! $constructor) {
1347
+        if ( ! $constructor) {
1348 1348
             return $arguments;
1349 1349
         }
1350 1350
         // get constructor parameters
@@ -1375,7 +1375,7 @@  discard block
 block discarded – undo
1375 1375
                 && ! class_exists($param_class, false)
1376 1376
                 // and something already exists in the incoming arguments for this param
1377 1377
                 && array_key_exists($index, $argument_keys)
1378
-                && isset($arguments[ $argument_keys[ $index ] ])
1378
+                && isset($arguments[$argument_keys[$index]])
1379 1379
             ) {
1380 1380
                 // so let's skip this argument and move on to the next
1381 1381
                 continue;
@@ -1385,8 +1385,8 @@  discard block
 block discarded – undo
1385 1385
                 // parameter exists as an incoming argument, AND it's the correct class
1386 1386
                 if (
1387 1387
                     array_key_exists($index, $argument_keys)
1388
-                    && isset($arguments[ $argument_keys[ $index ] ])
1389
-                    && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1388
+                    && isset($arguments[$argument_keys[$index]])
1389
+                    && $arguments[$argument_keys[$index]] instanceof $param_class
1390 1390
                 ) {
1391 1391
                     // skip this argument and move on to the next
1392 1392
                     continue;
@@ -1401,17 +1401,17 @@  discard block
 block discarded – undo
1401 1401
                     );
1402 1402
                 }
1403 1403
             }
1404
-            if (empty($arguments[ $index ])) {
1404
+            if (empty($arguments[$index])) {
1405 1405
                 $default_value = $this->mirror->getParameterDefaultValue(
1406 1406
                     $param,
1407 1407
                     $class_name,
1408 1408
                     $index
1409 1409
                 );
1410 1410
                 // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1411
-                $arguments[ $index ] = $default_value === null
1412
-                                       && isset($arguments[ $index ])
1413
-                                       && is_array($arguments[ $index ])
1414
-                    ? $arguments[ $index ]
1411
+                $arguments[$index] = $default_value === null
1412
+                                       && isset($arguments[$index])
1413
+                                       && is_array($arguments[$index])
1414
+                    ? $arguments[$index]
1415 1415
                     : $default_value;
1416 1416
             }
1417 1417
         }
@@ -1470,7 +1470,7 @@  discard block
 block discarded – undo
1470 1470
         // did we successfully find the correct dependency ?
1471 1471
         if ($dependency instanceof $param_class) {
1472 1472
             // then let's inject it into the incoming array of arguments at the correct location
1473
-            $arguments[ $index ] = $dependency;
1473
+            $arguments[$index] = $dependency;
1474 1474
         }
1475 1475
         return $arguments;
1476 1476
     }
@@ -1561,7 +1561,7 @@  discard block
 block discarded – undo
1561 1561
     {
1562 1562
         $addons = [];
1563 1563
         foreach ($this->addons as $addon) {
1564
-            $addons[ $addon->name() ] = $addon;
1564
+            $addons[$addon->name()] = $addon;
1565 1565
         }
1566 1566
         return $addons;
1567 1567
     }
@@ -1581,11 +1581,11 @@  discard block
 block discarded – undo
1581 1581
         $model_class_name = strpos($model_name, 'EEM_') !== 0
1582 1582
             ? "EEM_$model_name"
1583 1583
             : $model_name;
1584
-        if (! $this->LIB->has($model_class_name)) {
1584
+        if ( ! $this->LIB->has($model_class_name)) {
1585 1585
             return null;
1586 1586
         }
1587 1587
         $model = $this->LIB->get($model_class_name);
1588
-        if (! $model instanceof EEM_Base) {
1588
+        if ( ! $model instanceof EEM_Base) {
1589 1589
             return null;
1590 1590
         }
1591 1591
         // get that model reset it and make sure we nuke the old reference to it
@@ -1674,7 +1674,7 @@  discard block
 block discarded – undo
1674 1674
      */
1675 1675
     private static function _reset_and_unset_object($object, bool $reset_models): bool
1676 1676
     {
1677
-        if (! is_object($object)) {
1677
+        if ( ! is_object($object)) {
1678 1678
             // don't unset anything that's not an object
1679 1679
             return false;
1680 1680
         }
@@ -1694,7 +1694,7 @@  discard block
 block discarded – undo
1694 1694
             $object->reset();
1695 1695
             return true;
1696 1696
         }
1697
-        if (! $object instanceof InterminableInterface) {
1697
+        if ( ! $object instanceof InterminableInterface) {
1698 1698
             return true;
1699 1699
         }
1700 1700
         return false;
@@ -1711,7 +1711,7 @@  discard block
 block discarded – undo
1711 1711
         $cpt_models = [];
1712 1712
         foreach ($this->non_abstract_db_models as $short_name => $classname) {
1713 1713
             if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1714
-                $cpt_models[ $short_name ] = $classname;
1714
+                $cpt_models[$short_name] = $classname;
1715 1715
             }
1716 1716
         }
1717 1717
         return $cpt_models;
Please login to merge, or discard this patch.
core/helpers/EEH_Form_Fields.helper.php 2 patches
Indentation   +1946 added lines, -1946 removed lines patch added patch discarded remove patch
@@ -27,1973 +27,1973 @@
 block discarded – undo
27 27
  */
28 28
 class EEH_Form_Fields
29 29
 {
30
-    /**
31
-     *  Generates HTML for the forms used on admin pages
32
-     *
33
-     *
34
-     * @static
35
-     * @access public
36
-     * @param array $input_vars - array of input field details
37
-     *                          format:
38
-     *                          $template_form_fields['field-id'] = array(
39
-     *                          'name' => 'name_attribute',
40
-     *                          'label' => esc_html__('Field Label', 'event_espresso'), //or false
41
-     *                          'input' => 'hidden', //field input type can be 'text', 'select', 'textarea', 'hidden',
42
-     *                          'checkbox', 'wp_editor'
43
-     *                          'type' => 'int', //what "type" the value is (i.e. string, int etc)
44
-     *                          'required' => false, //boolean for whether the field is required
45
-     *                          'validation' => true, //boolean, whether to validate the field (todo)
46
-     *                          'value' => 'some_value_for_field', //what value is used for field
47
-     *                          'format' => '%d', //what format the value is (%d, %f, or %s)
48
-     *                          'db-col' => 'column_in_db' //used to indicate which column the field corresponds with
49
-     *                          in the db
50
-     *                          'options' => optiona, optionb || array('value' => 'label', '') //if the input type is
51
-     *                          "select", this allows you to set the args for the different <option> tags.
52
-     *                          'tabindex' => 1 //this allows you to set the tabindex for the field.
53
-     *                          'append_content' => '' //this allows you to send in html content to append to the
54
-     *                          field.
55
-     *                          )
56
-     * @param array $form_id    - used for defining unique identifiers for the form.
57
-     * @return string
58
-     * @todo   : at some point we can break this down into other static methods to abstract it a bit better.
59
-     */
60
-    public static function get_form_fields($input_vars = [], $form_id = false)
61
-    {
62
-
63
-        if (empty($input_vars)) {
64
-            EE_Error::add_error(
65
-                esc_html__('missing required variables for the form field generator', 'event_espresso'),
66
-                __FILE__,
67
-                __FUNCTION__,
68
-                __LINE__
69
-            );
70
-            return false;
71
-        }
72
-
73
-        $output        = "";
74
-        $inputs        = [];
75
-        $hidden_inputs = [];
76
-
77
-        // cycle thru inputs
78
-        foreach ($input_vars as $input_key => $input_value) {
79
-            $defaults = [
80
-                'append_content' => '',
81
-                'css_class'      => '',
82
-                'cols'           => 80,
83
-                'db-col'         => 'column_in_db',
84
-                'format'         => '%d',
85
-                'input'          => 'hidden',
86
-                'label'          => esc_html__('No label', 'event_espresso'),
87
-                'name'           => $input_key,
88
-                'options'        => [],
89
-                'required'       => false,
90
-                'tabindex'       => 0,
91
-                'rows'           => 10,
92
-                'type'           => 'int',
93
-                'validation'     => true,
94
-                'value'          => 'some_value_for_field',
95
-            ];
96
-
97
-            $input_value = wp_parse_args($input_value, $defaults);
98
-
99
-            $append_content = $input_value['append_content'];
100
-            $css_class      = $input_value['css_class'];
101
-            $cols           = $input_value['cols'];
102
-            $label          = $input_value['label'];
103
-            $name           = $input_value['name'];
104
-            $options        = $input_value['options'];
105
-            $required       = $input_value['required'];
106
-            $tab_index      = $input_value['tabindex'];
107
-            $rows           = $input_value['rows'];
108
-            $type           = $input_value['input'];
109
-            $value          = $input_value['value'];
110
-
111
-            $id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
-            $class = $required ? 'required ' . $css_class : $css_class;
113
-
114
-            // what type of input are we dealing with ?
115
-            switch ($type) {
116
-                case 'checkbox':
117
-                case 'radio':
118
-                    $field = self::adminMulti($value, $class, $id, $name, $required, $tab_index, $type, 1, $label);
119
-                    $field .= $append_content ?: '';
120
-                    break;
121
-
122
-                case 'hidden':
123
-                    $field           = null;
124
-                    $hidden_inputs[] = self::adminHidden($css_class, $id, $name, $value);
125
-                    break;
126
-
127
-                case 'select':
128
-                    $options = is_array($options) ? $options : explode(',', $options);
129
-                    $field   = self::adminLabel($id, $label, $required);
130
-                    $field   .= self::adminSelect($value, $class, $id, $name, $required, $tab_index, $options);
131
-                    $field   .= $append_content ?: '';
132
-                    break;
133
-
134
-                case 'textarea':
135
-                    $field = self::adminLabel($id, $label, $required);
136
-                    $field .= self::adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value);
137
-                    $field .= $append_content ?: '';
138
-                    break;
139
-
140
-                case 'wp_editor':
141
-                    $label = esc_html($label);
142
-                    $field = "<h4>{$label}</h4>";
143
-                    $field .= $append_content ?: '';
144
-                    $field .= self::adminWpEditor(
145
-                        $class,
146
-                        $id,
147
-                        $name,
148
-                        $rows,
149
-                        $tab_index,
150
-                        $value
151
-                    );
152
-                    break;
153
-
154
-                default:
155
-                    $field = self::adminLabel($id, $label, $required);
156
-                    $field .= self::adminText($class, $id, $name, $required, $tab_index, $value);
157
-                    $field .= $append_content ?: '';
158
-            }
159
-            if ($field) {
160
-                $inputs[] = $field;
161
-            }
162
-        } // end foreach( $input_vars as $input_key => $input_value )
163
-
164
-        if (! empty($inputs)) {
165
-            $glue   = "
30
+	/**
31
+	 *  Generates HTML for the forms used on admin pages
32
+	 *
33
+	 *
34
+	 * @static
35
+	 * @access public
36
+	 * @param array $input_vars - array of input field details
37
+	 *                          format:
38
+	 *                          $template_form_fields['field-id'] = array(
39
+	 *                          'name' => 'name_attribute',
40
+	 *                          'label' => esc_html__('Field Label', 'event_espresso'), //or false
41
+	 *                          'input' => 'hidden', //field input type can be 'text', 'select', 'textarea', 'hidden',
42
+	 *                          'checkbox', 'wp_editor'
43
+	 *                          'type' => 'int', //what "type" the value is (i.e. string, int etc)
44
+	 *                          'required' => false, //boolean for whether the field is required
45
+	 *                          'validation' => true, //boolean, whether to validate the field (todo)
46
+	 *                          'value' => 'some_value_for_field', //what value is used for field
47
+	 *                          'format' => '%d', //what format the value is (%d, %f, or %s)
48
+	 *                          'db-col' => 'column_in_db' //used to indicate which column the field corresponds with
49
+	 *                          in the db
50
+	 *                          'options' => optiona, optionb || array('value' => 'label', '') //if the input type is
51
+	 *                          "select", this allows you to set the args for the different <option> tags.
52
+	 *                          'tabindex' => 1 //this allows you to set the tabindex for the field.
53
+	 *                          'append_content' => '' //this allows you to send in html content to append to the
54
+	 *                          field.
55
+	 *                          )
56
+	 * @param array $form_id    - used for defining unique identifiers for the form.
57
+	 * @return string
58
+	 * @todo   : at some point we can break this down into other static methods to abstract it a bit better.
59
+	 */
60
+	public static function get_form_fields($input_vars = [], $form_id = false)
61
+	{
62
+
63
+		if (empty($input_vars)) {
64
+			EE_Error::add_error(
65
+				esc_html__('missing required variables for the form field generator', 'event_espresso'),
66
+				__FILE__,
67
+				__FUNCTION__,
68
+				__LINE__
69
+			);
70
+			return false;
71
+		}
72
+
73
+		$output        = "";
74
+		$inputs        = [];
75
+		$hidden_inputs = [];
76
+
77
+		// cycle thru inputs
78
+		foreach ($input_vars as $input_key => $input_value) {
79
+			$defaults = [
80
+				'append_content' => '',
81
+				'css_class'      => '',
82
+				'cols'           => 80,
83
+				'db-col'         => 'column_in_db',
84
+				'format'         => '%d',
85
+				'input'          => 'hidden',
86
+				'label'          => esc_html__('No label', 'event_espresso'),
87
+				'name'           => $input_key,
88
+				'options'        => [],
89
+				'required'       => false,
90
+				'tabindex'       => 0,
91
+				'rows'           => 10,
92
+				'type'           => 'int',
93
+				'validation'     => true,
94
+				'value'          => 'some_value_for_field',
95
+			];
96
+
97
+			$input_value = wp_parse_args($input_value, $defaults);
98
+
99
+			$append_content = $input_value['append_content'];
100
+			$css_class      = $input_value['css_class'];
101
+			$cols           = $input_value['cols'];
102
+			$label          = $input_value['label'];
103
+			$name           = $input_value['name'];
104
+			$options        = $input_value['options'];
105
+			$required       = $input_value['required'];
106
+			$tab_index      = $input_value['tabindex'];
107
+			$rows           = $input_value['rows'];
108
+			$type           = $input_value['input'];
109
+			$value          = $input_value['value'];
110
+
111
+			$id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
+			$class = $required ? 'required ' . $css_class : $css_class;
113
+
114
+			// what type of input are we dealing with ?
115
+			switch ($type) {
116
+				case 'checkbox':
117
+				case 'radio':
118
+					$field = self::adminMulti($value, $class, $id, $name, $required, $tab_index, $type, 1, $label);
119
+					$field .= $append_content ?: '';
120
+					break;
121
+
122
+				case 'hidden':
123
+					$field           = null;
124
+					$hidden_inputs[] = self::adminHidden($css_class, $id, $name, $value);
125
+					break;
126
+
127
+				case 'select':
128
+					$options = is_array($options) ? $options : explode(',', $options);
129
+					$field   = self::adminLabel($id, $label, $required);
130
+					$field   .= self::adminSelect($value, $class, $id, $name, $required, $tab_index, $options);
131
+					$field   .= $append_content ?: '';
132
+					break;
133
+
134
+				case 'textarea':
135
+					$field = self::adminLabel($id, $label, $required);
136
+					$field .= self::adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value);
137
+					$field .= $append_content ?: '';
138
+					break;
139
+
140
+				case 'wp_editor':
141
+					$label = esc_html($label);
142
+					$field = "<h4>{$label}</h4>";
143
+					$field .= $append_content ?: '';
144
+					$field .= self::adminWpEditor(
145
+						$class,
146
+						$id,
147
+						$name,
148
+						$rows,
149
+						$tab_index,
150
+						$value
151
+					);
152
+					break;
153
+
154
+				default:
155
+					$field = self::adminLabel($id, $label, $required);
156
+					$field .= self::adminText($class, $id, $name, $required, $tab_index, $value);
157
+					$field .= $append_content ?: '';
158
+			}
159
+			if ($field) {
160
+				$inputs[] = $field;
161
+			}
162
+		} // end foreach( $input_vars as $input_key => $input_value )
163
+
164
+		if (! empty($inputs)) {
165
+			$glue   = "
166 166
                 </li>
167 167
                 <li>
168 168
                     ";
169
-            $inputs = implode($glue, $inputs);
170
-            $output = "
169
+			$inputs = implode($glue, $inputs);
170
+			$output = "
171 171
             <ul>
172 172
                 <li>
173 173
                 {$inputs} 
174 174
                 </li>
175 175
             </ul>
176 176
             ";
177
-        }
178
-        return $output . implode("\n", $hidden_inputs);
179
-    }
180
-
181
-
182
-    /**
183
-     * form_fields_array
184
-     * This utility function assembles form fields from a given structured array with field information.
185
-     * //TODO: This is an alternate generator that we may want to use instead.
186
-     *
187
-     * @param array $fields structured array of fields to assemble in the following format:
188
-     *                      [field_name] => array(
189
-     *                      ['label'] => 'label for field',
190
-     *                      ['labels'] => array('label_1', 'label_2'); //optional - if the field type is a multi select
191
-     *                      type of field you can indicated the labels for each option via this index
192
-     *                      ['extra_desc'] => 'extra description for the field', //optional
193
-     *                      ['type'] => 'textarea'|'text'|'wp_editor'|'checkbox'|'radio'|'hidden'|'select', //defaults
194
-     *                      to text
195
-     *                      ['value'] => 'value that goes in the field', //(if multi then this is an array of values
196
-     *                      and the 'default' paramater will be used for what is selected)
197
-     *                      ['default'] => 'default if the field type is multi (i.e. select or radios or checkboxes)',
198
-     *                      ['class'] => 'name-of-class(es)-for-input',
199
-     *                      ['classes'] => array('class_1', 'class_2'); //optional - if the field type is a multi
200
-     *                      select type of field you can indicate the css class for each option via this index.
201
-     *                      ['id'] => 'css-id-for-input') //defaults to 'field_name'
202
-     *                      ['unique_id'] => 1 //defaults to empty string.  This is useful for when the fields
203
-     *                      generated are going to be used in a loop and you want to make sure that the field
204
-     *                      identifiers are unique from each other.
205
-     *                      ['dimensions'] => array(100,300), //defaults to empty array.  This is used by field types
206
-     *                      such as textarea to indicate cols/rows.
207
-     *                      ['tabindex'] => '' //this allows you to set the tabindex for the field.
208
-     *                      ['wpeditor_args'] => array() //if the type of field is wpeditor then this can optionally
209
-     *                      contain an array of arguments for the editor setup.
210
-     *
211
-     * @return array         an array of inputs for form indexed by field name, and in the following structure:
212
-     *     [field_name] => array( 'label' => '{label_html}', 'field' => '{input_html}'
213
-     */
214
-    public static function get_form_fields_array($fields)
215
-    {
216
-
217
-        $form_fields = [];
218
-        $fields      = (array) $fields;
219
-
220
-        foreach ($fields as $field_name => $field_atts) {
221
-            // defaults:
222
-            $defaults = [
223
-                'class'         => '',
224
-                'classes'       => '',
225
-                'default'       => '',
226
-                'dimensions'    => ['10', '5'],
227
-                'extra_desc'    => '',
228
-                'id'            => $field_name,
229
-                'label'         => '',
230
-                'labels'        => '',
231
-                'required'      => false,
232
-                'tabindex'      => 0,
233
-                'type'          => 'text',
234
-                'unique_id'     => '',
235
-                'value'         => '',
236
-                'wpeditor_args' => [],
237
-            ];
238
-            // merge defaults with passed arguments
239
-            $_fields = wp_parse_args($field_atts, $defaults);
240
-
241
-            $class          = $_fields['class'];
242
-            $classes        = $_fields['classes'];
243
-            $default        = $_fields['default'];
244
-            $dims           = $_fields['dimensions'];
245
-            $extra_desc     = $_fields['extra_desc'];
246
-            $id             = $_fields['id'];
247
-            $label          = $_fields['label'];
248
-            $labels         = $_fields['labels'];
249
-            $required       = $_fields['required'];
250
-            $tab_index      = $_fields['tabindex'];
251
-            $type           = $_fields['type'];
252
-            $unique_id      = $_fields['unique_id'];
253
-            $value          = $_fields['value'];
254
-            $wp_editor_args = $_fields['wpeditor_args'];
255
-
256
-            // generate label
257
-            $label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258
-            // generate field name
259
-            $name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
260
-
261
-            // we determine what we're building based on the type
262
-            switch ($type) {
263
-                case 'checkbox':
264
-                case 'radio':
265
-                    if (is_array($value)) {
266
-                        $c_input = '';
267
-                        foreach ($value as $key => $val) {
268
-                            $c_input .= self::adminMulti(
269
-                                $default,
270
-                                isset($classes[ $key ]) ? $classes[ $key ] : '',
271
-                                $field_name . '_' . $value,
272
-                                $name,
273
-                                $required,
274
-                                $tab_index,
275
-                                $type,
276
-                                $val,
277
-                                isset($labels[ $key ]) ? $labels[ $key ] : ''
278
-                            );
279
-                        }
280
-                        $field = $c_input;
281
-                    } else {
282
-                        $field = self::adminMulti(
283
-                            $default,
284
-                            $class,
285
-                            $id,
286
-                            $name,
287
-                            $required,
288
-                            $tab_index,
289
-                            $type,
290
-                            $value,
291
-                            $_fields['label']
292
-                        );
293
-                    }
294
-                    break;
295
-
296
-                case 'hidden':
297
-                    $field = self::adminHidden($class, $id, $name, $value);
298
-                    break;
299
-
300
-                case 'select':
301
-                    $options = [];
302
-                    foreach ($value as $key => $val) {
303
-                        $options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
304
-                    }
305
-                    $field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306
-                    break;
307
-
308
-                case 'textarea':
309
-                    $field =
310
-                        self::adminTextarea($class, $dims[0], $id, $name, $required, $dims[1], $tab_index, $value);
311
-                    break;
312
-
313
-                case 'wp_editor':
314
-                    $field = self::adminWpEditor(
315
-                        $class,
316
-                        $_fields['id'],
317
-                        $name,
318
-                        $dims[1],
319
-                        $tab_index,
320
-                        $value,
321
-                        $wp_editor_args
322
-                    );
323
-                    break;
324
-
325
-                default:
326
-                    $field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327
-            }
328
-
329
-            $form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
330
-        }
331
-
332
-        return $form_fields;
333
-    }
334
-
335
-
336
-    /**
337
-     * @param string $class
338
-     * @param string $id
339
-     * @param string $name
340
-     * @param string $value
341
-     * @return string
342
-     * @since   4.10.14.p
343
-     */
344
-    private static function adminHidden($class, $id, $name, $value)
345
-    {
346
-        return "
177
+		}
178
+		return $output . implode("\n", $hidden_inputs);
179
+	}
180
+
181
+
182
+	/**
183
+	 * form_fields_array
184
+	 * This utility function assembles form fields from a given structured array with field information.
185
+	 * //TODO: This is an alternate generator that we may want to use instead.
186
+	 *
187
+	 * @param array $fields structured array of fields to assemble in the following format:
188
+	 *                      [field_name] => array(
189
+	 *                      ['label'] => 'label for field',
190
+	 *                      ['labels'] => array('label_1', 'label_2'); //optional - if the field type is a multi select
191
+	 *                      type of field you can indicated the labels for each option via this index
192
+	 *                      ['extra_desc'] => 'extra description for the field', //optional
193
+	 *                      ['type'] => 'textarea'|'text'|'wp_editor'|'checkbox'|'radio'|'hidden'|'select', //defaults
194
+	 *                      to text
195
+	 *                      ['value'] => 'value that goes in the field', //(if multi then this is an array of values
196
+	 *                      and the 'default' paramater will be used for what is selected)
197
+	 *                      ['default'] => 'default if the field type is multi (i.e. select or radios or checkboxes)',
198
+	 *                      ['class'] => 'name-of-class(es)-for-input',
199
+	 *                      ['classes'] => array('class_1', 'class_2'); //optional - if the field type is a multi
200
+	 *                      select type of field you can indicate the css class for each option via this index.
201
+	 *                      ['id'] => 'css-id-for-input') //defaults to 'field_name'
202
+	 *                      ['unique_id'] => 1 //defaults to empty string.  This is useful for when the fields
203
+	 *                      generated are going to be used in a loop and you want to make sure that the field
204
+	 *                      identifiers are unique from each other.
205
+	 *                      ['dimensions'] => array(100,300), //defaults to empty array.  This is used by field types
206
+	 *                      such as textarea to indicate cols/rows.
207
+	 *                      ['tabindex'] => '' //this allows you to set the tabindex for the field.
208
+	 *                      ['wpeditor_args'] => array() //if the type of field is wpeditor then this can optionally
209
+	 *                      contain an array of arguments for the editor setup.
210
+	 *
211
+	 * @return array         an array of inputs for form indexed by field name, and in the following structure:
212
+	 *     [field_name] => array( 'label' => '{label_html}', 'field' => '{input_html}'
213
+	 */
214
+	public static function get_form_fields_array($fields)
215
+	{
216
+
217
+		$form_fields = [];
218
+		$fields      = (array) $fields;
219
+
220
+		foreach ($fields as $field_name => $field_atts) {
221
+			// defaults:
222
+			$defaults = [
223
+				'class'         => '',
224
+				'classes'       => '',
225
+				'default'       => '',
226
+				'dimensions'    => ['10', '5'],
227
+				'extra_desc'    => '',
228
+				'id'            => $field_name,
229
+				'label'         => '',
230
+				'labels'        => '',
231
+				'required'      => false,
232
+				'tabindex'      => 0,
233
+				'type'          => 'text',
234
+				'unique_id'     => '',
235
+				'value'         => '',
236
+				'wpeditor_args' => [],
237
+			];
238
+			// merge defaults with passed arguments
239
+			$_fields = wp_parse_args($field_atts, $defaults);
240
+
241
+			$class          = $_fields['class'];
242
+			$classes        = $_fields['classes'];
243
+			$default        = $_fields['default'];
244
+			$dims           = $_fields['dimensions'];
245
+			$extra_desc     = $_fields['extra_desc'];
246
+			$id             = $_fields['id'];
247
+			$label          = $_fields['label'];
248
+			$labels         = $_fields['labels'];
249
+			$required       = $_fields['required'];
250
+			$tab_index      = $_fields['tabindex'];
251
+			$type           = $_fields['type'];
252
+			$unique_id      = $_fields['unique_id'];
253
+			$value          = $_fields['value'];
254
+			$wp_editor_args = $_fields['wpeditor_args'];
255
+
256
+			// generate label
257
+			$label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258
+			// generate field name
259
+			$name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
260
+
261
+			// we determine what we're building based on the type
262
+			switch ($type) {
263
+				case 'checkbox':
264
+				case 'radio':
265
+					if (is_array($value)) {
266
+						$c_input = '';
267
+						foreach ($value as $key => $val) {
268
+							$c_input .= self::adminMulti(
269
+								$default,
270
+								isset($classes[ $key ]) ? $classes[ $key ] : '',
271
+								$field_name . '_' . $value,
272
+								$name,
273
+								$required,
274
+								$tab_index,
275
+								$type,
276
+								$val,
277
+								isset($labels[ $key ]) ? $labels[ $key ] : ''
278
+							);
279
+						}
280
+						$field = $c_input;
281
+					} else {
282
+						$field = self::adminMulti(
283
+							$default,
284
+							$class,
285
+							$id,
286
+							$name,
287
+							$required,
288
+							$tab_index,
289
+							$type,
290
+							$value,
291
+							$_fields['label']
292
+						);
293
+					}
294
+					break;
295
+
296
+				case 'hidden':
297
+					$field = self::adminHidden($class, $id, $name, $value);
298
+					break;
299
+
300
+				case 'select':
301
+					$options = [];
302
+					foreach ($value as $key => $val) {
303
+						$options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
304
+					}
305
+					$field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306
+					break;
307
+
308
+				case 'textarea':
309
+					$field =
310
+						self::adminTextarea($class, $dims[0], $id, $name, $required, $dims[1], $tab_index, $value);
311
+					break;
312
+
313
+				case 'wp_editor':
314
+					$field = self::adminWpEditor(
315
+						$class,
316
+						$_fields['id'],
317
+						$name,
318
+						$dims[1],
319
+						$tab_index,
320
+						$value,
321
+						$wp_editor_args
322
+					);
323
+					break;
324
+
325
+				default:
326
+					$field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327
+			}
328
+
329
+			$form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
330
+		}
331
+
332
+		return $form_fields;
333
+	}
334
+
335
+
336
+	/**
337
+	 * @param string $class
338
+	 * @param string $id
339
+	 * @param string $name
340
+	 * @param string $value
341
+	 * @return string
342
+	 * @since   4.10.14.p
343
+	 */
344
+	private static function adminHidden($class, $id, $name, $value)
345
+	{
346
+		return "
347 347
         <input name='" . esc_attr($name) . "' type='hidden' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' 
348 348
         value='" . esc_attr($value) . "' />";
349
-    }
350
-
351
-
352
-    /**
353
-     * @param string $id
354
-     * @param string $label
355
-     * @param string $required
356
-     * @return string
357
-     * @since   4.10.14.p
358
-     */
359
-    private static function adminLabel($id, $label, $required)
360
-    {
361
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? " <span>*</span>" : '';
362
-        return "<label for='" . esc_attr($id) . "'>" . esc_html($label) . $required . "</label>";
363
-    }
364
-
365
-
366
-    /**
367
-     * @param string $default
368
-     * @param string $class
369
-     * @param string $id
370
-     * @param string $name
371
-     * @param string $required
372
-     * @param int    $tab_index
373
-     * @param string $type
374
-     * @param string $value
375
-     * @param string $label
376
-     * @return string
377
-     * @since   4.10.14.p
378
-     */
379
-    private static function adminMulti($default, $class, $id, $name, $required, $tab_index, $type, $value, $label = '')
380
-    {
381
-        $checked   = ! empty($default) && $default == $value ? 'checked ' : '';
382
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
383
-        $input     = "
349
+	}
350
+
351
+
352
+	/**
353
+	 * @param string $id
354
+	 * @param string $label
355
+	 * @param string $required
356
+	 * @return string
357
+	 * @since   4.10.14.p
358
+	 */
359
+	private static function adminLabel($id, $label, $required)
360
+	{
361
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? " <span>*</span>" : '';
362
+		return "<label for='" . esc_attr($id) . "'>" . esc_html($label) . $required . "</label>";
363
+	}
364
+
365
+
366
+	/**
367
+	 * @param string $default
368
+	 * @param string $class
369
+	 * @param string $id
370
+	 * @param string $name
371
+	 * @param string $required
372
+	 * @param int    $tab_index
373
+	 * @param string $type
374
+	 * @param string $value
375
+	 * @param string $label
376
+	 * @return string
377
+	 * @since   4.10.14.p
378
+	 */
379
+	private static function adminMulti($default, $class, $id, $name, $required, $tab_index, $type, $value, $label = '')
380
+	{
381
+		$checked   = ! empty($default) && $default == $value ? 'checked ' : '';
382
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
383
+		$input     = "
384 384
         <input name='" . esc_attr($name) . "[]' type='" . esc_attr($type) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' value='" . esc_attr($value) . "' {$checked} {$required} tabindex='" . absint($tab_index) . "'/>";
385
-        if ($label === '') {
386
-            return $input;
387
-        }
388
-        $label = esc_html($label);
389
-        return "
385
+		if ($label === '') {
386
+			return $input;
387
+		}
388
+		$label = esc_html($label);
389
+		return "
390 390
         <label for='$id'>
391 391
             {$input}
392 392
             {$label}
393 393
         </label>";
394
-    }
395
-
396
-
397
-    /**
398
-     * @param string $default
399
-     * @param string $class
400
-     * @param string $id
401
-     * @param string $name
402
-     * @param string $required
403
-     * @param int    $tab_index
404
-     * @param array  $options
405
-     * @return string
406
-     * @since   4.10.14.p
407
-     */
408
-    private static function adminSelect($default, $class, $id, $name, $required, $tab_index, $options = [])
409
-    {
410
-        $options_array = [];
411
-        foreach ($options as $value => $label) {
412
-            $selected        = ! empty($default) && $default == $value ? 'selected' : '';
413
-            $label           = wp_strip_all_tags($label);
414
-            $options_array[] = "<option value='" . esc_attr($value) . "' {$selected}>{$label}</option>";
415
-        }
416
-        $options_html = implode("\n", $options_array);
417
-        $required     = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
418
-        return "
394
+	}
395
+
396
+
397
+	/**
398
+	 * @param string $default
399
+	 * @param string $class
400
+	 * @param string $id
401
+	 * @param string $name
402
+	 * @param string $required
403
+	 * @param int    $tab_index
404
+	 * @param array  $options
405
+	 * @return string
406
+	 * @since   4.10.14.p
407
+	 */
408
+	private static function adminSelect($default, $class, $id, $name, $required, $tab_index, $options = [])
409
+	{
410
+		$options_array = [];
411
+		foreach ($options as $value => $label) {
412
+			$selected        = ! empty($default) && $default == $value ? 'selected' : '';
413
+			$label           = wp_strip_all_tags($label);
414
+			$options_array[] = "<option value='" . esc_attr($value) . "' {$selected}>{$label}</option>";
415
+		}
416
+		$options_html = implode("\n", $options_array);
417
+		$required     = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
418
+		return "
419 419
         <select name='" . esc_attr($name) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' {$required} 
420 420
         tabindex='" . absint($tab_index) . "'>
421 421
             {$options_html}
422 422
         </select>";
423
-    }
424
-
425
-
426
-    /**
427
-     * @param string $class
428
-     * @param string $id
429
-     * @param string $name
430
-     * @param string $required
431
-     * @param int    $tab_index
432
-     * @param string $value
433
-     * @return string
434
-     * @since   4.10.14.p
435
-     */
436
-    private static function adminText($class, $id, $name, $required, $tab_index, $value)
437
-    {
438
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
439
-        return "
423
+	}
424
+
425
+
426
+	/**
427
+	 * @param string $class
428
+	 * @param string $id
429
+	 * @param string $name
430
+	 * @param string $required
431
+	 * @param int    $tab_index
432
+	 * @param string $value
433
+	 * @return string
434
+	 * @since   4.10.14.p
435
+	 */
436
+	private static function adminText($class, $id, $name, $required, $tab_index, $value)
437
+	{
438
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
439
+		return "
440 440
         <input name='" . esc_attr($name) . "' type='text' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' 
441 441
         value='" . esc_attr($value) . "' {$required} tabindex='" . absint($tab_index) . "'/>";
442
-    }
443
-
444
-
445
-    /**
446
-     * @param string $class
447
-     * @param int    $cols
448
-     * @param string $id
449
-     * @param string $name
450
-     * @param string $required
451
-     * @param int    $rows
452
-     * @param int    $tab_index
453
-     * @param string $value
454
-     * @return string
455
-     * @since   4.10.14.p
456
-     */
457
-    private static function adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value)
458
-    {
459
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
460
-        return "
442
+	}
443
+
444
+
445
+	/**
446
+	 * @param string $class
447
+	 * @param int    $cols
448
+	 * @param string $id
449
+	 * @param string $name
450
+	 * @param string $required
451
+	 * @param int    $rows
452
+	 * @param int    $tab_index
453
+	 * @param string $value
454
+	 * @return string
455
+	 * @since   4.10.14.p
456
+	 */
457
+	private static function adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value)
458
+	{
459
+		$required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
460
+		return "
461 461
         <textarea name='" . esc_attr($name) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' rows='" . absint($rows) . "' cols='" . absint($cols) . "' {$required} tabindex='" . absint($tab_index) . "'>" . esc_textarea($value) . "</textarea>";
462
-    }
463
-
464
-
465
-    /**
466
-     * @param string $class
467
-     * @param string $id
468
-     * @param string $name
469
-     * @param int    $rows
470
-     * @param int    $tab_index
471
-     * @param string $value
472
-     * @param array  $wp_editor_args
473
-     * @return false|string
474
-     * @since   4.10.14.p
475
-     */
476
-    private static function adminWpEditor($class, $id, $name, $rows, $tab_index, $value, $wp_editor_args = [])
477
-    {
478
-        $editor_settings = $wp_editor_args + [
479
-                'textarea_name' => esc_attr($name),
480
-                'textarea_rows' => absint($rows),
481
-                'editor_class'  => esc_attr($class),
482
-                'tabindex'      => absint($tab_index),
483
-            ];
484
-        ob_start();
485
-        wp_editor($value, esc_attr($id), $editor_settings);
486
-        return ob_get_clean();
487
-    }
488
-
489
-
490
-    /**
491
-     * espresso admin page select_input
492
-     * Turns an array into a select fields
493
-     *
494
-     * @static
495
-     * @access public
496
-     * @param string  $name       field name
497
-     * @param array   $values     option values, numbered array starting at 0, where each value is an array with a key
498
-     *                            'text' (meaning text to display' and 'id' (meaning the internal value) eg:
499
-     *                            array(1=>array('text'=>'Monday','id'=>1),2=>array('text'=>'Tuesday','id'=>2)...). or
500
-     *                            as an array of key-value pairs, where the key is to be used for the select input's
501
-     *                            name, and the value will be the text shown to the user.  Optionally you can also
502
-     *                            include an additional key of "class" which will add a specific class to the option
503
-     *                            for that value.
504
-     * @param string  $default    default value
505
-     * @param string  $parameters extra parameters
506
-     * @param string  $class      css class
507
-     * @param boolean $autosize   whether to autosize the select or not
508
-     * @return string              html string for the select input
509
-     */
510
-    public static function select_input($name, $values, $default = '', $parameters = '', $class = '', $autosize = true)
511
-    {
512
-        // if $values was submitted in the wrong format, convert it over
513
-        if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
514
-            $converted_values = [];
515
-            foreach ($values as $id => $text) {
516
-                $converted_values[] = ['id' => $id, 'text' => $text];
517
-            }
518
-            $values = $converted_values;
519
-        }
520
-
521
-        $field =
522
-            '<select id="' . EEH_Formatter::ee_tep_output_string($name)
523
-            . '" name="' . EEH_Formatter::ee_tep_output_string($name)
524
-            . '"';
525
-
526
-        if (EEH_Formatter::ee_tep_not_null($parameters)) {
527
-            $field .= ' ' . $parameters;
528
-        }
529
-        if ($autosize) {
530
-            $size = 'med';
531
-            for ($ii = 0, $ni = sizeof($values); $ii < $ni; $ii++) {
532
-                if ($values[ $ii ]['text']) {
533
-                    if (strlen($values[ $ii ]['text']) > 5) {
534
-                        $size = 'wide';
535
-                    }
536
-                }
537
-            }
538
-        } else {
539
-            $size = '';
540
-        }
541
-
542
-        $field .= ' class="' . $class . ' ' . $size . '">';
543
-
544
-        if (empty($default) && isset($GLOBALS[ $name ])) {
545
-            $default = stripslashes($GLOBALS[ $name ]);
546
-        }
547
-
548
-
549
-        for ($i = 0, $n = sizeof($values); $i < $n; $i++) {
550
-            $field .= '<option value="' . $values[ $i ]['id'] . '"';
551
-            if ($default == $values[ $i ]['id']) {
552
-                $field .= ' selected = "selected"';
553
-            }
554
-            if (isset($values[ $i ]['class'])) {
555
-                $field .= ' class="' . $values[ $i ]['class'] . '"';
556
-            }
557
-            $field .= '>' . $values[ $i ]['text'] . '</option>';
558
-        }
559
-        $field .= '</select>';
560
-
561
-        return $field;
562
-    }
563
-
564
-
565
-    /**
566
-     * generate_question_groups_html
567
-     *
568
-     * @param array  $question_groups
569
-     * @param string $group_wrapper
570
-     * @return string HTML
571
-     * @throws EE_Error
572
-     * @throws ReflectionException
573
-     */
574
-    public static function generate_question_groups_html($question_groups = [], $group_wrapper = 'fieldset')
575
-    {
576
-
577
-        $html                            = '';
578
-        $before_question_group_questions =
579
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
580
-        $after_question_group_questions  =
581
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
582
-
583
-        if (! empty($question_groups)) {
584
-            // loop thru question groups
585
-            foreach ($question_groups as $QSG) {
586
-                // check that questions exist
587
-                if (! empty($QSG['QSG_questions'])) {
588
-                    // use fieldsets
589
-                    $html .= "\n\t"
590
-                             . '<'
591
-                             . $group_wrapper
592
-                             . ' class="espresso-question-group-wrap" id="'
593
-                             . $QSG['QSG_identifier']
594
-                             . '">';
595
-                    // group_name
596
-                    $html .= $QSG['QSG_show_group_name']
597
-                        ? "\n\t\t"
598
-                          . '<h5 class="espresso-question-group-title-h5 section-title">'
599
-                          . self::prep_answer($QSG['QSG_name'])
600
-                          . '</h5>'
601
-                        : '';
602
-                    // group_desc
603
-                    $html .= $QSG['QSG_show_group_desc'] && ! empty($QSG['QSG_desc'])
604
-                        ? '<div class="espresso-question-group-desc-pg">'
605
-                          . self::prep_answer($QSG['QSG_desc'])
606
-                          . '</div>'
607
-                        : '';
608
-
609
-                    $html .= $before_question_group_questions;
610
-                    // loop thru questions
611
-                    foreach ($QSG['QSG_questions'] as $question) {
612
-                        $QFI  = new EE_Question_Form_Input(
613
-                            $question['qst_obj'],
614
-                            $question['ans_obj'],
615
-                            $question
616
-                        );
617
-                        $html .= self::generate_form_input($QFI);
618
-                    }
619
-                    $html .= $after_question_group_questions;
620
-                    $html .= "\n\t" . '</' . $group_wrapper . '>';
621
-                }
622
-            }
623
-        }
624
-
625
-        return $html;
626
-    }
627
-
628
-
629
-    /**
630
-     * generate_question_groups_html
631
-     *
632
-     * @param array  $question_groups
633
-     * @param array  $q_meta
634
-     * @param bool   $from_admin
635
-     * @param string $group_wrapper
636
-     * @return string HTML
637
-     * @throws EE_Error
638
-     * @throws ReflectionException
639
-     */
640
-    public static function generate_question_groups_html2(
641
-        $question_groups = [],
642
-        $q_meta = [],
643
-        $from_admin = false,
644
-        $group_wrapper = 'fieldset'
645
-    ) {
646
-
647
-        $html                            = '';
648
-        $before_question_group_questions =
649
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
650
-        $after_question_group_questions  =
651
-            apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
652
-
653
-        $default_q_meta = [
654
-            'att_nmbr'    => 1,
655
-            'ticket_id'   => '',
656
-            'input_name'  => '',
657
-            'input_id'    => '',
658
-            'input_class' => '',
659
-        ];
660
-        $q_meta         = array_merge($default_q_meta, $q_meta);
661
-
662
-        if (! empty($question_groups)) {
663
-            // loop thru question groups
664
-            foreach ($question_groups as $QSG) {
665
-                if ($QSG instanceof EE_Question_Group) {
666
-                    // check that questions exist
667
-
668
-                    $where = ['QST_deleted' => 0];
669
-                    if (! $from_admin) {
670
-                        $where['QST_admin_only'] = 0;
671
-                    }
672
-                    $questions =
673
-                        $QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
674
-                    if (! empty($questions)) {
675
-                        // use fieldsets
676
-                        $html .= "\n\t"
677
-                                 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
678
-                                 . 'id="' . $QSG->get('QSG_identifier') . '">';
679
-                        // group_name
680
-                        if ($QSG->show_group_name()) {
681
-                            $html .= "\n\t\t"
682
-                                     . '<h5 class="espresso-question-group-title-h5 section-title">'
683
-                                     . $QSG->get_pretty('QSG_name')
684
-                                     . '</h5>';
685
-                        }
686
-                        // group_desc
687
-                        if ($QSG->show_group_desc()) {
688
-                            $html .= '<div class="espresso-question-group-desc-pg">'
689
-                                     . $QSG->get_pretty('QSG_desc')
690
-                                     . '</div>';
691
-                        }
692
-
693
-                        $html .= $before_question_group_questions;
694
-                        // loop thru questions
695
-                        foreach ($questions as $QST) {
696
-                            $qstn_id = $QST->is_system_question() ? $QST->system_ID() : $QST->ID();
697
-
698
-                            $answer = null;
699
-
700
-                            /** @var RequestInterface $request */
701
-                            $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
702
-                            $request_qstn = $request->getRequestParam('qstn', [], 'string', true);
703
-                            if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
704
-                                // check for answer in $request_qstn in case we are reprocessing a form after an error
705
-                                if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
706
-                                    $answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
707
-                                        ? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
708
-                                        : sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
709
-                                }
710
-                            } elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
711
-                                // attendee data from the session
712
-                                $answer =
713
-                                    isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
714
-                            }
715
-
716
-
717
-                            $QFI  = new EE_Question_Form_Input(
718
-                                $QST,
719
-                                EE_Answer::new_instance(
720
-                                    [
721
-                                        'ANS_ID'    => 0,
722
-                                        'QST_ID'    => 0,
723
-                                        'REG_ID'    => 0,
724
-                                        'ANS_value' => $answer,
725
-                                    ]
726
-                                ),
727
-                                $q_meta
728
-                            );
729
-                            $html .= self::generate_form_input($QFI);
730
-                        }
731
-                        $html .= $after_question_group_questions;
732
-                        $html .= "\n\t" . '</' . $group_wrapper . '>';
733
-                    }
734
-                }
735
-            }
736
-        }
737
-        return $html;
738
-    }
739
-
740
-
741
-    /**
742
-     * generate_form_input
743
-     *
744
-     * @param EE_Question_Form_Input $QFI
745
-     * @return string HTML
746
-     * @throws EE_Error
747
-     * @throws ReflectionException
748
-     */
749
-    public static function generate_form_input(EE_Question_Form_Input $QFI)
750
-    {
751
-        if (isset($QFI->QST_admin_only) && $QFI->QST_admin_only && ! is_admin()) {
752
-            return '';
753
-        }
754
-        /** @var RequestInterface $request */
755
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
756
-
757
-        $QFI = self::_load_system_dropdowns($QFI);
758
-        $QFI = self::_load_specialized_dropdowns($QFI);
759
-
760
-        // we also need to verify
761
-
762
-        $display_text = $QFI->get('QST_display_text');
763
-        $input_name   = $QFI->get('QST_input_name');
764
-        $answer       = $request->getRequestParam($input_name, $QFI->get('ANS_value'));
765
-        $input_id     = $QFI->get('QST_input_id');
766
-        $input_class  = $QFI->get('QST_input_class');
767
-        //      $disabled = $QFI->get('QST_disabled') ? ' disabled="disabled"' : '';
768
-        $disabled          = $QFI->get('QST_disabled');
769
-        $required_label    = apply_filters(' FHEE__EEH_Form_Fields__generate_form_input__required_label', '<em>*</em>');
770
-        $QST_required      = $QFI->get('QST_required');
771
-        $required          =
772
-            $QST_required
773
-                ? ['label' => $required_label, 'class' => 'required needs-value', 'title' => $QST_required]
774
-                : [];
775
-        $use_html_entities = $QFI->get_meta('htmlentities');
776
-        $required_text     =
777
-            $QFI->get('QST_required_text') != ''
778
-                ? $QFI->get('QST_required_text')
779
-                : esc_html__('This field is required', 'event_espresso');
780
-        $required_text     = $QST_required
781
-            ? "\n\t\t\t"
782
-              . '<div class="required-text hidden">'
783
-              . self::prep_answer($required_text, $use_html_entities)
784
-              . '</div>'
785
-            : '';
786
-        $label_class       = 'espresso-form-input-lbl';
787
-        $QST_options       = $QFI->options(true, $answer);
788
-        $options           = is_array($QST_options) ? self::prep_answer_options($QST_options) : [];
789
-        $system_ID         = $QFI->get('QST_system');
790
-        $label_b4          = $QFI->get_meta('label_b4');
791
-        $use_desc_4_label  = $QFI->get_meta('use_desc_4_label');
792
-
793
-
794
-        switch ($QFI->get('QST_type')) {
795
-            case 'TEXTAREA':
796
-                return EEH_Form_Fields::textarea(
797
-                    $display_text,
798
-                    $answer,
799
-                    $input_name,
800
-                    $input_id,
801
-                    $input_class,
802
-                    [],
803
-                    $required,
804
-                    $required_text,
805
-                    $label_class,
806
-                    $disabled,
807
-                    $system_ID,
808
-                    $use_html_entities
809
-                );
810
-
811
-            case 'DROPDOWN':
812
-                return EEH_Form_Fields::select(
813
-                    $display_text,
814
-                    $answer,
815
-                    $options,
816
-                    $input_name,
817
-                    $input_id,
818
-                    $input_class,
819
-                    $required,
820
-                    $required_text,
821
-                    $label_class,
822
-                    $disabled,
823
-                    $system_ID,
824
-                    $use_html_entities,
825
-                    true
826
-                );
827
-
828
-
829
-            case 'RADIO_BTN':
830
-                return EEH_Form_Fields::radio(
831
-                    $display_text,
832
-                    $answer,
833
-                    $options,
834
-                    $input_name,
835
-                    $input_id,
836
-                    $input_class,
837
-                    $required,
838
-                    $required_text,
839
-                    $label_class,
840
-                    $disabled,
841
-                    $system_ID,
842
-                    $use_html_entities,
843
-                    $label_b4,
844
-                    $use_desc_4_label
845
-                );
846
-
847
-            case 'CHECKBOX':
848
-                return EEH_Form_Fields::checkbox(
849
-                    $display_text,
850
-                    $answer,
851
-                    $options,
852
-                    $input_name,
853
-                    $input_id,
854
-                    $input_class,
855
-                    $required,
856
-                    $required_text,
857
-                    $label_class,
858
-                    $disabled,
859
-                    $label_b4,
860
-                    $system_ID,
861
-                    $use_html_entities
862
-                );
863
-
864
-            case 'DATE':
865
-                return EEH_Form_Fields::datepicker(
866
-                    $display_text,
867
-                    $answer,
868
-                    $input_name,
869
-                    $input_id,
870
-                    $input_class,
871
-                    $required,
872
-                    $required_text,
873
-                    $label_class,
874
-                    $disabled,
875
-                    $system_ID,
876
-                    $use_html_entities
877
-                );
878
-
879
-            case 'TEXT':
880
-            default:
881
-                return EEH_Form_Fields::text(
882
-                    $display_text,
883
-                    $answer,
884
-                    $input_name,
885
-                    $input_id,
886
-                    $input_class,
887
-                    $required,
888
-                    $required_text,
889
-                    $label_class,
890
-                    $disabled,
891
-                    $system_ID,
892
-                    $use_html_entities
893
-                );
894
-        }
895
-    }
896
-
897
-
898
-    /**
899
-     * generates HTML for a form text input
900
-     *
901
-     * @param string $question    label content
902
-     * @param string $answer      form input value attribute
903
-     * @param string $name        form input name attribute
904
-     * @param string $id          form input css id attribute
905
-     * @param string $class       form input css class attribute
906
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
907
-     *                            required 'class', and required 'msg' attribute
908
-     * @param string $label_class css class attribute for the label
909
-     * @param string $disabled    disabled="disabled" or null
910
-     * @return string HTML
911
-     */
912
-    public static function text(
913
-        $question = false,
914
-        $answer = null,
915
-        $name = false,
916
-        $id = '',
917
-        $class = '',
918
-        $required = false,
919
-        $required_text = '',
920
-        $label_class = '',
921
-        $disabled = false,
922
-        $system_ID = false,
923
-        $use_html_entities = true
924
-    ) {
925
-        // need these
926
-        if (! $question || ! $name) {
927
-            return null;
928
-        }
929
-        // prep the answer
930
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
931
-        // prep the required array
932
-        $required = self::prep_required($required);
933
-        // set disabled tag
934
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
935
-        // ya gots ta have style man!!!
936
-        $txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
937
-        $class     = empty($class) ? $txt_class : $class;
938
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
939
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
940
-
941
-        $label_html =
942
-            $required_text
943
-            . "\n\t\t\t"
944
-            . '<label for="' . $name . '" class="' . $label_class . '">'
945
-            . self::prep_question($question)
946
-            . $required['label']
947
-            . '</label><br/>';
948
-        // filter label but ensure required text comes before it
949
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
950
-
951
-        $input_html =
952
-            "\n\t\t\t"
953
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
954
-            . 'class="' . $class . ' ' . $required['class'] . '" value="' . esc_attr($answer) . '"  '
955
-            . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
956
-
957
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
958
-        return $label_html . $input_html;
959
-    }
960
-
961
-
962
-    /**
963
-     * generates HTML for a form textarea
964
-     *
965
-     * @param string $question    label content
966
-     * @param string $answer      form input value attribute
967
-     * @param string $name        form input name attribute
968
-     * @param string $id          form input css id attribute
969
-     * @param string $class       form input css class attribute
970
-     * @param array  $dimensions  array of form input rows and cols attributes : array( 'rows' => 3, 'cols' => 40 )
971
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
972
-     *                            required 'class', and required 'msg' attribute
973
-     * @param string $label_class css class attribute for the label
974
-     * @param string $disabled    disabled="disabled" or null
975
-     * @return string HTML
976
-     */
977
-    public static function textarea(
978
-        $question = false,
979
-        $answer = null,
980
-        $name = false,
981
-        $id = '',
982
-        $class = '',
983
-        $dimensions = false,
984
-        $required = false,
985
-        $required_text = '',
986
-        $label_class = '',
987
-        $disabled = false,
988
-        $system_ID = false,
989
-        $use_html_entities = true
990
-    ) {
991
-        // need these
992
-        if (! $question || ! $name) {
993
-            return null;
994
-        }
995
-        // prep the answer
996
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
997
-        // prep the required array
998
-        $required = self::prep_required($required);
999
-        // make sure $dimensions is an array
1000
-        $dimensions = is_array($dimensions) ? $dimensions : [];
1001
-        // and set some defaults
1002
-        $dimensions = array_merge(['rows' => 3, 'cols' => 40], $dimensions);
1003
-        // set disabled tag
1004
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1005
-        // ya gots ta have style man!!!
1006
-        $txt_class = is_admin() ? 'regular-text' : 'espresso-textarea-inp';
1007
-        $class     = empty($class) ? $txt_class : $class;
1008
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1009
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1010
-
1011
-        $label_html =
1012
-            $required_text
1013
-            . "\n\t\t\t"
1014
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1015
-            . self::prep_question($question)
1016
-            . $required['label']
1017
-            . '</label><br/>';
1018
-        // filter label but ensure required text comes before it
1019
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1020
-
1021
-        $input_html =
1022
-            "\n\t\t\t"
1023
-            . '<textarea name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1024
-            . 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1025
-            . 'title="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1026
-            . esc_textarea($answer)
1027
-            . '</textarea>';
1028
-
1029
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1030
-        return $label_html . $input_html;
1031
-    }
1032
-
1033
-
1034
-    /**
1035
-     * generates HTML for a form select input
1036
-     *
1037
-     * @param string $question    label content
1038
-     * @param string $answer      form input value attribute
1039
-     * @param array  $options     array of answer options where array key = option value and array value = option
1040
-     *                            display text
1041
-     * @param string $name        form input name attribute
1042
-     * @param string $id          form input css id attribute
1043
-     * @param string $class       form input css class attribute
1044
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1045
-     *                            required 'class', and required 'msg' attribute
1046
-     * @param string $label_class css class attribute for the label
1047
-     * @param string $disabled    disabled="disabled" or null
1048
-     * @return string HTML
1049
-     */
1050
-    public static function select(
1051
-        $question = false,
1052
-        $answer = null,
1053
-        $options = false,
1054
-        $name = false,
1055
-        $id = '',
1056
-        $class = '',
1057
-        $required = false,
1058
-        $required_text = '',
1059
-        $label_class = '',
1060
-        $disabled = false,
1061
-        $system_ID = false,
1062
-        $use_html_entities = true,
1063
-        $add_please_select_option = false
1064
-    ) {
1065
-
1066
-        // need these
1067
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1068
-            return null;
1069
-        }
1070
-        // prep the answer
1071
-        $answer =
1072
-            is_array($answer)
1073
-                ? self::prep_answer(array_shift($answer), $use_html_entities)
1074
-                : self::prep_answer(
1075
-                    $answer,
1076
-                    $use_html_entities
1077
-                );
1078
-        // prep the required array
1079
-        $required = self::prep_required($required);
1080
-        // set disabled tag
1081
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1082
-        // ya gots ta have style man!!!
1083
-        $txt_class = is_admin() ? 'wide' : 'espresso-select-inp';
1084
-        $class     = empty($class) ? $txt_class : $class;
1085
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1086
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1087
-
1088
-        $label_html =
1089
-            $required_text
1090
-            . "\n\t\t\t"
1091
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1092
-            . self::prep_question($question)
1093
-            . $required['label']
1094
-            . '</label><br/>';
1095
-        // filter label but ensure required text comes before it
1096
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1097
-
1098
-        $input_html =
1099
-            "\n\t\t\t"
1100
-            . '<select name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1101
-            . 'title="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1102
-        // recursively count array elements, to determine total number of options
1103
-        $only_option = count($options, 1) == 1;
1104
-        if (! $only_option) {
1105
-            // if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1106
-            $selected   = $answer === null ? ' selected' : '';
1107
-            $input_html .= $add_please_select_option
1108
-                ? "\n\t\t\t\t"
1109
-                  . '<option value=""' . $selected . '>'
1110
-                  . esc_html__(' - please select - ', 'event_espresso')
1111
-                  . '</option>'
1112
-                : '';
1113
-        }
1114
-        foreach ($options as $key => $value) {
1115
-            // if value is an array, then create option groups, else create regular ol' options
1116
-            $input_html .= is_array($value)
1117
-                ? self::_generate_select_option_group(
1118
-                    $key,
1119
-                    $value,
1120
-                    $answer,
1121
-                    $use_html_entities
1122
-                )
1123
-                : self::_generate_select_option(
1124
-                    $value->value(),
1125
-                    $value->desc(),
1126
-                    $answer,
1127
-                    $only_option,
1128
-                    $use_html_entities
1129
-                );
1130
-        }
1131
-
1132
-        $input_html .= "\n\t\t\t" . '</select>';
1133
-
1134
-        $input_html =
1135
-            apply_filters(
1136
-                'FHEE__EEH_Form_Fields__select__before_end_wrapper',
1137
-                $input_html,
1138
-                $question,
1139
-                $answer,
1140
-                $name,
1141
-                $id,
1142
-                $class,
1143
-                $system_ID
1144
-            );
1145
-
1146
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1147
-        return $label_html . $input_html;
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     *  _generate_select_option_group
1153
-     *
1154
-     *  if  $value for a select box is an array, then the key will be used as the optgroup label
1155
-     *  and the value array will be looped thru and the elements sent to _generate_select_option
1156
-     *
1157
-     * @param mixed   $opt_group
1158
-     * @param mixed   $QSOs
1159
-     * @param mixed   $answer
1160
-     * @param boolean $use_html_entities
1161
-     * @return string
1162
-     */
1163
-    private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1164
-    {
1165
-        $html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1166
-        foreach ($QSOs as $QSO) {
1167
-            $html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1168
-        }
1169
-        $html .= "\n\t\t\t\t" . '</optgroup>';
1170
-        return $html;
1171
-    }
1172
-
1173
-
1174
-    /**
1175
-     *  _generate_select_option
1176
-     *
1177
-     * @param mixed   $key
1178
-     * @param mixed   $value
1179
-     * @param mixed   $answer
1180
-     * @param int     $only_option
1181
-     * @param boolean $use_html_entities
1182
-     * @return string
1183
-     */
1184
-    private static function _generate_select_option(
1185
-        $key,
1186
-        $value,
1187
-        $answer,
1188
-        $only_option = false,
1189
-        $use_html_entities = true
1190
-    ) {
1191
-        $key      = self::prep_answer($key, $use_html_entities);
1192
-        $value    = self::prep_answer($value, $use_html_entities);
1193
-        $value    = ! empty($value) ? $value : $key;
1194
-        $selected = ($answer == $key || $only_option) ? 'selected' : '';
1195
-        return "\n\t\t\t\t"
1196
-               . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1197
-               . $value
1198
-               . '&nbsp;&nbsp;&nbsp;</option>';
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * generates HTML for form radio button inputs
1204
-     *
1205
-     * @param bool|string $question    label content
1206
-     * @param string      $answer      form input value attribute
1207
-     * @param array|bool  $options     array of answer options where array key = option value and array value = option
1208
-     *                                 display text
1209
-     * @param bool|string $name        form input name attribute
1210
-     * @param string      $id          form input css id attribute
1211
-     * @param string      $class       form input css class attribute
1212
-     * @param array|bool  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1213
-     *                                 required 'class', and required 'msg' attribute
1214
-     * @param string      $required_text
1215
-     * @param string      $label_class css class attribute for the label
1216
-     * @param bool|string $disabled    disabled="disabled" or null
1217
-     * @param bool        $system_ID
1218
-     * @param bool        $use_html_entities
1219
-     * @param bool        $label_b4
1220
-     * @param bool        $use_desc_4_label
1221
-     * @return string HTML
1222
-     */
1223
-    public static function radio(
1224
-        $question = false,
1225
-        $answer = null,
1226
-        $options = false,
1227
-        $name = false,
1228
-        $id = '',
1229
-        $class = '',
1230
-        $required = false,
1231
-        $required_text = '',
1232
-        $label_class = '',
1233
-        $disabled = false,
1234
-        $system_ID = false,
1235
-        $use_html_entities = true,
1236
-        $label_b4 = false,
1237
-        $use_desc_4_label = false
1238
-    ) {
1239
-        // need these
1240
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1241
-            return null;
1242
-        }
1243
-        // prep the answer
1244
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1245
-        // prep the required array
1246
-        $required = self::prep_required($required);
1247
-        // set disabled tag
1248
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1249
-        // ya gots ta have style man!!!
1250
-        $radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1251
-        $class       = ! empty($class) ? $class : 'espresso-radio-btn-inp';
1252
-        $extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1253
-
1254
-        $label_html =
1255
-            $required_text
1256
-            . "\n\t\t\t"
1257
-            . '<label class="' . $label_class . '">'
1258
-            . self::prep_question($question)
1259
-            . $required['label']
1260
-            . '</label> ';
1261
-        // filter label but ensure required text comes before it
1262
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1263
-
1264
-        $input_html =
1265
-            "\n\t\t\t"
1266
-            . '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $label_class . ' ' . $class . '-ul">';
1267
-
1268
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1269
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1270
-
1271
-        foreach ($options as $OPT) {
1272
-            if ($OPT instanceof EE_Question_Option) {
1273
-                $value   = self::prep_option_value($OPT->value());
1274
-                $label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1275
-                $size    = $use_desc_4_label
1276
-                    ? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1277
-                    : self::get_label_size_class($OPT->value());
1278
-                $desc    = $OPT->desc();// no self::prep_answer
1279
-                $answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1280
-                $checked = (string) $value == (string) $answer ? ' checked' : '';
1281
-                $opt     = '-' . sanitize_key($value);
1282
-
1283
-                $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1284
-                $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1285
-                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>' : '';
1286
-                $input_html .= "\n\t\t\t\t\t\t"
1287
-                               . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1288
-                               . 'class="' . $class . '" value="' . $value . '" '
1289
-                               . 'title="' . esc_attr($required['msg']) . '" ' . $disabled
1290
-                               . $checked . ' ' . $extra . '/>';
1291
-                $input_html .= ! $label_b4
1292
-                    ? "\n\t\t\t\t\t\t"
1293
-                      . '<span class="espresso-radio-btn-desc">'
1294
-                      . $label
1295
-                      . '</span>'
1296
-                    : '';
1297
-                $input_html .= "\n\t\t\t\t\t" . '</label>';
1298
-                $input_html .= $use_desc_4_label
1299
-                    ? ''
1300
-                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1301
-                $input_html .= "\n\t\t\t\t" . '</li>';
1302
-            }
1303
-        }
1304
-
1305
-        $input_html .= "\n\t\t\t" . '</ul>';
1306
-
1307
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1308
-        return $label_html . $input_html;
1309
-    }
1310
-
1311
-
1312
-    /**
1313
-     * generates HTML for form checkbox inputs
1314
-     *
1315
-     * @param string $question    label content
1316
-     * @param string $answer      form input value attribute
1317
-     * @param array  $options     array of options where array key = option value and array value = option display text
1318
-     * @param string $name        form input name attribute
1319
-     * @param string $id          form input css id attribute
1320
-     * @param string $class       form input css class attribute
1321
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1322
-     *                            required 'class', and required 'msg' attribute
1323
-     * @param string $label_class css class attribute for the label
1324
-     * @param string $disabled    disabled="disabled" or null
1325
-     * @return string HTML
1326
-     */
1327
-    public static function checkbox(
1328
-        $question = false,
1329
-        $answer = null,
1330
-        $options = false,
1331
-        $name = false,
1332
-        $id = '',
1333
-        $class = '',
1334
-        $required = false,
1335
-        $required_text = '',
1336
-        $label_class = '',
1337
-        $disabled = false,
1338
-        $label_b4 = false,
1339
-        $system_ID = false,
1340
-        $use_html_entities = true
1341
-    ) {
1342
-        // need these
1343
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1344
-            return null;
1345
-        }
1346
-        $answer = maybe_unserialize($answer);
1347
-
1348
-        // prep the answer(s)
1349
-        $answer = is_array($answer) ? $answer : [sanitize_key($answer) => $answer];
1350
-
1351
-        foreach ($answer as $key => $value) {
1352
-            $key            = self::prep_option_value($key);
1353
-            $answer[ $key ] = self::prep_answer($value, $use_html_entities);
1354
-        }
1355
-
1356
-        // prep the required array
1357
-        $required = self::prep_required($required);
1358
-        // set disabled tag
1359
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1360
-        // ya gots ta have style man!!!
1361
-        $radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1362
-        $class       = empty($class) ? 'espresso-radio-btn-inp' : $class;
1363
-        $extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1364
-
1365
-        $label_html =
1366
-            $required_text
1367
-            . "\n\t\t\t"
1368
-            . '<label class="' . $label_class . '">'
1369
-            . self::prep_question($question)
1370
-            . $required['label']
1371
-            . '</label> ';
1372
-        // filter label but ensure required text comes before it
1373
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1374
-
1375
-        $input_html =
1376
-            "\n\t\t\t"
1377
-            . '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $label_class . ' ' . $class . '-ul">';
1378
-
1379
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1380
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1381
-
1382
-        foreach ($options as $OPT) {
1383
-            $value = $OPT->value();// self::prep_option_value( $OPT->value() );
1384
-            $size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1385
-            $text  = self::prep_answer($OPT->value());
1386
-            $desc  = $OPT->desc();
1387
-            $opt   = '-' . sanitize_key($value);
1388
-
1389
-            $checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1390
-
1391
-            $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1392
-            $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1393
-            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1394
-            $input_html .= "\n\t\t\t\t\t\t"
1395
-                           . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1396
-                           . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1397
-                           . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1398
-            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1399
-            $input_html .= "\n\t\t\t\t\t" . '</label>';
1400
-            if (! empty($desc) && $desc != $text) {
1401
-                $input_html .= "\n\t\t\t\t\t"
1402
-                               . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1403
-                               . $desc
1404
-                               . '</div>';
1405
-            }
1406
-            $input_html .= "\n\t\t\t\t" . '</li>';
1407
-        }
1408
-
1409
-        $input_html .= "\n\t\t\t" . '</ul>';
1410
-
1411
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1412
-        return $label_html . $input_html;
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * generates HTML for a form datepicker input
1418
-     *
1419
-     * @param string $question    label content
1420
-     * @param string $answer      form input value attribute
1421
-     * @param string $name        form input name attribute
1422
-     * @param string $id          form input css id attribute
1423
-     * @param string $class       form input css class attribute
1424
-     * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1425
-     *                            required 'class', and required 'msg' attribute
1426
-     * @param string $label_class css class attribute for the label
1427
-     * @param string $disabled    disabled="disabled" or null
1428
-     * @return string HTML
1429
-     */
1430
-    public static function datepicker(
1431
-        $question = false,
1432
-        $answer = null,
1433
-        $name = false,
1434
-        $id = '',
1435
-        $class = '',
1436
-        $required = false,
1437
-        $required_text = '',
1438
-        $label_class = '',
1439
-        $disabled = false,
1440
-        $system_ID = false,
1441
-        $use_html_entities = true
1442
-    ) {
1443
-        // need these
1444
-        if (! $question || ! $name) {
1445
-            return null;
1446
-        }
1447
-        // prep the answer
1448
-        $answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1449
-        // prep the required array
1450
-        $required = self::prep_required($required);
1451
-        // set disabled tag
1452
-        $disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1453
-        // ya gots ta have style man!!!
1454
-        $txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1455
-        $class     = empty($class) ? $txt_class : $class;
1456
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1457
-        $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1458
-
1459
-        $label_html =
1460
-            $required_text
1461
-            . "\n\t\t\t"
1462
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1463
-            . self::prep_question($question)
1464
-            . $required['label']
1465
-            . '</label><br/>';
1466
-        // filter label but ensure required text comes before it
1467
-        $label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1468
-
1469
-        $input_html =
1470
-            "\n\t\t\t"
1471
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
1472
-            . 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1473
-            . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1474
-
1475
-        // enqueue scripts
1476
-        wp_register_style(
1477
-            'espresso-ui-theme',
1478
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1479
-            [],
1480
-            EVENT_ESPRESSO_VERSION
1481
-        );
1482
-        wp_enqueue_style('espresso-ui-theme');
1483
-        wp_enqueue_script('jquery-ui-datepicker');
1484
-
1485
-        $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1486
-        return $label_html . $input_html;
1487
-    }
1488
-
1489
-
1490
-    /**
1491
-     *  remove_label_keep_required_msg
1492
-     *  this will strip out a form input's label HTML while keeping the required text HTML that MUST be before the label
1493
-     *
1494
-     * @access public
1495
-     * @return     string
1496
-     */
1497
-    public static function remove_label_keep_required_msg($label_html, $required_text)
1498
-    {
1499
-        return $required_text;
1500
-    }
1501
-
1502
-
1503
-    /**
1504
-     * Simply returns the HTML for a hidden input of the given name and value.
1505
-     *
1506
-     * @param string $name
1507
-     * @param string $value
1508
-     * @return string HTML
1509
-     */
1510
-    public static function hidden_input($name, $value, $id = '')
1511
-    {
1512
-        $id = ! empty($id) ? $id : $name;
1513
-        return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1514
-    }
1515
-
1516
-
1517
-    /**
1518
-     * prep_question
1519
-     *
1520
-     * @param string $question
1521
-     * @return string
1522
-     */
1523
-    public static function prep_question($question)
1524
-    {
1525
-        return $question;
1526
-    }
1527
-
1528
-
1529
-    /**
1530
-     *  prep_answer
1531
-     *
1532
-     * @param mixed $answer
1533
-     * @return string
1534
-     */
1535
-    public static function prep_answer($answer, $use_html_entities = true)
1536
-    {
1537
-        // make sure we convert bools first.  Otherwise (bool) false becomes an empty string which is NOT desired,
1538
-        // we want "0".
1539
-        if (is_bool($answer)) {
1540
-            $answer = $answer ? 1 : 0;
1541
-        }
1542
-        $answer = trim(stripslashes(str_replace('&#039;', "'", $answer)));
1543
-        return $use_html_entities ? htmlentities($answer, ENT_QUOTES, 'UTF-8') : $answer;
1544
-    }
1545
-
1546
-
1547
-    /**
1548
-     *  prep_answer_options
1549
-     *
1550
-     * @param array $QSOs array of EE_Question_Option objects
1551
-     * @return array
1552
-     */
1553
-    public static function prep_answer_options($QSOs = [])
1554
-    {
1555
-        $prepped_answer_options = [];
1556
-        if (is_array($QSOs) && ! empty($QSOs)) {
1557
-            foreach ($QSOs as $key => $QSO) {
1558
-                if (! $QSO instanceof EE_Question_Option) {
1559
-                    $QSO = EE_Question_Option::new_instance(
1560
-                        [
1561
-                            'QSO_value' => is_array($QSO) && isset($QSO['id'])
1562
-                                ? (string) $QSO['id']
1563
-                                : (string) $key,
1564
-                            'QSO_desc'  => is_array($QSO) && isset($QSO['text'])
1565
-                                ? (string) $QSO['text']
1566
-                                : (string) $QSO,
1567
-                        ]
1568
-                    );
1569
-                }
1570
-                if ($QSO->opt_group()) {
1571
-                    $prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1572
-                } else {
1573
-                    $prepped_answer_options[] = $QSO;
1574
-                }
1575
-            }
1576
-        }
1577
-        //      d( $prepped_answer_options );
1578
-        return $prepped_answer_options;
1579
-    }
1580
-
1581
-
1582
-    /**
1583
-     *  prep_option_value
1584
-     *
1585
-     * @param string $option_value
1586
-     * @return string
1587
-     */
1588
-    public static function prep_option_value($option_value)
1589
-    {
1590
-        return esc_attr(trim(stripslashes($option_value)));
1591
-    }
1592
-
1593
-
1594
-    /**
1595
-     *  prep_required
1596
-     *
1597
-     * @param string|array $required
1598
-     * @return array
1599
-     */
1600
-    public static function prep_required($required = [])
1601
-    {
1602
-        // make sure required is an array
1603
-        $required = is_array($required) ? $required : [];
1604
-        // and set some defaults
1605
-        return array_merge(['label' => '', 'class' => '', 'msg' => ''], $required);
1606
-    }
1607
-
1608
-
1609
-    /**
1610
-     *  get_label_size_class
1611
-     *
1612
-     * @param string $value
1613
-     * @return string
1614
-     */
1615
-    public static function get_label_size_class($value = false)
1616
-    {
1617
-        if ($value === false || $value === '') {
1618
-            return ' class="medium-lbl"';
1619
-        }
1620
-        // determine length of option value
1621
-        $val_size = strlen($value);
1622
-        switch ($val_size) {
1623
-            case $val_size < 3:
1624
-                $size = ' class="nano-lbl"';
1625
-                break;
1626
-            case $val_size < 6:
1627
-                $size = ' class="micro-lbl"';
1628
-                break;
1629
-            case $val_size < 12:
1630
-                $size = ' class="tiny-lbl"';
1631
-                break;
1632
-            case $val_size < 25:
1633
-                $size = ' class="small-lbl"';
1634
-                break;
1635
-            case $val_size > 100:
1636
-                $size = ' class="big-lbl"';
1637
-                break;
1638
-            default:
1639
-                $size = ' class="medium-lbl"';
1640
-                break;
1641
-        }
1642
-        return $size;
1643
-    }
1644
-
1645
-
1646
-    /**
1647
-     *  _load_system_dropdowns
1648
-     *
1649
-     * @param EE_Question_Form_Input $QFI
1650
-     * @return array
1651
-     * @throws EE_Error
1652
-     * @throws ReflectionException
1653
-     */
1654
-    private static function _load_system_dropdowns($QFI)
1655
-    {
1656
-        $QST_system = $QFI->get('QST_system');
1657
-        switch ($QST_system) {
1658
-            case 'state':
1659
-                $QFI = self::generate_state_dropdown($QFI);
1660
-                break;
1661
-            case 'country':
1662
-                $QFI = self::generate_country_dropdown($QFI);
1663
-                break;
1664
-            case 'admin-state':
1665
-                $QFI = self::generate_state_dropdown($QFI, true);
1666
-                break;
1667
-            case 'admin-country':
1668
-                $QFI = self::generate_country_dropdown($QFI, true);
1669
-                break;
1670
-        }
1671
-        return $QFI;
1672
-    }
1673
-
1674
-
1675
-    /**
1676
-     * This preps dropdowns that are specialized.
1677
-     *
1678
-     * @param EE_Question_Form_Input $QFI
1679
-     *
1680
-     * @return EE_Question_Form_Input
1681
-     * @throws EE_Error
1682
-     * @throws ReflectionException
1683
-     * @since  4.6.0
1684
-     */
1685
-    protected static function _load_specialized_dropdowns($QFI)
1686
-    {
1687
-        switch ($QFI->get('QST_type')) {
1688
-            case 'STATE':
1689
-                $QFI = self::generate_state_dropdown($QFI);
1690
-                break;
1691
-            case 'COUNTRY':
1692
-                $QFI = self::generate_country_dropdown($QFI);
1693
-                break;
1694
-        }
1695
-        return $QFI;
1696
-    }
1697
-
1698
-
1699
-    /**
1700
-     *    generate_state_dropdown
1701
-     *
1702
-     * @param EE_Question_Form_Input $QST
1703
-     * @param bool                   $get_all
1704
-     * @return EE_Question_Form_Input
1705
-     * @throws EE_Error
1706
-     * @throws ReflectionException
1707
-     */
1708
-    public static function generate_state_dropdown($QST, $get_all = false)
1709
-    {
1710
-        $states = $get_all
1711
-            ? EEM_State::instance()->get_all_states()
1712
-            : EEM_State::instance()->get_all_states_of_active_countries();
1713
-        if ($states && count($states) != count($QST->options())) {
1714
-            $QST->set('QST_type', 'DROPDOWN');
1715
-            // if multiple countries, we'll create option groups within the dropdown
1716
-            foreach ($states as $state) {
1717
-                if ($state instanceof EE_State) {
1718
-                    $QSO = EE_Question_Option::new_instance(
1719
-                        [
1720
-                            'QSO_value'   => $state->ID(),
1721
-                            'QSO_desc'    => $state->name(),
1722
-                            'QST_ID'      => $QST->get('QST_ID'),
1723
-                            'QSO_deleted' => false,
1724
-                        ]
1725
-                    );
1726
-                    // set option group
1727
-                    $QSO->set_opt_group($state->country()->name());
1728
-                    // add option to question
1729
-                    $QST->add_temp_option($QSO);
1730
-                }
1731
-            }
1732
-        }
1733
-        return $QST;
1734
-    }
1735
-
1736
-
1737
-    /**
1738
-     *    generate_country_dropdown
1739
-     *
1740
-     * @param      $QST
1741
-     * @param bool $get_all
1742
-     * @return array
1743
-     * @throws EE_Error
1744
-     * @throws ReflectionException
1745
-     * @internal param array $question
1746
-     */
1747
-    public static function generate_country_dropdown($QST, $get_all = false)
1748
-    {
1749
-        $countries = $get_all
1750
-            ? EEM_Country::instance()->get_all_countries()
1751
-            : EEM_Country::instance()->get_all_active_countries();
1752
-        if ($countries && count($countries) != count($QST->options())) {
1753
-            $QST->set('QST_type', 'DROPDOWN');
1754
-            // now add countries
1755
-            foreach ($countries as $country) {
1756
-                if ($country instanceof EE_Country) {
1757
-                    $QSO = EE_Question_Option::new_instance(
1758
-                        [
1759
-                            'QSO_value'   => $country->ID(),
1760
-                            'QSO_desc'    => $country->name(),
1761
-                            'QST_ID'      => $QST->get('QST_ID'),
1762
-                            'QSO_deleted' => false,
1763
-                        ]
1764
-                    );
1765
-                    $QST->add_temp_option($QSO);
1766
-                }
1767
-            }
1768
-        }
1769
-        return $QST;
1770
-    }
1771
-
1772
-
1773
-    /**
1774
-     *  generates options for a month dropdown selector with numbers from 01 to 12
1775
-     *
1776
-     * @return array()
1777
-     */
1778
-    public static function two_digit_months_dropdown_options()
1779
-    {
1780
-        $options = [];
1781
-        for ($x = 1; $x <= 12; $x++) {
1782
-            $mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1783
-            $options[ $mm ] = $mm;
1784
-        }
1785
-        return EEH_Form_Fields::prep_answer_options($options);
1786
-    }
1787
-
1788
-
1789
-    /**
1790
-     *  generates a year dropdown selector with numbers for the next ten years
1791
-     *
1792
-     * @return array
1793
-     */
1794
-    public static function next_decade_two_digit_year_dropdown_options()
1795
-    {
1796
-        $options      = [];
1797
-        $current_year = date('y');
1798
-        $next_decade  = $current_year + 10;
1799
-        for ($x = $current_year; $x <= $next_decade; $x++) {
1800
-            $yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1801
-            $options[ $yy ] = $yy;
1802
-        }
1803
-        return EEH_Form_Fields::prep_answer_options($options);
1804
-    }
1805
-
1806
-
1807
-    /**
1808
-     * generates a month/year dropdown selector for all registrations matching the given criteria.  Typically used for
1809
-     * list table filter.
1810
-     *
1811
-     * @param string  $cur_date     any currently selected date can be entered here.
1812
-     * @param string  $status       Registration status
1813
-     * @param integer $evt_category Event Category ID if the Event Category filter is selected
1814
-     * @return string                html
1815
-     * @throws EE_Error
1816
-     */
1817
-    public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1818
-    {
1819
-        $_where = [];
1820
-        if (! empty($status)) {
1821
-            $_where['STS_ID'] = $status;
1822
-        }
1823
-
1824
-        if ($evt_category > 0) {
1825
-            $_where['Event.Term_Taxonomy.term_id'] = $evt_category;
1826
-        }
1827
-
1828
-        $regdtts = EEM_Registration::instance()->get_reg_months_and_years($_where);
1829
-
1830
-        // setup vals for select input helper
1831
-        $options = [
1832
-            0 => [
1833
-                'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1834
-                'id'   => '',
1835
-            ],
1836
-        ];
1837
-
1838
-        foreach ($regdtts as $regdtt) {
1839
-            $date      = $regdtt->reg_month . ' ' . $regdtt->reg_year;
1840
-            $options[] = [
1841
-                'text' => $date,
1842
-                'id'   => $date,
1843
-            ];
1844
-        }
1845
-
1846
-        return self::select_input('month_range', $options, $cur_date, '', 'wide');
1847
-    }
1848
-
1849
-
1850
-    /**
1851
-     * generates a month/year dropdown selector for all events matching the given criteria
1852
-     * Typically used for list table filter
1853
-     *
1854
-     * @param string $cur_date          any currently selected date can be entered here.
1855
-     * @param string $status            "view" (i.e. all, today, month, draft)
1856
-     * @param int    $evt_category      category event belongs to
1857
-     * @param string $evt_active_status "upcoming", "expired", "active", or "inactive"
1858
-     * @return string                    html
1859
-     * @throws EE_Error
1860
-     */
1861
-    public static function generate_event_months_dropdown(
1862
-        $cur_date = '',
1863
-        $status = null,
1864
-        $evt_category = null,
1865
-        $evt_active_status = null
1866
-    ) {
1867
-        // determine what post_status our condition will have for the query.
1868
-        // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
1869
-        switch ($status) {
1870
-            case 'month':
1871
-            case 'today':
1872
-            case null:
1873
-            case 'all':
1874
-                $where['Event.status'] = ['NOT IN', ['trash']];
1875
-                break;
1876
-            case 'draft':
1877
-                $where['Event.status'] = ['IN', ['draft', 'auto-draft']];
1878
-                break;
1879
-            default:
1880
-                $where['Event.status'] = $status;
1881
-        }
1882
-
1883
-        // phpcs:enable
1884
-
1885
-        // categories?
1886
-
1887
-
1888
-        if (! empty($evt_category)) {
1889
-            $where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1890
-            $where['Event.Term_Taxonomy.term_id']  = $evt_category;
1891
-        }
1892
-
1893
-
1894
-        //      $where['DTT_is_primary'] = 1;
1895
-
1896
-        $DTTS = EEM_Datetime::instance()->get_dtt_months_and_years($where, $evt_active_status);
1897
-
1898
-        // let's setup vals for select input helper
1899
-        $options = [
1900
-            0 => [
1901
-                'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1902
-                'id'   => "",
1903
-            ],
1904
-        ];
1905
-
1906
-
1907
-        // translate month and date
1908
-        global $wp_locale;
1909
-
1910
-        foreach ($DTTS as $DTT) {
1911
-            $localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
1912
-            $id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
1913
-            $options[]      = [
1914
-                'text' => $localized_date,
1915
-                'id'   => $id,
1916
-            ];
1917
-        }
1918
-
1919
-
1920
-        return self::select_input('month_range', $options, $cur_date, '', 'wide');
1921
-    }
1922
-
1923
-
1924
-    /**
1925
-     * generates the dropdown selector for event categories
1926
-     * typically used as a filter on list tables.
1927
-     *
1928
-     * @param integer $current_cat currently selected category
1929
-     * @return string               html for dropdown
1930
-     * @throws EE_Error
1931
-     * @throws ReflectionException
1932
-     */
1933
-    public static function generate_event_category_dropdown($current_cat = -1)
1934
-    {
1935
-        $categories = EEM_Term::instance()->get_all_ee_categories(true);
1936
-        $options    = [
1937
-            '0' => [
1938
-                'text' => esc_html__('All Categories', 'event_espresso'),
1939
-                'id'   => -1,
1940
-            ],
1941
-        ];
1942
-
1943
-        // setup categories for dropdown
1944
-        foreach ($categories as $category) {
1945
-            $options[] = [
1946
-                'text' => $category->get('name'),
1947
-                'id'   => $category->ID(),
1948
-            ];
1949
-        }
1950
-
1951
-        return self::select_input('EVT_CAT', $options, $current_cat);
1952
-    }
1953
-
1954
-
1955
-    /**
1956
-     *    generate a submit button with or without it's own microform
1957
-     *    this is the only way to create buttons that are compatible across all themes
1958
-     *
1959
-     * @access    public
1960
-     * @param string      $url              - the form action
1961
-     * @param string      $ID               - some kind of unique ID, appended with "-sbmt" for the input and "-frm"
1962
-     *                                      for the form
1963
-     * @param string      $class            - css classes (separated by spaces if more than one)
1964
-     * @param string      $text             - what appears on the button
1965
-     * @param string      $nonce_action     - if using nonces
1966
-     * @param bool|string $input_only       - whether to print form header and footer. TRUE returns the input without
1967
-     *                                      the form
1968
-     * @param string      $extra_attributes - any extra attributes that need to be attached to the form input
1969
-     * @return    string
1970
-     */
1971
-    public static function submit_button(
1972
-        $url = '',
1973
-        $ID = '',
1974
-        $class = '',
1975
-        $text = '',
1976
-        $nonce_action = '',
1977
-        $input_only = false,
1978
-        $extra_attributes = ''
1979
-    ) {
1980
-        $btn = '';
1981
-        if (empty($url) || empty($ID)) {
1982
-            return $btn;
1983
-        }
1984
-        $text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
1985
-        $btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
1986
-                 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
1987
-        if (! $input_only) {
1988
-            $btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
1989
-            $btn_frm .= ! empty($nonce_action)
1990
-                ? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
1991
-                : '';
1992
-            $btn_frm .= $btn;
1993
-            $btn_frm .= '</form>';
1994
-            $btn     = $btn_frm;
1995
-            unset($btn_frm);
1996
-        }
1997
-        return $btn;
1998
-    }
462
+	}
463
+
464
+
465
+	/**
466
+	 * @param string $class
467
+	 * @param string $id
468
+	 * @param string $name
469
+	 * @param int    $rows
470
+	 * @param int    $tab_index
471
+	 * @param string $value
472
+	 * @param array  $wp_editor_args
473
+	 * @return false|string
474
+	 * @since   4.10.14.p
475
+	 */
476
+	private static function adminWpEditor($class, $id, $name, $rows, $tab_index, $value, $wp_editor_args = [])
477
+	{
478
+		$editor_settings = $wp_editor_args + [
479
+				'textarea_name' => esc_attr($name),
480
+				'textarea_rows' => absint($rows),
481
+				'editor_class'  => esc_attr($class),
482
+				'tabindex'      => absint($tab_index),
483
+			];
484
+		ob_start();
485
+		wp_editor($value, esc_attr($id), $editor_settings);
486
+		return ob_get_clean();
487
+	}
488
+
489
+
490
+	/**
491
+	 * espresso admin page select_input
492
+	 * Turns an array into a select fields
493
+	 *
494
+	 * @static
495
+	 * @access public
496
+	 * @param string  $name       field name
497
+	 * @param array   $values     option values, numbered array starting at 0, where each value is an array with a key
498
+	 *                            'text' (meaning text to display' and 'id' (meaning the internal value) eg:
499
+	 *                            array(1=>array('text'=>'Monday','id'=>1),2=>array('text'=>'Tuesday','id'=>2)...). or
500
+	 *                            as an array of key-value pairs, where the key is to be used for the select input's
501
+	 *                            name, and the value will be the text shown to the user.  Optionally you can also
502
+	 *                            include an additional key of "class" which will add a specific class to the option
503
+	 *                            for that value.
504
+	 * @param string  $default    default value
505
+	 * @param string  $parameters extra parameters
506
+	 * @param string  $class      css class
507
+	 * @param boolean $autosize   whether to autosize the select or not
508
+	 * @return string              html string for the select input
509
+	 */
510
+	public static function select_input($name, $values, $default = '', $parameters = '', $class = '', $autosize = true)
511
+	{
512
+		// if $values was submitted in the wrong format, convert it over
513
+		if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
514
+			$converted_values = [];
515
+			foreach ($values as $id => $text) {
516
+				$converted_values[] = ['id' => $id, 'text' => $text];
517
+			}
518
+			$values = $converted_values;
519
+		}
520
+
521
+		$field =
522
+			'<select id="' . EEH_Formatter::ee_tep_output_string($name)
523
+			. '" name="' . EEH_Formatter::ee_tep_output_string($name)
524
+			. '"';
525
+
526
+		if (EEH_Formatter::ee_tep_not_null($parameters)) {
527
+			$field .= ' ' . $parameters;
528
+		}
529
+		if ($autosize) {
530
+			$size = 'med';
531
+			for ($ii = 0, $ni = sizeof($values); $ii < $ni; $ii++) {
532
+				if ($values[ $ii ]['text']) {
533
+					if (strlen($values[ $ii ]['text']) > 5) {
534
+						$size = 'wide';
535
+					}
536
+				}
537
+			}
538
+		} else {
539
+			$size = '';
540
+		}
541
+
542
+		$field .= ' class="' . $class . ' ' . $size . '">';
543
+
544
+		if (empty($default) && isset($GLOBALS[ $name ])) {
545
+			$default = stripslashes($GLOBALS[ $name ]);
546
+		}
547
+
548
+
549
+		for ($i = 0, $n = sizeof($values); $i < $n; $i++) {
550
+			$field .= '<option value="' . $values[ $i ]['id'] . '"';
551
+			if ($default == $values[ $i ]['id']) {
552
+				$field .= ' selected = "selected"';
553
+			}
554
+			if (isset($values[ $i ]['class'])) {
555
+				$field .= ' class="' . $values[ $i ]['class'] . '"';
556
+			}
557
+			$field .= '>' . $values[ $i ]['text'] . '</option>';
558
+		}
559
+		$field .= '</select>';
560
+
561
+		return $field;
562
+	}
563
+
564
+
565
+	/**
566
+	 * generate_question_groups_html
567
+	 *
568
+	 * @param array  $question_groups
569
+	 * @param string $group_wrapper
570
+	 * @return string HTML
571
+	 * @throws EE_Error
572
+	 * @throws ReflectionException
573
+	 */
574
+	public static function generate_question_groups_html($question_groups = [], $group_wrapper = 'fieldset')
575
+	{
576
+
577
+		$html                            = '';
578
+		$before_question_group_questions =
579
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
580
+		$after_question_group_questions  =
581
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
582
+
583
+		if (! empty($question_groups)) {
584
+			// loop thru question groups
585
+			foreach ($question_groups as $QSG) {
586
+				// check that questions exist
587
+				if (! empty($QSG['QSG_questions'])) {
588
+					// use fieldsets
589
+					$html .= "\n\t"
590
+							 . '<'
591
+							 . $group_wrapper
592
+							 . ' class="espresso-question-group-wrap" id="'
593
+							 . $QSG['QSG_identifier']
594
+							 . '">';
595
+					// group_name
596
+					$html .= $QSG['QSG_show_group_name']
597
+						? "\n\t\t"
598
+						  . '<h5 class="espresso-question-group-title-h5 section-title">'
599
+						  . self::prep_answer($QSG['QSG_name'])
600
+						  . '</h5>'
601
+						: '';
602
+					// group_desc
603
+					$html .= $QSG['QSG_show_group_desc'] && ! empty($QSG['QSG_desc'])
604
+						? '<div class="espresso-question-group-desc-pg">'
605
+						  . self::prep_answer($QSG['QSG_desc'])
606
+						  . '</div>'
607
+						: '';
608
+
609
+					$html .= $before_question_group_questions;
610
+					// loop thru questions
611
+					foreach ($QSG['QSG_questions'] as $question) {
612
+						$QFI  = new EE_Question_Form_Input(
613
+							$question['qst_obj'],
614
+							$question['ans_obj'],
615
+							$question
616
+						);
617
+						$html .= self::generate_form_input($QFI);
618
+					}
619
+					$html .= $after_question_group_questions;
620
+					$html .= "\n\t" . '</' . $group_wrapper . '>';
621
+				}
622
+			}
623
+		}
624
+
625
+		return $html;
626
+	}
627
+
628
+
629
+	/**
630
+	 * generate_question_groups_html
631
+	 *
632
+	 * @param array  $question_groups
633
+	 * @param array  $q_meta
634
+	 * @param bool   $from_admin
635
+	 * @param string $group_wrapper
636
+	 * @return string HTML
637
+	 * @throws EE_Error
638
+	 * @throws ReflectionException
639
+	 */
640
+	public static function generate_question_groups_html2(
641
+		$question_groups = [],
642
+		$q_meta = [],
643
+		$from_admin = false,
644
+		$group_wrapper = 'fieldset'
645
+	) {
646
+
647
+		$html                            = '';
648
+		$before_question_group_questions =
649
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', '');
650
+		$after_question_group_questions  =
651
+			apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
652
+
653
+		$default_q_meta = [
654
+			'att_nmbr'    => 1,
655
+			'ticket_id'   => '',
656
+			'input_name'  => '',
657
+			'input_id'    => '',
658
+			'input_class' => '',
659
+		];
660
+		$q_meta         = array_merge($default_q_meta, $q_meta);
661
+
662
+		if (! empty($question_groups)) {
663
+			// loop thru question groups
664
+			foreach ($question_groups as $QSG) {
665
+				if ($QSG instanceof EE_Question_Group) {
666
+					// check that questions exist
667
+
668
+					$where = ['QST_deleted' => 0];
669
+					if (! $from_admin) {
670
+						$where['QST_admin_only'] = 0;
671
+					}
672
+					$questions =
673
+						$QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
674
+					if (! empty($questions)) {
675
+						// use fieldsets
676
+						$html .= "\n\t"
677
+								 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
678
+								 . 'id="' . $QSG->get('QSG_identifier') . '">';
679
+						// group_name
680
+						if ($QSG->show_group_name()) {
681
+							$html .= "\n\t\t"
682
+									 . '<h5 class="espresso-question-group-title-h5 section-title">'
683
+									 . $QSG->get_pretty('QSG_name')
684
+									 . '</h5>';
685
+						}
686
+						// group_desc
687
+						if ($QSG->show_group_desc()) {
688
+							$html .= '<div class="espresso-question-group-desc-pg">'
689
+									 . $QSG->get_pretty('QSG_desc')
690
+									 . '</div>';
691
+						}
692
+
693
+						$html .= $before_question_group_questions;
694
+						// loop thru questions
695
+						foreach ($questions as $QST) {
696
+							$qstn_id = $QST->is_system_question() ? $QST->system_ID() : $QST->ID();
697
+
698
+							$answer = null;
699
+
700
+							/** @var RequestInterface $request */
701
+							$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
702
+							$request_qstn = $request->getRequestParam('qstn', [], 'string', true);
703
+							if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
704
+								// check for answer in $request_qstn in case we are reprocessing a form after an error
705
+								if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
706
+									$answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
707
+										? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
708
+										: sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
709
+								}
710
+							} elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
711
+								// attendee data from the session
712
+								$answer =
713
+									isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
714
+							}
715
+
716
+
717
+							$QFI  = new EE_Question_Form_Input(
718
+								$QST,
719
+								EE_Answer::new_instance(
720
+									[
721
+										'ANS_ID'    => 0,
722
+										'QST_ID'    => 0,
723
+										'REG_ID'    => 0,
724
+										'ANS_value' => $answer,
725
+									]
726
+								),
727
+								$q_meta
728
+							);
729
+							$html .= self::generate_form_input($QFI);
730
+						}
731
+						$html .= $after_question_group_questions;
732
+						$html .= "\n\t" . '</' . $group_wrapper . '>';
733
+					}
734
+				}
735
+			}
736
+		}
737
+		return $html;
738
+	}
739
+
740
+
741
+	/**
742
+	 * generate_form_input
743
+	 *
744
+	 * @param EE_Question_Form_Input $QFI
745
+	 * @return string HTML
746
+	 * @throws EE_Error
747
+	 * @throws ReflectionException
748
+	 */
749
+	public static function generate_form_input(EE_Question_Form_Input $QFI)
750
+	{
751
+		if (isset($QFI->QST_admin_only) && $QFI->QST_admin_only && ! is_admin()) {
752
+			return '';
753
+		}
754
+		/** @var RequestInterface $request */
755
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
756
+
757
+		$QFI = self::_load_system_dropdowns($QFI);
758
+		$QFI = self::_load_specialized_dropdowns($QFI);
759
+
760
+		// we also need to verify
761
+
762
+		$display_text = $QFI->get('QST_display_text');
763
+		$input_name   = $QFI->get('QST_input_name');
764
+		$answer       = $request->getRequestParam($input_name, $QFI->get('ANS_value'));
765
+		$input_id     = $QFI->get('QST_input_id');
766
+		$input_class  = $QFI->get('QST_input_class');
767
+		//      $disabled = $QFI->get('QST_disabled') ? ' disabled="disabled"' : '';
768
+		$disabled          = $QFI->get('QST_disabled');
769
+		$required_label    = apply_filters(' FHEE__EEH_Form_Fields__generate_form_input__required_label', '<em>*</em>');
770
+		$QST_required      = $QFI->get('QST_required');
771
+		$required          =
772
+			$QST_required
773
+				? ['label' => $required_label, 'class' => 'required needs-value', 'title' => $QST_required]
774
+				: [];
775
+		$use_html_entities = $QFI->get_meta('htmlentities');
776
+		$required_text     =
777
+			$QFI->get('QST_required_text') != ''
778
+				? $QFI->get('QST_required_text')
779
+				: esc_html__('This field is required', 'event_espresso');
780
+		$required_text     = $QST_required
781
+			? "\n\t\t\t"
782
+			  . '<div class="required-text hidden">'
783
+			  . self::prep_answer($required_text, $use_html_entities)
784
+			  . '</div>'
785
+			: '';
786
+		$label_class       = 'espresso-form-input-lbl';
787
+		$QST_options       = $QFI->options(true, $answer);
788
+		$options           = is_array($QST_options) ? self::prep_answer_options($QST_options) : [];
789
+		$system_ID         = $QFI->get('QST_system');
790
+		$label_b4          = $QFI->get_meta('label_b4');
791
+		$use_desc_4_label  = $QFI->get_meta('use_desc_4_label');
792
+
793
+
794
+		switch ($QFI->get('QST_type')) {
795
+			case 'TEXTAREA':
796
+				return EEH_Form_Fields::textarea(
797
+					$display_text,
798
+					$answer,
799
+					$input_name,
800
+					$input_id,
801
+					$input_class,
802
+					[],
803
+					$required,
804
+					$required_text,
805
+					$label_class,
806
+					$disabled,
807
+					$system_ID,
808
+					$use_html_entities
809
+				);
810
+
811
+			case 'DROPDOWN':
812
+				return EEH_Form_Fields::select(
813
+					$display_text,
814
+					$answer,
815
+					$options,
816
+					$input_name,
817
+					$input_id,
818
+					$input_class,
819
+					$required,
820
+					$required_text,
821
+					$label_class,
822
+					$disabled,
823
+					$system_ID,
824
+					$use_html_entities,
825
+					true
826
+				);
827
+
828
+
829
+			case 'RADIO_BTN':
830
+				return EEH_Form_Fields::radio(
831
+					$display_text,
832
+					$answer,
833
+					$options,
834
+					$input_name,
835
+					$input_id,
836
+					$input_class,
837
+					$required,
838
+					$required_text,
839
+					$label_class,
840
+					$disabled,
841
+					$system_ID,
842
+					$use_html_entities,
843
+					$label_b4,
844
+					$use_desc_4_label
845
+				);
846
+
847
+			case 'CHECKBOX':
848
+				return EEH_Form_Fields::checkbox(
849
+					$display_text,
850
+					$answer,
851
+					$options,
852
+					$input_name,
853
+					$input_id,
854
+					$input_class,
855
+					$required,
856
+					$required_text,
857
+					$label_class,
858
+					$disabled,
859
+					$label_b4,
860
+					$system_ID,
861
+					$use_html_entities
862
+				);
863
+
864
+			case 'DATE':
865
+				return EEH_Form_Fields::datepicker(
866
+					$display_text,
867
+					$answer,
868
+					$input_name,
869
+					$input_id,
870
+					$input_class,
871
+					$required,
872
+					$required_text,
873
+					$label_class,
874
+					$disabled,
875
+					$system_ID,
876
+					$use_html_entities
877
+				);
878
+
879
+			case 'TEXT':
880
+			default:
881
+				return EEH_Form_Fields::text(
882
+					$display_text,
883
+					$answer,
884
+					$input_name,
885
+					$input_id,
886
+					$input_class,
887
+					$required,
888
+					$required_text,
889
+					$label_class,
890
+					$disabled,
891
+					$system_ID,
892
+					$use_html_entities
893
+				);
894
+		}
895
+	}
896
+
897
+
898
+	/**
899
+	 * generates HTML for a form text input
900
+	 *
901
+	 * @param string $question    label content
902
+	 * @param string $answer      form input value attribute
903
+	 * @param string $name        form input name attribute
904
+	 * @param string $id          form input css id attribute
905
+	 * @param string $class       form input css class attribute
906
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
907
+	 *                            required 'class', and required 'msg' attribute
908
+	 * @param string $label_class css class attribute for the label
909
+	 * @param string $disabled    disabled="disabled" or null
910
+	 * @return string HTML
911
+	 */
912
+	public static function text(
913
+		$question = false,
914
+		$answer = null,
915
+		$name = false,
916
+		$id = '',
917
+		$class = '',
918
+		$required = false,
919
+		$required_text = '',
920
+		$label_class = '',
921
+		$disabled = false,
922
+		$system_ID = false,
923
+		$use_html_entities = true
924
+	) {
925
+		// need these
926
+		if (! $question || ! $name) {
927
+			return null;
928
+		}
929
+		// prep the answer
930
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
931
+		// prep the required array
932
+		$required = self::prep_required($required);
933
+		// set disabled tag
934
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
935
+		// ya gots ta have style man!!!
936
+		$txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
937
+		$class     = empty($class) ? $txt_class : $class;
938
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
939
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
940
+
941
+		$label_html =
942
+			$required_text
943
+			. "\n\t\t\t"
944
+			. '<label for="' . $name . '" class="' . $label_class . '">'
945
+			. self::prep_question($question)
946
+			. $required['label']
947
+			. '</label><br/>';
948
+		// filter label but ensure required text comes before it
949
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
950
+
951
+		$input_html =
952
+			"\n\t\t\t"
953
+			. '<input type="text" name="' . $name . '" id="' . $id . '" '
954
+			. 'class="' . $class . ' ' . $required['class'] . '" value="' . esc_attr($answer) . '"  '
955
+			. 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
956
+
957
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
958
+		return $label_html . $input_html;
959
+	}
960
+
961
+
962
+	/**
963
+	 * generates HTML for a form textarea
964
+	 *
965
+	 * @param string $question    label content
966
+	 * @param string $answer      form input value attribute
967
+	 * @param string $name        form input name attribute
968
+	 * @param string $id          form input css id attribute
969
+	 * @param string $class       form input css class attribute
970
+	 * @param array  $dimensions  array of form input rows and cols attributes : array( 'rows' => 3, 'cols' => 40 )
971
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
972
+	 *                            required 'class', and required 'msg' attribute
973
+	 * @param string $label_class css class attribute for the label
974
+	 * @param string $disabled    disabled="disabled" or null
975
+	 * @return string HTML
976
+	 */
977
+	public static function textarea(
978
+		$question = false,
979
+		$answer = null,
980
+		$name = false,
981
+		$id = '',
982
+		$class = '',
983
+		$dimensions = false,
984
+		$required = false,
985
+		$required_text = '',
986
+		$label_class = '',
987
+		$disabled = false,
988
+		$system_ID = false,
989
+		$use_html_entities = true
990
+	) {
991
+		// need these
992
+		if (! $question || ! $name) {
993
+			return null;
994
+		}
995
+		// prep the answer
996
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
997
+		// prep the required array
998
+		$required = self::prep_required($required);
999
+		// make sure $dimensions is an array
1000
+		$dimensions = is_array($dimensions) ? $dimensions : [];
1001
+		// and set some defaults
1002
+		$dimensions = array_merge(['rows' => 3, 'cols' => 40], $dimensions);
1003
+		// set disabled tag
1004
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1005
+		// ya gots ta have style man!!!
1006
+		$txt_class = is_admin() ? 'regular-text' : 'espresso-textarea-inp';
1007
+		$class     = empty($class) ? $txt_class : $class;
1008
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1009
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1010
+
1011
+		$label_html =
1012
+			$required_text
1013
+			. "\n\t\t\t"
1014
+			. '<label for="' . $name . '" class="' . $label_class . '">'
1015
+			. self::prep_question($question)
1016
+			. $required['label']
1017
+			. '</label><br/>';
1018
+		// filter label but ensure required text comes before it
1019
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1020
+
1021
+		$input_html =
1022
+			"\n\t\t\t"
1023
+			. '<textarea name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1024
+			. 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1025
+			. 'title="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1026
+			. esc_textarea($answer)
1027
+			. '</textarea>';
1028
+
1029
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1030
+		return $label_html . $input_html;
1031
+	}
1032
+
1033
+
1034
+	/**
1035
+	 * generates HTML for a form select input
1036
+	 *
1037
+	 * @param string $question    label content
1038
+	 * @param string $answer      form input value attribute
1039
+	 * @param array  $options     array of answer options where array key = option value and array value = option
1040
+	 *                            display text
1041
+	 * @param string $name        form input name attribute
1042
+	 * @param string $id          form input css id attribute
1043
+	 * @param string $class       form input css class attribute
1044
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1045
+	 *                            required 'class', and required 'msg' attribute
1046
+	 * @param string $label_class css class attribute for the label
1047
+	 * @param string $disabled    disabled="disabled" or null
1048
+	 * @return string HTML
1049
+	 */
1050
+	public static function select(
1051
+		$question = false,
1052
+		$answer = null,
1053
+		$options = false,
1054
+		$name = false,
1055
+		$id = '',
1056
+		$class = '',
1057
+		$required = false,
1058
+		$required_text = '',
1059
+		$label_class = '',
1060
+		$disabled = false,
1061
+		$system_ID = false,
1062
+		$use_html_entities = true,
1063
+		$add_please_select_option = false
1064
+	) {
1065
+
1066
+		// need these
1067
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1068
+			return null;
1069
+		}
1070
+		// prep the answer
1071
+		$answer =
1072
+			is_array($answer)
1073
+				? self::prep_answer(array_shift($answer), $use_html_entities)
1074
+				: self::prep_answer(
1075
+					$answer,
1076
+					$use_html_entities
1077
+				);
1078
+		// prep the required array
1079
+		$required = self::prep_required($required);
1080
+		// set disabled tag
1081
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1082
+		// ya gots ta have style man!!!
1083
+		$txt_class = is_admin() ? 'wide' : 'espresso-select-inp';
1084
+		$class     = empty($class) ? $txt_class : $class;
1085
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1086
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1087
+
1088
+		$label_html =
1089
+			$required_text
1090
+			. "\n\t\t\t"
1091
+			. '<label for="' . $name . '" class="' . $label_class . '">'
1092
+			. self::prep_question($question)
1093
+			. $required['label']
1094
+			. '</label><br/>';
1095
+		// filter label but ensure required text comes before it
1096
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1097
+
1098
+		$input_html =
1099
+			"\n\t\t\t"
1100
+			. '<select name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1101
+			. 'title="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1102
+		// recursively count array elements, to determine total number of options
1103
+		$only_option = count($options, 1) == 1;
1104
+		if (! $only_option) {
1105
+			// if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1106
+			$selected   = $answer === null ? ' selected' : '';
1107
+			$input_html .= $add_please_select_option
1108
+				? "\n\t\t\t\t"
1109
+				  . '<option value=""' . $selected . '>'
1110
+				  . esc_html__(' - please select - ', 'event_espresso')
1111
+				  . '</option>'
1112
+				: '';
1113
+		}
1114
+		foreach ($options as $key => $value) {
1115
+			// if value is an array, then create option groups, else create regular ol' options
1116
+			$input_html .= is_array($value)
1117
+				? self::_generate_select_option_group(
1118
+					$key,
1119
+					$value,
1120
+					$answer,
1121
+					$use_html_entities
1122
+				)
1123
+				: self::_generate_select_option(
1124
+					$value->value(),
1125
+					$value->desc(),
1126
+					$answer,
1127
+					$only_option,
1128
+					$use_html_entities
1129
+				);
1130
+		}
1131
+
1132
+		$input_html .= "\n\t\t\t" . '</select>';
1133
+
1134
+		$input_html =
1135
+			apply_filters(
1136
+				'FHEE__EEH_Form_Fields__select__before_end_wrapper',
1137
+				$input_html,
1138
+				$question,
1139
+				$answer,
1140
+				$name,
1141
+				$id,
1142
+				$class,
1143
+				$system_ID
1144
+			);
1145
+
1146
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1147
+		return $label_html . $input_html;
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 *  _generate_select_option_group
1153
+	 *
1154
+	 *  if  $value for a select box is an array, then the key will be used as the optgroup label
1155
+	 *  and the value array will be looped thru and the elements sent to _generate_select_option
1156
+	 *
1157
+	 * @param mixed   $opt_group
1158
+	 * @param mixed   $QSOs
1159
+	 * @param mixed   $answer
1160
+	 * @param boolean $use_html_entities
1161
+	 * @return string
1162
+	 */
1163
+	private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1164
+	{
1165
+		$html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1166
+		foreach ($QSOs as $QSO) {
1167
+			$html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1168
+		}
1169
+		$html .= "\n\t\t\t\t" . '</optgroup>';
1170
+		return $html;
1171
+	}
1172
+
1173
+
1174
+	/**
1175
+	 *  _generate_select_option
1176
+	 *
1177
+	 * @param mixed   $key
1178
+	 * @param mixed   $value
1179
+	 * @param mixed   $answer
1180
+	 * @param int     $only_option
1181
+	 * @param boolean $use_html_entities
1182
+	 * @return string
1183
+	 */
1184
+	private static function _generate_select_option(
1185
+		$key,
1186
+		$value,
1187
+		$answer,
1188
+		$only_option = false,
1189
+		$use_html_entities = true
1190
+	) {
1191
+		$key      = self::prep_answer($key, $use_html_entities);
1192
+		$value    = self::prep_answer($value, $use_html_entities);
1193
+		$value    = ! empty($value) ? $value : $key;
1194
+		$selected = ($answer == $key || $only_option) ? 'selected' : '';
1195
+		return "\n\t\t\t\t"
1196
+			   . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1197
+			   . $value
1198
+			   . '&nbsp;&nbsp;&nbsp;</option>';
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * generates HTML for form radio button inputs
1204
+	 *
1205
+	 * @param bool|string $question    label content
1206
+	 * @param string      $answer      form input value attribute
1207
+	 * @param array|bool  $options     array of answer options where array key = option value and array value = option
1208
+	 *                                 display text
1209
+	 * @param bool|string $name        form input name attribute
1210
+	 * @param string      $id          form input css id attribute
1211
+	 * @param string      $class       form input css class attribute
1212
+	 * @param array|bool  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1213
+	 *                                 required 'class', and required 'msg' attribute
1214
+	 * @param string      $required_text
1215
+	 * @param string      $label_class css class attribute for the label
1216
+	 * @param bool|string $disabled    disabled="disabled" or null
1217
+	 * @param bool        $system_ID
1218
+	 * @param bool        $use_html_entities
1219
+	 * @param bool        $label_b4
1220
+	 * @param bool        $use_desc_4_label
1221
+	 * @return string HTML
1222
+	 */
1223
+	public static function radio(
1224
+		$question = false,
1225
+		$answer = null,
1226
+		$options = false,
1227
+		$name = false,
1228
+		$id = '',
1229
+		$class = '',
1230
+		$required = false,
1231
+		$required_text = '',
1232
+		$label_class = '',
1233
+		$disabled = false,
1234
+		$system_ID = false,
1235
+		$use_html_entities = true,
1236
+		$label_b4 = false,
1237
+		$use_desc_4_label = false
1238
+	) {
1239
+		// need these
1240
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1241
+			return null;
1242
+		}
1243
+		// prep the answer
1244
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1245
+		// prep the required array
1246
+		$required = self::prep_required($required);
1247
+		// set disabled tag
1248
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1249
+		// ya gots ta have style man!!!
1250
+		$radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1251
+		$class       = ! empty($class) ? $class : 'espresso-radio-btn-inp';
1252
+		$extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1253
+
1254
+		$label_html =
1255
+			$required_text
1256
+			. "\n\t\t\t"
1257
+			. '<label class="' . $label_class . '">'
1258
+			. self::prep_question($question)
1259
+			. $required['label']
1260
+			. '</label> ';
1261
+		// filter label but ensure required text comes before it
1262
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1263
+
1264
+		$input_html =
1265
+			"\n\t\t\t"
1266
+			. '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $label_class . ' ' . $class . '-ul">';
1267
+
1268
+		$class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1269
+		$class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1270
+
1271
+		foreach ($options as $OPT) {
1272
+			if ($OPT instanceof EE_Question_Option) {
1273
+				$value   = self::prep_option_value($OPT->value());
1274
+				$label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1275
+				$size    = $use_desc_4_label
1276
+					? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1277
+					: self::get_label_size_class($OPT->value());
1278
+				$desc    = $OPT->desc();// no self::prep_answer
1279
+				$answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1280
+				$checked = (string) $value == (string) $answer ? ' checked' : '';
1281
+				$opt     = '-' . sanitize_key($value);
1282
+
1283
+				$input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1284
+				$input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1285
+				$input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>' : '';
1286
+				$input_html .= "\n\t\t\t\t\t\t"
1287
+							   . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1288
+							   . 'class="' . $class . '" value="' . $value . '" '
1289
+							   . 'title="' . esc_attr($required['msg']) . '" ' . $disabled
1290
+							   . $checked . ' ' . $extra . '/>';
1291
+				$input_html .= ! $label_b4
1292
+					? "\n\t\t\t\t\t\t"
1293
+					  . '<span class="espresso-radio-btn-desc">'
1294
+					  . $label
1295
+					  . '</span>'
1296
+					: '';
1297
+				$input_html .= "\n\t\t\t\t\t" . '</label>';
1298
+				$input_html .= $use_desc_4_label
1299
+					? ''
1300
+					: '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1301
+				$input_html .= "\n\t\t\t\t" . '</li>';
1302
+			}
1303
+		}
1304
+
1305
+		$input_html .= "\n\t\t\t" . '</ul>';
1306
+
1307
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1308
+		return $label_html . $input_html;
1309
+	}
1310
+
1311
+
1312
+	/**
1313
+	 * generates HTML for form checkbox inputs
1314
+	 *
1315
+	 * @param string $question    label content
1316
+	 * @param string $answer      form input value attribute
1317
+	 * @param array  $options     array of options where array key = option value and array value = option display text
1318
+	 * @param string $name        form input name attribute
1319
+	 * @param string $id          form input css id attribute
1320
+	 * @param string $class       form input css class attribute
1321
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1322
+	 *                            required 'class', and required 'msg' attribute
1323
+	 * @param string $label_class css class attribute for the label
1324
+	 * @param string $disabled    disabled="disabled" or null
1325
+	 * @return string HTML
1326
+	 */
1327
+	public static function checkbox(
1328
+		$question = false,
1329
+		$answer = null,
1330
+		$options = false,
1331
+		$name = false,
1332
+		$id = '',
1333
+		$class = '',
1334
+		$required = false,
1335
+		$required_text = '',
1336
+		$label_class = '',
1337
+		$disabled = false,
1338
+		$label_b4 = false,
1339
+		$system_ID = false,
1340
+		$use_html_entities = true
1341
+	) {
1342
+		// need these
1343
+		if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1344
+			return null;
1345
+		}
1346
+		$answer = maybe_unserialize($answer);
1347
+
1348
+		// prep the answer(s)
1349
+		$answer = is_array($answer) ? $answer : [sanitize_key($answer) => $answer];
1350
+
1351
+		foreach ($answer as $key => $value) {
1352
+			$key            = self::prep_option_value($key);
1353
+			$answer[ $key ] = self::prep_answer($value, $use_html_entities);
1354
+		}
1355
+
1356
+		// prep the required array
1357
+		$required = self::prep_required($required);
1358
+		// set disabled tag
1359
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1360
+		// ya gots ta have style man!!!
1361
+		$radio_class = is_admin() ? 'ee-admin-radio-lbl' : $label_class;
1362
+		$class       = empty($class) ? 'espresso-radio-btn-inp' : $class;
1363
+		$extra       = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1364
+
1365
+		$label_html =
1366
+			$required_text
1367
+			. "\n\t\t\t"
1368
+			. '<label class="' . $label_class . '">'
1369
+			. self::prep_question($question)
1370
+			. $required['label']
1371
+			. '</label> ';
1372
+		// filter label but ensure required text comes before it
1373
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1374
+
1375
+		$input_html =
1376
+			"\n\t\t\t"
1377
+			. '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $label_class . ' ' . $class . '-ul">';
1378
+
1379
+		$class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1380
+		$class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1381
+
1382
+		foreach ($options as $OPT) {
1383
+			$value = $OPT->value();// self::prep_option_value( $OPT->value() );
1384
+			$size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1385
+			$text  = self::prep_answer($OPT->value());
1386
+			$desc  = $OPT->desc();
1387
+			$opt   = '-' . sanitize_key($value);
1388
+
1389
+			$checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1390
+
1391
+			$input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1392
+			$input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1393
+			$input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1394
+			$input_html .= "\n\t\t\t\t\t\t"
1395
+						   . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1396
+						   . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1397
+						   . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1398
+			$input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1399
+			$input_html .= "\n\t\t\t\t\t" . '</label>';
1400
+			if (! empty($desc) && $desc != $text) {
1401
+				$input_html .= "\n\t\t\t\t\t"
1402
+							   . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1403
+							   . $desc
1404
+							   . '</div>';
1405
+			}
1406
+			$input_html .= "\n\t\t\t\t" . '</li>';
1407
+		}
1408
+
1409
+		$input_html .= "\n\t\t\t" . '</ul>';
1410
+
1411
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1412
+		return $label_html . $input_html;
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * generates HTML for a form datepicker input
1418
+	 *
1419
+	 * @param string $question    label content
1420
+	 * @param string $answer      form input value attribute
1421
+	 * @param string $name        form input name attribute
1422
+	 * @param string $id          form input css id attribute
1423
+	 * @param string $class       form input css class attribute
1424
+	 * @param array  $required    'label', 'class', and 'msg' - array of values for required "label" content, css
1425
+	 *                            required 'class', and required 'msg' attribute
1426
+	 * @param string $label_class css class attribute for the label
1427
+	 * @param string $disabled    disabled="disabled" or null
1428
+	 * @return string HTML
1429
+	 */
1430
+	public static function datepicker(
1431
+		$question = false,
1432
+		$answer = null,
1433
+		$name = false,
1434
+		$id = '',
1435
+		$class = '',
1436
+		$required = false,
1437
+		$required_text = '',
1438
+		$label_class = '',
1439
+		$disabled = false,
1440
+		$system_ID = false,
1441
+		$use_html_entities = true
1442
+	) {
1443
+		// need these
1444
+		if (! $question || ! $name) {
1445
+			return null;
1446
+		}
1447
+		// prep the answer
1448
+		$answer = is_array($answer) ? '' : self::prep_answer($answer, $use_html_entities);
1449
+		// prep the required array
1450
+		$required = self::prep_required($required);
1451
+		// set disabled tag
1452
+		$disabled = $answer === null || ! $disabled ? '' : ' disabled="disabled"';
1453
+		// ya gots ta have style man!!!
1454
+		$txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1455
+		$class     = empty($class) ? $txt_class : $class;
1456
+		$class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1457
+		$extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1458
+
1459
+		$label_html =
1460
+			$required_text
1461
+			. "\n\t\t\t"
1462
+			. '<label for="' . $name . '" class="' . $label_class . '">'
1463
+			. self::prep_question($question)
1464
+			. $required['label']
1465
+			. '</label><br/>';
1466
+		// filter label but ensure required text comes before it
1467
+		$label_html = apply_filters('FHEE__EEH_Form_Fields__label_html', $label_html, $required_text);
1468
+
1469
+		$input_html =
1470
+			"\n\t\t\t"
1471
+			. '<input type="text" name="' . $name . '" id="' . $id . '" '
1472
+			. 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1473
+			. 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1474
+
1475
+		// enqueue scripts
1476
+		wp_register_style(
1477
+			'espresso-ui-theme',
1478
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1479
+			[],
1480
+			EVENT_ESPRESSO_VERSION
1481
+		);
1482
+		wp_enqueue_style('espresso-ui-theme');
1483
+		wp_enqueue_script('jquery-ui-datepicker');
1484
+
1485
+		$input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1486
+		return $label_html . $input_html;
1487
+	}
1488
+
1489
+
1490
+	/**
1491
+	 *  remove_label_keep_required_msg
1492
+	 *  this will strip out a form input's label HTML while keeping the required text HTML that MUST be before the label
1493
+	 *
1494
+	 * @access public
1495
+	 * @return     string
1496
+	 */
1497
+	public static function remove_label_keep_required_msg($label_html, $required_text)
1498
+	{
1499
+		return $required_text;
1500
+	}
1501
+
1502
+
1503
+	/**
1504
+	 * Simply returns the HTML for a hidden input of the given name and value.
1505
+	 *
1506
+	 * @param string $name
1507
+	 * @param string $value
1508
+	 * @return string HTML
1509
+	 */
1510
+	public static function hidden_input($name, $value, $id = '')
1511
+	{
1512
+		$id = ! empty($id) ? $id : $name;
1513
+		return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1514
+	}
1515
+
1516
+
1517
+	/**
1518
+	 * prep_question
1519
+	 *
1520
+	 * @param string $question
1521
+	 * @return string
1522
+	 */
1523
+	public static function prep_question($question)
1524
+	{
1525
+		return $question;
1526
+	}
1527
+
1528
+
1529
+	/**
1530
+	 *  prep_answer
1531
+	 *
1532
+	 * @param mixed $answer
1533
+	 * @return string
1534
+	 */
1535
+	public static function prep_answer($answer, $use_html_entities = true)
1536
+	{
1537
+		// make sure we convert bools first.  Otherwise (bool) false becomes an empty string which is NOT desired,
1538
+		// we want "0".
1539
+		if (is_bool($answer)) {
1540
+			$answer = $answer ? 1 : 0;
1541
+		}
1542
+		$answer = trim(stripslashes(str_replace('&#039;', "'", $answer)));
1543
+		return $use_html_entities ? htmlentities($answer, ENT_QUOTES, 'UTF-8') : $answer;
1544
+	}
1545
+
1546
+
1547
+	/**
1548
+	 *  prep_answer_options
1549
+	 *
1550
+	 * @param array $QSOs array of EE_Question_Option objects
1551
+	 * @return array
1552
+	 */
1553
+	public static function prep_answer_options($QSOs = [])
1554
+	{
1555
+		$prepped_answer_options = [];
1556
+		if (is_array($QSOs) && ! empty($QSOs)) {
1557
+			foreach ($QSOs as $key => $QSO) {
1558
+				if (! $QSO instanceof EE_Question_Option) {
1559
+					$QSO = EE_Question_Option::new_instance(
1560
+						[
1561
+							'QSO_value' => is_array($QSO) && isset($QSO['id'])
1562
+								? (string) $QSO['id']
1563
+								: (string) $key,
1564
+							'QSO_desc'  => is_array($QSO) && isset($QSO['text'])
1565
+								? (string) $QSO['text']
1566
+								: (string) $QSO,
1567
+						]
1568
+					);
1569
+				}
1570
+				if ($QSO->opt_group()) {
1571
+					$prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1572
+				} else {
1573
+					$prepped_answer_options[] = $QSO;
1574
+				}
1575
+			}
1576
+		}
1577
+		//      d( $prepped_answer_options );
1578
+		return $prepped_answer_options;
1579
+	}
1580
+
1581
+
1582
+	/**
1583
+	 *  prep_option_value
1584
+	 *
1585
+	 * @param string $option_value
1586
+	 * @return string
1587
+	 */
1588
+	public static function prep_option_value($option_value)
1589
+	{
1590
+		return esc_attr(trim(stripslashes($option_value)));
1591
+	}
1592
+
1593
+
1594
+	/**
1595
+	 *  prep_required
1596
+	 *
1597
+	 * @param string|array $required
1598
+	 * @return array
1599
+	 */
1600
+	public static function prep_required($required = [])
1601
+	{
1602
+		// make sure required is an array
1603
+		$required = is_array($required) ? $required : [];
1604
+		// and set some defaults
1605
+		return array_merge(['label' => '', 'class' => '', 'msg' => ''], $required);
1606
+	}
1607
+
1608
+
1609
+	/**
1610
+	 *  get_label_size_class
1611
+	 *
1612
+	 * @param string $value
1613
+	 * @return string
1614
+	 */
1615
+	public static function get_label_size_class($value = false)
1616
+	{
1617
+		if ($value === false || $value === '') {
1618
+			return ' class="medium-lbl"';
1619
+		}
1620
+		// determine length of option value
1621
+		$val_size = strlen($value);
1622
+		switch ($val_size) {
1623
+			case $val_size < 3:
1624
+				$size = ' class="nano-lbl"';
1625
+				break;
1626
+			case $val_size < 6:
1627
+				$size = ' class="micro-lbl"';
1628
+				break;
1629
+			case $val_size < 12:
1630
+				$size = ' class="tiny-lbl"';
1631
+				break;
1632
+			case $val_size < 25:
1633
+				$size = ' class="small-lbl"';
1634
+				break;
1635
+			case $val_size > 100:
1636
+				$size = ' class="big-lbl"';
1637
+				break;
1638
+			default:
1639
+				$size = ' class="medium-lbl"';
1640
+				break;
1641
+		}
1642
+		return $size;
1643
+	}
1644
+
1645
+
1646
+	/**
1647
+	 *  _load_system_dropdowns
1648
+	 *
1649
+	 * @param EE_Question_Form_Input $QFI
1650
+	 * @return array
1651
+	 * @throws EE_Error
1652
+	 * @throws ReflectionException
1653
+	 */
1654
+	private static function _load_system_dropdowns($QFI)
1655
+	{
1656
+		$QST_system = $QFI->get('QST_system');
1657
+		switch ($QST_system) {
1658
+			case 'state':
1659
+				$QFI = self::generate_state_dropdown($QFI);
1660
+				break;
1661
+			case 'country':
1662
+				$QFI = self::generate_country_dropdown($QFI);
1663
+				break;
1664
+			case 'admin-state':
1665
+				$QFI = self::generate_state_dropdown($QFI, true);
1666
+				break;
1667
+			case 'admin-country':
1668
+				$QFI = self::generate_country_dropdown($QFI, true);
1669
+				break;
1670
+		}
1671
+		return $QFI;
1672
+	}
1673
+
1674
+
1675
+	/**
1676
+	 * This preps dropdowns that are specialized.
1677
+	 *
1678
+	 * @param EE_Question_Form_Input $QFI
1679
+	 *
1680
+	 * @return EE_Question_Form_Input
1681
+	 * @throws EE_Error
1682
+	 * @throws ReflectionException
1683
+	 * @since  4.6.0
1684
+	 */
1685
+	protected static function _load_specialized_dropdowns($QFI)
1686
+	{
1687
+		switch ($QFI->get('QST_type')) {
1688
+			case 'STATE':
1689
+				$QFI = self::generate_state_dropdown($QFI);
1690
+				break;
1691
+			case 'COUNTRY':
1692
+				$QFI = self::generate_country_dropdown($QFI);
1693
+				break;
1694
+		}
1695
+		return $QFI;
1696
+	}
1697
+
1698
+
1699
+	/**
1700
+	 *    generate_state_dropdown
1701
+	 *
1702
+	 * @param EE_Question_Form_Input $QST
1703
+	 * @param bool                   $get_all
1704
+	 * @return EE_Question_Form_Input
1705
+	 * @throws EE_Error
1706
+	 * @throws ReflectionException
1707
+	 */
1708
+	public static function generate_state_dropdown($QST, $get_all = false)
1709
+	{
1710
+		$states = $get_all
1711
+			? EEM_State::instance()->get_all_states()
1712
+			: EEM_State::instance()->get_all_states_of_active_countries();
1713
+		if ($states && count($states) != count($QST->options())) {
1714
+			$QST->set('QST_type', 'DROPDOWN');
1715
+			// if multiple countries, we'll create option groups within the dropdown
1716
+			foreach ($states as $state) {
1717
+				if ($state instanceof EE_State) {
1718
+					$QSO = EE_Question_Option::new_instance(
1719
+						[
1720
+							'QSO_value'   => $state->ID(),
1721
+							'QSO_desc'    => $state->name(),
1722
+							'QST_ID'      => $QST->get('QST_ID'),
1723
+							'QSO_deleted' => false,
1724
+						]
1725
+					);
1726
+					// set option group
1727
+					$QSO->set_opt_group($state->country()->name());
1728
+					// add option to question
1729
+					$QST->add_temp_option($QSO);
1730
+				}
1731
+			}
1732
+		}
1733
+		return $QST;
1734
+	}
1735
+
1736
+
1737
+	/**
1738
+	 *    generate_country_dropdown
1739
+	 *
1740
+	 * @param      $QST
1741
+	 * @param bool $get_all
1742
+	 * @return array
1743
+	 * @throws EE_Error
1744
+	 * @throws ReflectionException
1745
+	 * @internal param array $question
1746
+	 */
1747
+	public static function generate_country_dropdown($QST, $get_all = false)
1748
+	{
1749
+		$countries = $get_all
1750
+			? EEM_Country::instance()->get_all_countries()
1751
+			: EEM_Country::instance()->get_all_active_countries();
1752
+		if ($countries && count($countries) != count($QST->options())) {
1753
+			$QST->set('QST_type', 'DROPDOWN');
1754
+			// now add countries
1755
+			foreach ($countries as $country) {
1756
+				if ($country instanceof EE_Country) {
1757
+					$QSO = EE_Question_Option::new_instance(
1758
+						[
1759
+							'QSO_value'   => $country->ID(),
1760
+							'QSO_desc'    => $country->name(),
1761
+							'QST_ID'      => $QST->get('QST_ID'),
1762
+							'QSO_deleted' => false,
1763
+						]
1764
+					);
1765
+					$QST->add_temp_option($QSO);
1766
+				}
1767
+			}
1768
+		}
1769
+		return $QST;
1770
+	}
1771
+
1772
+
1773
+	/**
1774
+	 *  generates options for a month dropdown selector with numbers from 01 to 12
1775
+	 *
1776
+	 * @return array()
1777
+	 */
1778
+	public static function two_digit_months_dropdown_options()
1779
+	{
1780
+		$options = [];
1781
+		for ($x = 1; $x <= 12; $x++) {
1782
+			$mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1783
+			$options[ $mm ] = $mm;
1784
+		}
1785
+		return EEH_Form_Fields::prep_answer_options($options);
1786
+	}
1787
+
1788
+
1789
+	/**
1790
+	 *  generates a year dropdown selector with numbers for the next ten years
1791
+	 *
1792
+	 * @return array
1793
+	 */
1794
+	public static function next_decade_two_digit_year_dropdown_options()
1795
+	{
1796
+		$options      = [];
1797
+		$current_year = date('y');
1798
+		$next_decade  = $current_year + 10;
1799
+		for ($x = $current_year; $x <= $next_decade; $x++) {
1800
+			$yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1801
+			$options[ $yy ] = $yy;
1802
+		}
1803
+		return EEH_Form_Fields::prep_answer_options($options);
1804
+	}
1805
+
1806
+
1807
+	/**
1808
+	 * generates a month/year dropdown selector for all registrations matching the given criteria.  Typically used for
1809
+	 * list table filter.
1810
+	 *
1811
+	 * @param string  $cur_date     any currently selected date can be entered here.
1812
+	 * @param string  $status       Registration status
1813
+	 * @param integer $evt_category Event Category ID if the Event Category filter is selected
1814
+	 * @return string                html
1815
+	 * @throws EE_Error
1816
+	 */
1817
+	public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1818
+	{
1819
+		$_where = [];
1820
+		if (! empty($status)) {
1821
+			$_where['STS_ID'] = $status;
1822
+		}
1823
+
1824
+		if ($evt_category > 0) {
1825
+			$_where['Event.Term_Taxonomy.term_id'] = $evt_category;
1826
+		}
1827
+
1828
+		$regdtts = EEM_Registration::instance()->get_reg_months_and_years($_where);
1829
+
1830
+		// setup vals for select input helper
1831
+		$options = [
1832
+			0 => [
1833
+				'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1834
+				'id'   => '',
1835
+			],
1836
+		];
1837
+
1838
+		foreach ($regdtts as $regdtt) {
1839
+			$date      = $regdtt->reg_month . ' ' . $regdtt->reg_year;
1840
+			$options[] = [
1841
+				'text' => $date,
1842
+				'id'   => $date,
1843
+			];
1844
+		}
1845
+
1846
+		return self::select_input('month_range', $options, $cur_date, '', 'wide');
1847
+	}
1848
+
1849
+
1850
+	/**
1851
+	 * generates a month/year dropdown selector for all events matching the given criteria
1852
+	 * Typically used for list table filter
1853
+	 *
1854
+	 * @param string $cur_date          any currently selected date can be entered here.
1855
+	 * @param string $status            "view" (i.e. all, today, month, draft)
1856
+	 * @param int    $evt_category      category event belongs to
1857
+	 * @param string $evt_active_status "upcoming", "expired", "active", or "inactive"
1858
+	 * @return string                    html
1859
+	 * @throws EE_Error
1860
+	 */
1861
+	public static function generate_event_months_dropdown(
1862
+		$cur_date = '',
1863
+		$status = null,
1864
+		$evt_category = null,
1865
+		$evt_active_status = null
1866
+	) {
1867
+		// determine what post_status our condition will have for the query.
1868
+		// phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
1869
+		switch ($status) {
1870
+			case 'month':
1871
+			case 'today':
1872
+			case null:
1873
+			case 'all':
1874
+				$where['Event.status'] = ['NOT IN', ['trash']];
1875
+				break;
1876
+			case 'draft':
1877
+				$where['Event.status'] = ['IN', ['draft', 'auto-draft']];
1878
+				break;
1879
+			default:
1880
+				$where['Event.status'] = $status;
1881
+		}
1882
+
1883
+		// phpcs:enable
1884
+
1885
+		// categories?
1886
+
1887
+
1888
+		if (! empty($evt_category)) {
1889
+			$where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1890
+			$where['Event.Term_Taxonomy.term_id']  = $evt_category;
1891
+		}
1892
+
1893
+
1894
+		//      $where['DTT_is_primary'] = 1;
1895
+
1896
+		$DTTS = EEM_Datetime::instance()->get_dtt_months_and_years($where, $evt_active_status);
1897
+
1898
+		// let's setup vals for select input helper
1899
+		$options = [
1900
+			0 => [
1901
+				'text' => esc_html__('Select a Month/Year', 'event_espresso'),
1902
+				'id'   => "",
1903
+			],
1904
+		];
1905
+
1906
+
1907
+		// translate month and date
1908
+		global $wp_locale;
1909
+
1910
+		foreach ($DTTS as $DTT) {
1911
+			$localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
1912
+			$id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
1913
+			$options[]      = [
1914
+				'text' => $localized_date,
1915
+				'id'   => $id,
1916
+			];
1917
+		}
1918
+
1919
+
1920
+		return self::select_input('month_range', $options, $cur_date, '', 'wide');
1921
+	}
1922
+
1923
+
1924
+	/**
1925
+	 * generates the dropdown selector for event categories
1926
+	 * typically used as a filter on list tables.
1927
+	 *
1928
+	 * @param integer $current_cat currently selected category
1929
+	 * @return string               html for dropdown
1930
+	 * @throws EE_Error
1931
+	 * @throws ReflectionException
1932
+	 */
1933
+	public static function generate_event_category_dropdown($current_cat = -1)
1934
+	{
1935
+		$categories = EEM_Term::instance()->get_all_ee_categories(true);
1936
+		$options    = [
1937
+			'0' => [
1938
+				'text' => esc_html__('All Categories', 'event_espresso'),
1939
+				'id'   => -1,
1940
+			],
1941
+		];
1942
+
1943
+		// setup categories for dropdown
1944
+		foreach ($categories as $category) {
1945
+			$options[] = [
1946
+				'text' => $category->get('name'),
1947
+				'id'   => $category->ID(),
1948
+			];
1949
+		}
1950
+
1951
+		return self::select_input('EVT_CAT', $options, $current_cat);
1952
+	}
1953
+
1954
+
1955
+	/**
1956
+	 *    generate a submit button with or without it's own microform
1957
+	 *    this is the only way to create buttons that are compatible across all themes
1958
+	 *
1959
+	 * @access    public
1960
+	 * @param string      $url              - the form action
1961
+	 * @param string      $ID               - some kind of unique ID, appended with "-sbmt" for the input and "-frm"
1962
+	 *                                      for the form
1963
+	 * @param string      $class            - css classes (separated by spaces if more than one)
1964
+	 * @param string      $text             - what appears on the button
1965
+	 * @param string      $nonce_action     - if using nonces
1966
+	 * @param bool|string $input_only       - whether to print form header and footer. TRUE returns the input without
1967
+	 *                                      the form
1968
+	 * @param string      $extra_attributes - any extra attributes that need to be attached to the form input
1969
+	 * @return    string
1970
+	 */
1971
+	public static function submit_button(
1972
+		$url = '',
1973
+		$ID = '',
1974
+		$class = '',
1975
+		$text = '',
1976
+		$nonce_action = '',
1977
+		$input_only = false,
1978
+		$extra_attributes = ''
1979
+	) {
1980
+		$btn = '';
1981
+		if (empty($url) || empty($ID)) {
1982
+			return $btn;
1983
+		}
1984
+		$text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
1985
+		$btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
1986
+				 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
1987
+		if (! $input_only) {
1988
+			$btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
1989
+			$btn_frm .= ! empty($nonce_action)
1990
+				? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
1991
+				: '';
1992
+			$btn_frm .= $btn;
1993
+			$btn_frm .= '</form>';
1994
+			$btn     = $btn_frm;
1995
+			unset($btn_frm);
1996
+		}
1997
+		return $btn;
1998
+	}
1999 1999
 }
Please login to merge, or discard this patch.
Spacing   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -108,8 +108,8 @@  discard block
 block discarded – undo
108 108
             $type           = $input_value['input'];
109 109
             $value          = $input_value['value'];
110 110
 
111
-            $id    = $form_id ? $form_id . '-' . $input_key : $input_key;
112
-            $class = $required ? 'required ' . $css_class : $css_class;
111
+            $id    = $form_id ? $form_id.'-'.$input_key : $input_key;
112
+            $class = $required ? 'required '.$css_class : $css_class;
113 113
 
114 114
             // what type of input are we dealing with ?
115 115
             switch ($type) {
@@ -161,8 +161,8 @@  discard block
 block discarded – undo
161 161
             }
162 162
         } // end foreach( $input_vars as $input_key => $input_value )
163 163
 
164
-        if (! empty($inputs)) {
165
-            $glue   = "
164
+        if ( ! empty($inputs)) {
165
+            $glue = "
166 166
                 </li>
167 167
                 <li>
168 168
                     ";
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
             </ul>
176 176
             ";
177 177
         }
178
-        return $output . implode("\n", $hidden_inputs);
178
+        return $output.implode("\n", $hidden_inputs);
179 179
     }
180 180
 
181 181
 
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
             // generate label
257 257
             $label = ! empty($label) ? self::adminLabel($id, $label, $required) : '';
258 258
             // generate field name
259
-            $name = ! empty($unique_id) ? $field_name . '[' . $unique_id . ']' : $field_name;
259
+            $name = ! empty($unique_id) ? $field_name.'['.$unique_id.']' : $field_name;
260 260
 
261 261
             // we determine what we're building based on the type
262 262
             switch ($type) {
@@ -267,14 +267,14 @@  discard block
 block discarded – undo
267 267
                         foreach ($value as $key => $val) {
268 268
                             $c_input .= self::adminMulti(
269 269
                                 $default,
270
-                                isset($classes[ $key ]) ? $classes[ $key ] : '',
271
-                                $field_name . '_' . $value,
270
+                                isset($classes[$key]) ? $classes[$key] : '',
271
+                                $field_name.'_'.$value,
272 272
                                 $name,
273 273
                                 $required,
274 274
                                 $tab_index,
275 275
                                 $type,
276 276
                                 $val,
277
-                                isset($labels[ $key ]) ? $labels[ $key ] : ''
277
+                                isset($labels[$key]) ? $labels[$key] : ''
278 278
                             );
279 279
                         }
280 280
                         $field = $c_input;
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
                 case 'select':
301 301
                     $options = [];
302 302
                     foreach ($value as $key => $val) {
303
-                        $options[ $val ] = isset($labels[ $key ]) ? $labels[ $key ] : '';
303
+                        $options[$val] = isset($labels[$key]) ? $labels[$key] : '';
304 304
                     }
305 305
                     $field = self::adminSelect($default, $class, $id, $name, $required, $tab_index, $options);
306 306
                     break;
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
                     $field = self::adminText($class, $id, $name, $required, $tab_index, $value);
327 327
             }
328 328
 
329
-            $form_fields[ $field_name ] = ['label' => $label, 'field' => $field . $extra_desc];
329
+            $form_fields[$field_name] = ['label' => $label, 'field' => $field.$extra_desc];
330 330
         }
331 331
 
332 332
         return $form_fields;
@@ -344,8 +344,8 @@  discard block
 block discarded – undo
344 344
     private static function adminHidden($class, $id, $name, $value)
345 345
     {
346 346
         return "
347
-        <input name='" . esc_attr($name) . "' type='hidden' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' 
348
-        value='" . esc_attr($value) . "' />";
347
+        <input name='" . esc_attr($name)."' type='hidden' id='".esc_attr($id)."' class='".esc_attr($class)."' 
348
+        value='" . esc_attr($value)."' />";
349 349
     }
350 350
 
351 351
 
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
     private static function adminLabel($id, $label, $required)
360 360
     {
361 361
         $required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? " <span>*</span>" : '';
362
-        return "<label for='" . esc_attr($id) . "'>" . esc_html($label) . $required . "</label>";
362
+        return "<label for='".esc_attr($id)."'>".esc_html($label).$required."</label>";
363 363
     }
364 364
 
365 365
 
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
         $checked   = ! empty($default) && $default == $value ? 'checked ' : '';
382 382
         $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
383 383
         $input     = "
384
-        <input name='" . esc_attr($name) . "[]' type='" . esc_attr($type) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' value='" . esc_attr($value) . "' {$checked} {$required} tabindex='" . absint($tab_index) . "'/>";
384
+        <input name='" . esc_attr($name)."[]' type='".esc_attr($type)."' id='".esc_attr($id)."' class='".esc_attr($class)."' value='".esc_attr($value)."' {$checked} {$required} tabindex='".absint($tab_index)."'/>";
385 385
         if ($label === '') {
386 386
             return $input;
387 387
         }
@@ -411,13 +411,13 @@  discard block
 block discarded – undo
411 411
         foreach ($options as $value => $label) {
412 412
             $selected        = ! empty($default) && $default == $value ? 'selected' : '';
413 413
             $label           = wp_strip_all_tags($label);
414
-            $options_array[] = "<option value='" . esc_attr($value) . "' {$selected}>{$label}</option>";
414
+            $options_array[] = "<option value='".esc_attr($value)."' {$selected}>{$label}</option>";
415 415
         }
416 416
         $options_html = implode("\n", $options_array);
417 417
         $required     = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
418 418
         return "
419
-        <select name='" . esc_attr($name) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' {$required} 
420
-        tabindex='" . absint($tab_index) . "'>
419
+        <select name='" . esc_attr($name)."' id='".esc_attr($id)."' class='".esc_attr($class)."' {$required} 
420
+        tabindex='".absint($tab_index)."'>
421 421
             {$options_html}
422 422
         </select>";
423 423
     }
@@ -435,10 +435,10 @@  discard block
 block discarded – undo
435 435
      */
436 436
     private static function adminText($class, $id, $name, $required, $tab_index, $value)
437 437
     {
438
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
438
+        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
439 439
         return "
440
-        <input name='" . esc_attr($name) . "' type='text' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' 
441
-        value='" . esc_attr($value) . "' {$required} tabindex='" . absint($tab_index) . "'/>";
440
+        <input name='" . esc_attr($name)."' type='text' id='".esc_attr($id)."' class='".esc_attr($class)."' 
441
+        value='" . esc_attr($value)."' {$required} tabindex='".absint($tab_index)."'/>";
442 442
     }
443 443
 
444 444
 
@@ -456,9 +456,9 @@  discard block
 block discarded – undo
456 456
      */
457 457
     private static function adminTextarea($class, $cols, $id, $name, $required, $rows, $tab_index, $value)
458 458
     {
459
-        $required  = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
459
+        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN) ? 'required' : '';
460 460
         return "
461
-        <textarea name='" . esc_attr($name) . "' id='" . esc_attr($id) . "' class='" . esc_attr($class) . "' rows='" . absint($rows) . "' cols='" . absint($cols) . "' {$required} tabindex='" . absint($tab_index) . "'>" . esc_textarea($value) . "</textarea>";
461
+        <textarea name='" . esc_attr($name)."' id='".esc_attr($id)."' class='".esc_attr($class)."' rows='".absint($rows)."' cols='".absint($cols)."' {$required} tabindex='".absint($tab_index)."'>".esc_textarea($value)."</textarea>";
462 462
     }
463 463
 
464 464
 
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
     public static function select_input($name, $values, $default = '', $parameters = '', $class = '', $autosize = true)
511 511
     {
512 512
         // if $values was submitted in the wrong format, convert it over
513
-        if (! empty($values) && (! array_key_exists(0, $values) || ! is_array($values[0]))) {
513
+        if ( ! empty($values) && ( ! array_key_exists(0, $values) || ! is_array($values[0]))) {
514 514
             $converted_values = [];
515 515
             foreach ($values as $id => $text) {
516 516
                 $converted_values[] = ['id' => $id, 'text' => $text];
@@ -519,18 +519,18 @@  discard block
 block discarded – undo
519 519
         }
520 520
 
521 521
         $field =
522
-            '<select id="' . EEH_Formatter::ee_tep_output_string($name)
523
-            . '" name="' . EEH_Formatter::ee_tep_output_string($name)
522
+            '<select id="'.EEH_Formatter::ee_tep_output_string($name)
523
+            . '" name="'.EEH_Formatter::ee_tep_output_string($name)
524 524
             . '"';
525 525
 
526 526
         if (EEH_Formatter::ee_tep_not_null($parameters)) {
527
-            $field .= ' ' . $parameters;
527
+            $field .= ' '.$parameters;
528 528
         }
529 529
         if ($autosize) {
530 530
             $size = 'med';
531 531
             for ($ii = 0, $ni = sizeof($values); $ii < $ni; $ii++) {
532
-                if ($values[ $ii ]['text']) {
533
-                    if (strlen($values[ $ii ]['text']) > 5) {
532
+                if ($values[$ii]['text']) {
533
+                    if (strlen($values[$ii]['text']) > 5) {
534 534
                         $size = 'wide';
535 535
                     }
536 536
                 }
@@ -539,22 +539,22 @@  discard block
 block discarded – undo
539 539
             $size = '';
540 540
         }
541 541
 
542
-        $field .= ' class="' . $class . ' ' . $size . '">';
542
+        $field .= ' class="'.$class.' '.$size.'">';
543 543
 
544
-        if (empty($default) && isset($GLOBALS[ $name ])) {
545
-            $default = stripslashes($GLOBALS[ $name ]);
544
+        if (empty($default) && isset($GLOBALS[$name])) {
545
+            $default = stripslashes($GLOBALS[$name]);
546 546
         }
547 547
 
548 548
 
549 549
         for ($i = 0, $n = sizeof($values); $i < $n; $i++) {
550
-            $field .= '<option value="' . $values[ $i ]['id'] . '"';
551
-            if ($default == $values[ $i ]['id']) {
550
+            $field .= '<option value="'.$values[$i]['id'].'"';
551
+            if ($default == $values[$i]['id']) {
552 552
                 $field .= ' selected = "selected"';
553 553
             }
554
-            if (isset($values[ $i ]['class'])) {
555
-                $field .= ' class="' . $values[ $i ]['class'] . '"';
554
+            if (isset($values[$i]['class'])) {
555
+                $field .= ' class="'.$values[$i]['class'].'"';
556 556
             }
557
-            $field .= '>' . $values[ $i ]['text'] . '</option>';
557
+            $field .= '>'.$values[$i]['text'].'</option>';
558 558
         }
559 559
         $field .= '</select>';
560 560
 
@@ -580,11 +580,11 @@  discard block
 block discarded – undo
580 580
         $after_question_group_questions  =
581 581
             apply_filters('FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', '');
582 582
 
583
-        if (! empty($question_groups)) {
583
+        if ( ! empty($question_groups)) {
584 584
             // loop thru question groups
585 585
             foreach ($question_groups as $QSG) {
586 586
                 // check that questions exist
587
-                if (! empty($QSG['QSG_questions'])) {
587
+                if ( ! empty($QSG['QSG_questions'])) {
588 588
                     // use fieldsets
589 589
                     $html .= "\n\t"
590 590
                              . '<'
@@ -609,7 +609,7 @@  discard block
 block discarded – undo
609 609
                     $html .= $before_question_group_questions;
610 610
                     // loop thru questions
611 611
                     foreach ($QSG['QSG_questions'] as $question) {
612
-                        $QFI  = new EE_Question_Form_Input(
612
+                        $QFI = new EE_Question_Form_Input(
613 613
                             $question['qst_obj'],
614 614
                             $question['ans_obj'],
615 615
                             $question
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
                         $html .= self::generate_form_input($QFI);
618 618
                     }
619 619
                     $html .= $after_question_group_questions;
620
-                    $html .= "\n\t" . '</' . $group_wrapper . '>';
620
+                    $html .= "\n\t".'</'.$group_wrapper.'>';
621 621
                 }
622 622
             }
623 623
         }
@@ -657,25 +657,25 @@  discard block
 block discarded – undo
657 657
             'input_id'    => '',
658 658
             'input_class' => '',
659 659
         ];
660
-        $q_meta         = array_merge($default_q_meta, $q_meta);
660
+        $q_meta = array_merge($default_q_meta, $q_meta);
661 661
 
662
-        if (! empty($question_groups)) {
662
+        if ( ! empty($question_groups)) {
663 663
             // loop thru question groups
664 664
             foreach ($question_groups as $QSG) {
665 665
                 if ($QSG instanceof EE_Question_Group) {
666 666
                     // check that questions exist
667 667
 
668 668
                     $where = ['QST_deleted' => 0];
669
-                    if (! $from_admin) {
669
+                    if ( ! $from_admin) {
670 670
                         $where['QST_admin_only'] = 0;
671 671
                     }
672 672
                     $questions =
673 673
                         $QSG->questions([$where, 'order_by' => ['Question_Group_Question.QGQ_order' => 'ASC']]);
674
-                    if (! empty($questions)) {
674
+                    if ( ! empty($questions)) {
675 675
                         // use fieldsets
676 676
                         $html .= "\n\t"
677
-                                 . '<' . $group_wrapper . ' class="espresso-question-group-wrap" '
678
-                                 . 'id="' . $QSG->get('QSG_identifier') . '">';
677
+                                 . '<'.$group_wrapper.' class="espresso-question-group-wrap" '
678
+                                 . 'id="'.$QSG->get('QSG_identifier').'">';
679 679
                         // group_name
680 680
                         if ($QSG->show_group_name()) {
681 681
                             $html .= "\n\t\t"
@@ -700,21 +700,21 @@  discard block
 block discarded – undo
700 700
                             /** @var RequestInterface $request */
701 701
                             $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
702 702
                             $request_qstn = $request->getRequestParam('qstn', [], 'string', true);
703
-                            if (! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
703
+                            if ( ! empty($request_qstn) && isset($q_meta['input_id']) && isset($q_meta['att_nmbr'])) {
704 704
                                 // check for answer in $request_qstn in case we are reprocessing a form after an error
705
-                                if (isset($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])) {
706
-                                    $answer = is_array($request_qstn[ $q_meta['input_id'] ][ $qstn_id ])
707
-                                        ? $request_qstn[ $q_meta['input_id'] ][ $qstn_id ]
708
-                                        : sanitize_text_field($request_qstn[ $q_meta['input_id'] ][ $qstn_id ]);
705
+                                if (isset($request_qstn[$q_meta['input_id']][$qstn_id])) {
706
+                                    $answer = is_array($request_qstn[$q_meta['input_id']][$qstn_id])
707
+                                        ? $request_qstn[$q_meta['input_id']][$qstn_id]
708
+                                        : sanitize_text_field($request_qstn[$q_meta['input_id']][$qstn_id]);
709 709
                                 }
710 710
                             } elseif (isset($q_meta['attendee']) && $q_meta['attendee']) {
711 711
                                 // attendee data from the session
712 712
                                 $answer =
713
-                                    isset($q_meta['attendee'][ $qstn_id ]) ? $q_meta['attendee'][ $qstn_id ] : null;
713
+                                    isset($q_meta['attendee'][$qstn_id]) ? $q_meta['attendee'][$qstn_id] : null;
714 714
                             }
715 715
 
716 716
 
717
-                            $QFI  = new EE_Question_Form_Input(
717
+                            $QFI = new EE_Question_Form_Input(
718 718
                                 $QST,
719 719
                                 EE_Answer::new_instance(
720 720
                                     [
@@ -729,7 +729,7 @@  discard block
 block discarded – undo
729 729
                             $html .= self::generate_form_input($QFI);
730 730
                         }
731 731
                         $html .= $after_question_group_questions;
732
-                        $html .= "\n\t" . '</' . $group_wrapper . '>';
732
+                        $html .= "\n\t".'</'.$group_wrapper.'>';
733 733
                     }
734 734
                 }
735 735
             }
@@ -777,7 +777,7 @@  discard block
 block discarded – undo
777 777
             $QFI->get('QST_required_text') != ''
778 778
                 ? $QFI->get('QST_required_text')
779 779
                 : esc_html__('This field is required', 'event_espresso');
780
-        $required_text     = $QST_required
780
+        $required_text = $QST_required
781 781
             ? "\n\t\t\t"
782 782
               . '<div class="required-text hidden">'
783 783
               . self::prep_answer($required_text, $use_html_entities)
@@ -923,7 +923,7 @@  discard block
 block discarded – undo
923 923
         $use_html_entities = true
924 924
     ) {
925 925
         // need these
926
-        if (! $question || ! $name) {
926
+        if ( ! $question || ! $name) {
927 927
             return null;
928 928
         }
929 929
         // prep the answer
@@ -935,13 +935,13 @@  discard block
 block discarded – undo
935 935
         // ya gots ta have style man!!!
936 936
         $txt_class = is_admin() ? 'regular-text' : 'espresso-text-inp';
937 937
         $class     = empty($class) ? $txt_class : $class;
938
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
938
+        $class     .= ! empty($system_ID) ? ' '.$system_ID : '';
939 939
         $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
940 940
 
941 941
         $label_html =
942 942
             $required_text
943 943
             . "\n\t\t\t"
944
-            . '<label for="' . $name . '" class="' . $label_class . '">'
944
+            . '<label for="'.$name.'" class="'.$label_class.'">'
945 945
             . self::prep_question($question)
946 946
             . $required['label']
947 947
             . '</label><br/>';
@@ -950,12 +950,12 @@  discard block
 block discarded – undo
950 950
 
951 951
         $input_html =
952 952
             "\n\t\t\t"
953
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
954
-            . 'class="' . $class . ' ' . $required['class'] . '" value="' . esc_attr($answer) . '"  '
955
-            . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
953
+            . '<input type="text" name="'.$name.'" id="'.$id.'" '
954
+            . 'class="'.$class.' '.$required['class'].'" value="'.esc_attr($answer).'"  '
955
+            . 'title="'.esc_attr($required['msg']).'" '.$disabled.' '.$extra.'/>';
956 956
 
957 957
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
958
-        return $label_html . $input_html;
958
+        return $label_html.$input_html;
959 959
     }
960 960
 
961 961
 
@@ -989,7 +989,7 @@  discard block
 block discarded – undo
989 989
         $use_html_entities = true
990 990
     ) {
991 991
         // need these
992
-        if (! $question || ! $name) {
992
+        if ( ! $question || ! $name) {
993 993
             return null;
994 994
         }
995 995
         // prep the answer
@@ -1005,13 +1005,13 @@  discard block
 block discarded – undo
1005 1005
         // ya gots ta have style man!!!
1006 1006
         $txt_class = is_admin() ? 'regular-text' : 'espresso-textarea-inp';
1007 1007
         $class     = empty($class) ? $txt_class : $class;
1008
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1008
+        $class     .= ! empty($system_ID) ? ' '.$system_ID : '';
1009 1009
         $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1010 1010
 
1011 1011
         $label_html =
1012 1012
             $required_text
1013 1013
             . "\n\t\t\t"
1014
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1014
+            . '<label for="'.$name.'" class="'.$label_class.'">'
1015 1015
             . self::prep_question($question)
1016 1016
             . $required['label']
1017 1017
             . '</label><br/>';
@@ -1020,14 +1020,14 @@  discard block
 block discarded – undo
1020 1020
 
1021 1021
         $input_html =
1022 1022
             "\n\t\t\t"
1023
-            . '<textarea name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1024
-            . 'rows="' . $dimensions['rows'] . '" cols="' . $dimensions['cols'] . '"  '
1025
-            . 'title="' . $required['msg'] . '" ' . $disabled . ' ' . $extra . '>'
1023
+            . '<textarea name="'.$name.'" id="'.$id.'" class="'.$class.' '.$required['class'].'" '
1024
+            . 'rows="'.$dimensions['rows'].'" cols="'.$dimensions['cols'].'"  '
1025
+            . 'title="'.$required['msg'].'" '.$disabled.' '.$extra.'>'
1026 1026
             . esc_textarea($answer)
1027 1027
             . '</textarea>';
1028 1028
 
1029 1029
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1030
-        return $label_html . $input_html;
1030
+        return $label_html.$input_html;
1031 1031
     }
1032 1032
 
1033 1033
 
@@ -1064,7 +1064,7 @@  discard block
 block discarded – undo
1064 1064
     ) {
1065 1065
 
1066 1066
         // need these
1067
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1067
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1068 1068
             return null;
1069 1069
         }
1070 1070
         // prep the answer
@@ -1082,13 +1082,13 @@  discard block
 block discarded – undo
1082 1082
         // ya gots ta have style man!!!
1083 1083
         $txt_class = is_admin() ? 'wide' : 'espresso-select-inp';
1084 1084
         $class     = empty($class) ? $txt_class : $class;
1085
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1085
+        $class     .= ! empty($system_ID) ? ' '.$system_ID : '';
1086 1086
         $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1087 1087
 
1088 1088
         $label_html =
1089 1089
             $required_text
1090 1090
             . "\n\t\t\t"
1091
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1091
+            . '<label for="'.$name.'" class="'.$label_class.'">'
1092 1092
             . self::prep_question($question)
1093 1093
             . $required['label']
1094 1094
             . '</label><br/>';
@@ -1097,16 +1097,16 @@  discard block
 block discarded – undo
1097 1097
 
1098 1098
         $input_html =
1099 1099
             "\n\t\t\t"
1100
-            . '<select name="' . $name . '" id="' . $id . '" class="' . $class . ' ' . $required['class'] . '" '
1101
-            . 'title="' . esc_attr($required['msg']) . '"' . $disabled . ' ' . $extra . '>';
1100
+            . '<select name="'.$name.'" id="'.$id.'" class="'.$class.' '.$required['class'].'" '
1101
+            . 'title="'.esc_attr($required['msg']).'"'.$disabled.' '.$extra.'>';
1102 1102
         // recursively count array elements, to determine total number of options
1103 1103
         $only_option = count($options, 1) == 1;
1104
-        if (! $only_option) {
1104
+        if ( ! $only_option) {
1105 1105
             // if there is NO answer set and there are multiple options to choose from, then set the "please select" message as selected
1106
-            $selected   = $answer === null ? ' selected' : '';
1106
+            $selected = $answer === null ? ' selected' : '';
1107 1107
             $input_html .= $add_please_select_option
1108 1108
                 ? "\n\t\t\t\t"
1109
-                  . '<option value=""' . $selected . '>'
1109
+                  . '<option value=""'.$selected.'>'
1110 1110
                   . esc_html__(' - please select - ', 'event_espresso')
1111 1111
                   . '</option>'
1112 1112
                 : '';
@@ -1129,7 +1129,7 @@  discard block
 block discarded – undo
1129 1129
                 );
1130 1130
         }
1131 1131
 
1132
-        $input_html .= "\n\t\t\t" . '</select>';
1132
+        $input_html .= "\n\t\t\t".'</select>';
1133 1133
 
1134 1134
         $input_html =
1135 1135
             apply_filters(
@@ -1144,7 +1144,7 @@  discard block
 block discarded – undo
1144 1144
             );
1145 1145
 
1146 1146
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1147
-        return $label_html . $input_html;
1147
+        return $label_html.$input_html;
1148 1148
     }
1149 1149
 
1150 1150
 
@@ -1162,11 +1162,11 @@  discard block
 block discarded – undo
1162 1162
      */
1163 1163
     private static function _generate_select_option_group($opt_group, $QSOs, $answer, $use_html_entities = true)
1164 1164
     {
1165
-        $html = "\n\t\t\t\t" . '<optgroup label="' . self::prep_option_value($opt_group) . '">';
1165
+        $html = "\n\t\t\t\t".'<optgroup label="'.self::prep_option_value($opt_group).'">';
1166 1166
         foreach ($QSOs as $QSO) {
1167 1167
             $html .= self::_generate_select_option($QSO->value(), $QSO->desc(), $answer, false, $use_html_entities);
1168 1168
         }
1169
-        $html .= "\n\t\t\t\t" . '</optgroup>';
1169
+        $html .= "\n\t\t\t\t".'</optgroup>';
1170 1170
         return $html;
1171 1171
     }
1172 1172
 
@@ -1193,7 +1193,7 @@  discard block
 block discarded – undo
1193 1193
         $value    = ! empty($value) ? $value : $key;
1194 1194
         $selected = ($answer == $key || $only_option) ? 'selected' : '';
1195 1195
         return "\n\t\t\t\t"
1196
-               . '<option value="' . self::prep_option_value($key) . '" ' . $selected . '> '
1196
+               . '<option value="'.self::prep_option_value($key).'" '.$selected.'> '
1197 1197
                . $value
1198 1198
                . '&nbsp;&nbsp;&nbsp;</option>';
1199 1199
     }
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
         $use_desc_4_label = false
1238 1238
     ) {
1239 1239
         // need these
1240
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1240
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1241 1241
             return null;
1242 1242
         }
1243 1243
         // prep the answer
@@ -1254,7 +1254,7 @@  discard block
 block discarded – undo
1254 1254
         $label_html =
1255 1255
             $required_text
1256 1256
             . "\n\t\t\t"
1257
-            . '<label class="' . $label_class . '">'
1257
+            . '<label class="'.$label_class.'">'
1258 1258
             . self::prep_question($question)
1259 1259
             . $required['label']
1260 1260
             . '</label> ';
@@ -1263,49 +1263,49 @@  discard block
 block discarded – undo
1263 1263
 
1264 1264
         $input_html =
1265 1265
             "\n\t\t\t"
1266
-            . '<ul id="' . $id . '-ul" class="espresso-radio-btn-options-ul ' . $label_class . ' ' . $class . '-ul">';
1266
+            . '<ul id="'.$id.'-ul" class="espresso-radio-btn-options-ul '.$label_class.' '.$class.'-ul">';
1267 1267
 
1268
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1269
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1268
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1269
+        $class .= ! empty($required['class']) ? ' '.$required['class'] : '';
1270 1270
 
1271 1271
         foreach ($options as $OPT) {
1272 1272
             if ($OPT instanceof EE_Question_Option) {
1273 1273
                 $value   = self::prep_option_value($OPT->value());
1274 1274
                 $label   = $use_desc_4_label ? $OPT->desc() : $OPT->value();
1275 1275
                 $size    = $use_desc_4_label
1276
-                    ? self::get_label_size_class($OPT->value() . ' ' . $OPT->desc())
1276
+                    ? self::get_label_size_class($OPT->value().' '.$OPT->desc())
1277 1277
                     : self::get_label_size_class($OPT->value());
1278
-                $desc    = $OPT->desc();// no self::prep_answer
1278
+                $desc    = $OPT->desc(); // no self::prep_answer
1279 1279
                 $answer  = is_numeric($value) && empty($answer) ? 0 : $answer;
1280 1280
                 $checked = (string) $value == (string) $answer ? ' checked' : '';
1281
-                $opt     = '-' . sanitize_key($value);
1281
+                $opt     = '-'.sanitize_key($value);
1282 1282
 
1283
-                $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1284
-                $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-radio-btn-lbl">';
1285
-                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $label . '</span>' : '';
1283
+                $input_html .= "\n\t\t\t\t".'<li'.$size.'>';
1284
+                $input_html .= "\n\t\t\t\t\t".'<label class="'.$radio_class.' espresso-radio-btn-lbl">';
1285
+                $input_html .= $label_b4 ? "\n\t\t\t\t\t\t".'<span>'.$label.'</span>' : '';
1286 1286
                 $input_html .= "\n\t\t\t\t\t\t"
1287
-                               . '<input type="radio" name="' . $name . '" id="' . $id . $opt . '" '
1288
-                               . 'class="' . $class . '" value="' . $value . '" '
1289
-                               . 'title="' . esc_attr($required['msg']) . '" ' . $disabled
1290
-                               . $checked . ' ' . $extra . '/>';
1287
+                               . '<input type="radio" name="'.$name.'" id="'.$id.$opt.'" '
1288
+                               . 'class="'.$class.'" value="'.$value.'" '
1289
+                               . 'title="'.esc_attr($required['msg']).'" '.$disabled
1290
+                               . $checked.' '.$extra.'/>';
1291 1291
                 $input_html .= ! $label_b4
1292 1292
                     ? "\n\t\t\t\t\t\t"
1293 1293
                       . '<span class="espresso-radio-btn-desc">'
1294 1294
                       . $label
1295 1295
                       . '</span>'
1296 1296
                     : '';
1297
-                $input_html .= "\n\t\t\t\t\t" . '</label>';
1297
+                $input_html .= "\n\t\t\t\t\t".'</label>';
1298 1298
                 $input_html .= $use_desc_4_label
1299 1299
                     ? ''
1300
-                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">' . $desc . '</span>';
1301
-                $input_html .= "\n\t\t\t\t" . '</li>';
1300
+                    : '<span class="espresso-radio-btn-option-desc small-text grey-text">'.$desc.'</span>';
1301
+                $input_html .= "\n\t\t\t\t".'</li>';
1302 1302
             }
1303 1303
         }
1304 1304
 
1305
-        $input_html .= "\n\t\t\t" . '</ul>';
1305
+        $input_html .= "\n\t\t\t".'</ul>';
1306 1306
 
1307 1307
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1308
-        return $label_html . $input_html;
1308
+        return $label_html.$input_html;
1309 1309
     }
1310 1310
 
1311 1311
 
@@ -1340,7 +1340,7 @@  discard block
 block discarded – undo
1340 1340
         $use_html_entities = true
1341 1341
     ) {
1342 1342
         // need these
1343
-        if (! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1343
+        if ( ! $question || ! $name || ! $options || empty($options) || ! is_array($options)) {
1344 1344
             return null;
1345 1345
         }
1346 1346
         $answer = maybe_unserialize($answer);
@@ -1350,7 +1350,7 @@  discard block
 block discarded – undo
1350 1350
 
1351 1351
         foreach ($answer as $key => $value) {
1352 1352
             $key            = self::prep_option_value($key);
1353
-            $answer[ $key ] = self::prep_answer($value, $use_html_entities);
1353
+            $answer[$key] = self::prep_answer($value, $use_html_entities);
1354 1354
         }
1355 1355
 
1356 1356
         // prep the required array
@@ -1365,7 +1365,7 @@  discard block
 block discarded – undo
1365 1365
         $label_html =
1366 1366
             $required_text
1367 1367
             . "\n\t\t\t"
1368
-            . '<label class="' . $label_class . '">'
1368
+            . '<label class="'.$label_class.'">'
1369 1369
             . self::prep_question($question)
1370 1370
             . $required['label']
1371 1371
             . '</label> ';
@@ -1374,42 +1374,42 @@  discard block
 block discarded – undo
1374 1374
 
1375 1375
         $input_html =
1376 1376
             "\n\t\t\t"
1377
-            . '<ul id="' . $id . '-ul" class="espresso-checkbox-options-ul ' . $label_class . ' ' . $class . '-ul">';
1377
+            . '<ul id="'.$id.'-ul" class="espresso-checkbox-options-ul '.$label_class.' '.$class.'-ul">';
1378 1378
 
1379
-        $class .= ! empty($system_ID) ? ' ' . $system_ID : '';
1380
-        $class .= ! empty($required['class']) ? ' ' . $required['class'] : '';
1379
+        $class .= ! empty($system_ID) ? ' '.$system_ID : '';
1380
+        $class .= ! empty($required['class']) ? ' '.$required['class'] : '';
1381 1381
 
1382 1382
         foreach ($options as $OPT) {
1383
-            $value = $OPT->value();// self::prep_option_value( $OPT->value() );
1384
-            $size  = self::get_label_size_class($OPT->value() . ' ' . $OPT->desc());
1383
+            $value = $OPT->value(); // self::prep_option_value( $OPT->value() );
1384
+            $size  = self::get_label_size_class($OPT->value().' '.$OPT->desc());
1385 1385
             $text  = self::prep_answer($OPT->value());
1386 1386
             $desc  = $OPT->desc();
1387
-            $opt   = '-' . sanitize_key($value);
1387
+            $opt   = '-'.sanitize_key($value);
1388 1388
 
1389 1389
             $checked = is_array($answer) && in_array($text, $answer) ? ' checked' : '';
1390 1390
 
1391
-            $input_html .= "\n\t\t\t\t" . '<li' . $size . '>';
1392
-            $input_html .= "\n\t\t\t\t\t" . '<label class="' . $radio_class . ' espresso-checkbox-lbl">';
1393
-            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1391
+            $input_html .= "\n\t\t\t\t".'<li'.$size.'>';
1392
+            $input_html .= "\n\t\t\t\t\t".'<label class="'.$radio_class.' espresso-checkbox-lbl">';
1393
+            $input_html .= $label_b4 ? "\n\t\t\t\t\t\t".'<span>'.$text.'</span>' : '';
1394 1394
             $input_html .= "\n\t\t\t\t\t\t"
1395
-                           . '<input type="checkbox" name="' . $name . '[' . $OPT->ID() . ']" '
1396
-                           . 'id="' . $id . $opt . '" class="' . $class . '" value="' . $value . '" '
1397
-                           . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . $checked . ' ' . $extra . '/>';
1398
-            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t" . '<span>' . $text . '</span>' : '';
1399
-            $input_html .= "\n\t\t\t\t\t" . '</label>';
1400
-            if (! empty($desc) && $desc != $text) {
1395
+                           . '<input type="checkbox" name="'.$name.'['.$OPT->ID().']" '
1396
+                           . 'id="'.$id.$opt.'" class="'.$class.'" value="'.$value.'" '
1397
+                           . 'title="'.esc_attr($required['msg']).'" '.$disabled.$checked.' '.$extra.'/>';
1398
+            $input_html .= ! $label_b4 ? "\n\t\t\t\t\t\t".'<span>'.$text.'</span>' : '';
1399
+            $input_html .= "\n\t\t\t\t\t".'</label>';
1400
+            if ( ! empty($desc) && $desc != $text) {
1401 1401
                 $input_html .= "\n\t\t\t\t\t"
1402 1402
                                . ' &nbsp; <br/><div class="espresso-checkbox-option-desc small-text grey-text">'
1403 1403
                                . $desc
1404 1404
                                . '</div>';
1405 1405
             }
1406
-            $input_html .= "\n\t\t\t\t" . '</li>';
1406
+            $input_html .= "\n\t\t\t\t".'</li>';
1407 1407
         }
1408 1408
 
1409
-        $input_html .= "\n\t\t\t" . '</ul>';
1409
+        $input_html .= "\n\t\t\t".'</ul>';
1410 1410
 
1411 1411
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1412
-        return $label_html . $input_html;
1412
+        return $label_html.$input_html;
1413 1413
     }
1414 1414
 
1415 1415
 
@@ -1441,7 +1441,7 @@  discard block
 block discarded – undo
1441 1441
         $use_html_entities = true
1442 1442
     ) {
1443 1443
         // need these
1444
-        if (! $question || ! $name) {
1444
+        if ( ! $question || ! $name) {
1445 1445
             return null;
1446 1446
         }
1447 1447
         // prep the answer
@@ -1453,13 +1453,13 @@  discard block
 block discarded – undo
1453 1453
         // ya gots ta have style man!!!
1454 1454
         $txt_class = is_admin() ? 'regular-text' : 'espresso-datepicker-inp';
1455 1455
         $class     = empty($class) ? $txt_class : $class;
1456
-        $class     .= ! empty($system_ID) ? ' ' . $system_ID : '';
1456
+        $class     .= ! empty($system_ID) ? ' '.$system_ID : '';
1457 1457
         $extra     = apply_filters('FHEE__EEH_Form_Fields__additional_form_field_attributes', '');
1458 1458
 
1459 1459
         $label_html =
1460 1460
             $required_text
1461 1461
             . "\n\t\t\t"
1462
-            . '<label for="' . $name . '" class="' . $label_class . '">'
1462
+            . '<label for="'.$name.'" class="'.$label_class.'">'
1463 1463
             . self::prep_question($question)
1464 1464
             . $required['label']
1465 1465
             . '</label><br/>';
@@ -1468,14 +1468,14 @@  discard block
 block discarded – undo
1468 1468
 
1469 1469
         $input_html =
1470 1470
             "\n\t\t\t"
1471
-            . '<input type="text" name="' . $name . '" id="' . $id . '" '
1472
-            . 'class="' . $class . ' ' . $required['class'] . ' datepicker" value="' . $answer . '"  '
1473
-            . 'title="' . esc_attr($required['msg']) . '" ' . $disabled . ' ' . $extra . '/>';
1471
+            . '<input type="text" name="'.$name.'" id="'.$id.'" '
1472
+            . 'class="'.$class.' '.$required['class'].' datepicker" value="'.$answer.'"  '
1473
+            . 'title="'.esc_attr($required['msg']).'" '.$disabled.' '.$extra.'/>';
1474 1474
 
1475 1475
         // enqueue scripts
1476 1476
         wp_register_style(
1477 1477
             'espresso-ui-theme',
1478
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1478
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1479 1479
             [],
1480 1480
             EVENT_ESPRESSO_VERSION
1481 1481
         );
@@ -1483,7 +1483,7 @@  discard block
 block discarded – undo
1483 1483
         wp_enqueue_script('jquery-ui-datepicker');
1484 1484
 
1485 1485
         $input_html = apply_filters('FHEE__EEH_Form_Fields__input_html', $input_html, $label_html, $id);
1486
-        return $label_html . $input_html;
1486
+        return $label_html.$input_html;
1487 1487
     }
1488 1488
 
1489 1489
 
@@ -1510,7 +1510,7 @@  discard block
 block discarded – undo
1510 1510
     public static function hidden_input($name, $value, $id = '')
1511 1511
     {
1512 1512
         $id = ! empty($id) ? $id : $name;
1513
-        return '<input id="' . $id . '" type="hidden" name="' . $name . '" value="' . $value . '"/>';
1513
+        return '<input id="'.$id.'" type="hidden" name="'.$name.'" value="'.$value.'"/>';
1514 1514
     }
1515 1515
 
1516 1516
 
@@ -1555,7 +1555,7 @@  discard block
 block discarded – undo
1555 1555
         $prepped_answer_options = [];
1556 1556
         if (is_array($QSOs) && ! empty($QSOs)) {
1557 1557
             foreach ($QSOs as $key => $QSO) {
1558
-                if (! $QSO instanceof EE_Question_Option) {
1558
+                if ( ! $QSO instanceof EE_Question_Option) {
1559 1559
                     $QSO = EE_Question_Option::new_instance(
1560 1560
                         [
1561 1561
                             'QSO_value' => is_array($QSO) && isset($QSO['id'])
@@ -1568,7 +1568,7 @@  discard block
 block discarded – undo
1568 1568
                     );
1569 1569
                 }
1570 1570
                 if ($QSO->opt_group()) {
1571
-                    $prepped_answer_options[ $QSO->opt_group() ][] = $QSO;
1571
+                    $prepped_answer_options[$QSO->opt_group()][] = $QSO;
1572 1572
                 } else {
1573 1573
                     $prepped_answer_options[] = $QSO;
1574 1574
                 }
@@ -1780,7 +1780,7 @@  discard block
 block discarded – undo
1780 1780
         $options = [];
1781 1781
         for ($x = 1; $x <= 12; $x++) {
1782 1782
             $mm             = str_pad($x, 2, '0', STR_PAD_LEFT);
1783
-            $options[ $mm ] = $mm;
1783
+            $options[$mm] = $mm;
1784 1784
         }
1785 1785
         return EEH_Form_Fields::prep_answer_options($options);
1786 1786
     }
@@ -1798,7 +1798,7 @@  discard block
 block discarded – undo
1798 1798
         $next_decade  = $current_year + 10;
1799 1799
         for ($x = $current_year; $x <= $next_decade; $x++) {
1800 1800
             $yy             = str_pad($x, 2, '0', STR_PAD_LEFT);
1801
-            $options[ $yy ] = $yy;
1801
+            $options[$yy] = $yy;
1802 1802
         }
1803 1803
         return EEH_Form_Fields::prep_answer_options($options);
1804 1804
     }
@@ -1817,7 +1817,7 @@  discard block
 block discarded – undo
1817 1817
     public static function generate_registration_months_dropdown($cur_date = '', $status = '', $evt_category = 0)
1818 1818
     {
1819 1819
         $_where = [];
1820
-        if (! empty($status)) {
1820
+        if ( ! empty($status)) {
1821 1821
             $_where['STS_ID'] = $status;
1822 1822
         }
1823 1823
 
@@ -1836,7 +1836,7 @@  discard block
 block discarded – undo
1836 1836
         ];
1837 1837
 
1838 1838
         foreach ($regdtts as $regdtt) {
1839
-            $date      = $regdtt->reg_month . ' ' . $regdtt->reg_year;
1839
+            $date      = $regdtt->reg_month.' '.$regdtt->reg_year;
1840 1840
             $options[] = [
1841 1841
                 'text' => $date,
1842 1842
                 'id'   => $date,
@@ -1885,7 +1885,7 @@  discard block
 block discarded – undo
1885 1885
         // categories?
1886 1886
 
1887 1887
 
1888
-        if (! empty($evt_category)) {
1888
+        if ( ! empty($evt_category)) {
1889 1889
             $where['Event.Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1890 1890
             $where['Event.Term_Taxonomy.term_id']  = $evt_category;
1891 1891
         }
@@ -1908,8 +1908,8 @@  discard block
 block discarded – undo
1908 1908
         global $wp_locale;
1909 1909
 
1910 1910
         foreach ($DTTS as $DTT) {
1911
-            $localized_date = $wp_locale->get_month($DTT->dtt_month_num) . ' ' . $DTT->dtt_year;
1912
-            $id             = $DTT->dtt_month . ' ' . $DTT->dtt_year;
1911
+            $localized_date = $wp_locale->get_month($DTT->dtt_month_num).' '.$DTT->dtt_year;
1912
+            $id             = $DTT->dtt_month.' '.$DTT->dtt_year;
1913 1913
             $options[]      = [
1914 1914
                 'text' => $localized_date,
1915 1915
                 'id'   => $id,
@@ -1982,16 +1982,16 @@  discard block
 block discarded – undo
1982 1982
             return $btn;
1983 1983
         }
1984 1984
         $text = ! empty($text) ? $text : esc_html__('Submit', 'event_espresso');
1985
-        $btn  .= '<input id="' . $ID . '-btn" class="' . $class . '" '
1986
-                 . 'type="submit" value="' . $text . '" ' . $extra_attributes . '/>';
1987
-        if (! $input_only) {
1988
-            $btn_frm = '<form id="' . $ID . '-frm" method="POST" action="' . $url . '">';
1985
+        $btn .= '<input id="'.$ID.'-btn" class="'.$class.'" '
1986
+                 . 'type="submit" value="'.$text.'" '.$extra_attributes.'/>';
1987
+        if ( ! $input_only) {
1988
+            $btn_frm = '<form id="'.$ID.'-frm" method="POST" action="'.$url.'">';
1989 1989
             $btn_frm .= ! empty($nonce_action)
1990
-                ? wp_nonce_field($nonce_action, $nonce_action . '_nonce', true, false)
1990
+                ? wp_nonce_field($nonce_action, $nonce_action.'_nonce', true, false)
1991 1991
                 : '';
1992 1992
             $btn_frm .= $btn;
1993 1993
             $btn_frm .= '</form>';
1994
-            $btn     = $btn_frm;
1994
+            $btn = $btn_frm;
1995 1995
             unset($btn_frm);
1996 1996
         }
1997 1997
         return $btn;
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Addon.lib.php 2 patches
Indentation   +1260 added lines, -1260 removed lines patch added patch discarded remove patch
@@ -22,1264 +22,1264 @@
 block discarded – undo
22 22
  */
23 23
 class EE_Register_Addon implements EEI_Plugin_API
24 24
 {
25
-    /**
26
-     * possibly truncated version of the EE core version string
27
-     *
28
-     * @var string
29
-     */
30
-    protected static $_core_version = '';
31
-
32
-    /**
33
-     * Holds values for registered addons
34
-     *
35
-     * @var array
36
-     */
37
-    protected static $_settings = array();
38
-
39
-    /**
40
-     * @var  array $_incompatible_addons keys are addon SLUGS
41
-     * (first argument passed to EE_Register_Addon::register()), keys are
42
-     * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
43
-     * Generally this should be used sparingly, as we don't want to muddle up
44
-     * EE core with knowledge of ALL the addons out there.
45
-     * If you want NO versions of an addon to run with a certain version of core,
46
-     * it's usually best to define the addon's "min_core_version" as part of its call
47
-     * to EE_Register_Addon::register(), rather than using this array with a super high value for its
48
-     * minimum plugin version.
49
-     * @access    protected
50
-     */
51
-    protected static $_incompatible_addons = array(
52
-        'Multi_Event_Registration' => '2.0.11.rc.002',
53
-        'Promotions'               => '1.0.0.rc.084',
54
-    );
55
-
56
-
57
-    /**
58
-     * We should always be comparing core to a version like '4.3.0.rc.000',
59
-     * not just '4.3.0'.
60
-     * So if the addon developer doesn't provide that full version string,
61
-     * fill in the blanks for them
62
-     *
63
-     * @param string $min_core_version
64
-     * @return string always like '4.3.0.rc.000'
65
-     */
66
-    protected static function _effective_version($min_core_version)
67
-    {
68
-        // versions: 4 . 3 . 1 . p . 123
69
-        // offsets:    0 . 1 . 2 . 3 . 4
70
-        $version_parts = explode('.', $min_core_version);
71
-        // check they specified the micro version (after 2nd period)
72
-        if (! isset($version_parts[2])) {
73
-            $version_parts[2] = '0';
74
-        }
75
-        // if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76
-        // soon we can assume that's 'rc', but this current version is 'alpha'
77
-        if (! isset($version_parts[3])) {
78
-            $version_parts[3] = 'dev';
79
-        }
80
-        if (! isset($version_parts[4])) {
81
-            $version_parts[4] = '000';
82
-        }
83
-        return implode('.', $version_parts);
84
-    }
85
-
86
-
87
-    /**
88
-     * Returns whether or not the min core version requirement of the addon is met
89
-     *
90
-     * @param string $min_core_version    the minimum core version required by the addon
91
-     * @param string $actual_core_version the actual core version, optional
92
-     * @return boolean
93
-     */
94
-    public static function _meets_min_core_version_requirement(
95
-        $min_core_version,
96
-        $actual_core_version = EVENT_ESPRESSO_VERSION
97
-    ) {
98
-        return version_compare(
99
-            self::_effective_version($actual_core_version),
100
-            self::_effective_version($min_core_version),
101
-            '>='
102
-        );
103
-    }
104
-
105
-
106
-    /**
107
-     * Method for registering new EE_Addons.
108
-     * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
109
-     * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
110
-     * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
111
-     * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
112
-     * 'activate_plugin', it registers the addon still, but its components are not registered
113
-     * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
114
-     * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
115
-     * (so that we can detect that the addon has activated on the subsequent request)
116
-     *
117
-     * @since    4.3.0
118
-     * @param string                  $addon_name                       [Required] the EE_Addon's name.
119
-     * @param  array                  $setup_args                       {
120
-     *                                                                  An array of arguments provided for registering
121
-     *                                                                  the message type.
122
-     * @type  string                  $class_name                       the addon's main file name.
123
-     *                                                                  If left blank, generated from the addon name,
124
-     *                                                                  changes something like "calendar" to
125
-     *                                                                  "EE_Calendar"
126
-     * @type string                   $min_core_version                 the minimum version of EE Core that the
127
-     *                                                                  addon will work with. eg "4.8.1.rc.084"
128
-     * @type string                   $version                          the "software" version for the addon. eg
129
-     *                                                                  "1.0.0.p" for a first stable release, or
130
-     *                                                                  "1.0.0.rc.043" for a version in progress
131
-     * @type string                   $main_file_path                   the full server path to the main file
132
-     *                                                                  loaded directly by WP
133
-     * @type DomainInterface $domain                                    child class of
134
-     *                                                                  EventEspresso\core\domain\DomainBase
135
-     * @type string                   $domain_fqcn                      Fully Qualified Class Name
136
-     *                                                                  for the addon's Domain class
137
-     *                                                                  (see EventEspresso\core\domain\Domain)
138
-     * @type string                   $admin_path                       full server path to the folder where the
139
-     *                                                                  addon\'s admin files reside
140
-     * @type string                   $admin_callback                   a method to be called when the EE Admin is
141
-     *                                                                  first invoked, can be used for hooking into
142
-     *                                                                  any admin page
143
-     * @type string                   $config_section                   the section name for this addon's
144
-     *                                                                  configuration settings section
145
-     *                                                                  (defaults to "addons")
146
-     * @type string                   $config_class                     the class name for this addon's
147
-     *                                                                  configuration settings object
148
-     * @type string                   $config_name                      the class name for this addon's
149
-     *                                                                  configuration settings object
150
-     * @type string                   $autoloader_paths                 [Required] an array of class names and the full
151
-     *                                                                  server paths to those files.
152
-     * @type string                   $autoloader_folders               an array of  "full server paths" for any
153
-     *                                                                  folders containing classes that might be
154
-     *                                                                  invoked by the addon
155
-     * @type string                   $dms_paths                        [Required] an array of full server paths to
156
-     *                                                                  folders that contain data migration scripts.
157
-     *                                                                  The key should be the EE_Addon class name that
158
-     *                                                                  this set of data migration scripts belongs to.
159
-     *                                                                  If the EE_Addon class is namespaced, then this
160
-     *                                                                  needs to be the Fully Qualified Class Name
161
-     * @type string                   $module_paths                     an array of full server paths to any
162
-     *                                                                  EED_Modules used by the addon
163
-     * @type string                   $shortcode_paths                  an array of full server paths to folders
164
-     *                                                                  that contain EES_Shortcodes
165
-     * @type string                   $widget_paths                     an array of full server paths to folders
166
-     *                                                                  that contain WP_Widgets
167
-     * @type string                   $pue_options
168
-     * @type array                    $capabilities                     an array indexed by role name
169
-     *                                                                  (i.e administrator,author ) and the values
170
-     *                                                                  are an array of caps to add to the role.
171
-     *                                                                  'administrator' => array(
172
-     *                                                                  'read_addon',
173
-     *                                                                  'edit_addon',
174
-     *                                                                  etc.
175
-     *                                                                  ).
176
-     * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
177
-     *                                                                  for any addons that need to register any
178
-     *                                                                  special meta mapped capabilities.  Should
179
-     *                                                                  be indexed where the key is the
180
-     *                                                                  EE_Meta_Capability_Map class name and the
181
-     *                                                                  values are the arguments sent to the class.
182
-     * @type array                    $model_paths                      array of folders containing DB models
183
-     * @see      EE_Register_Model
184
-     * @type array                    $class_paths                      array of folders containing DB classes
185
-     * @see      EE_Register_Model
186
-     * @type array                    $model_extension_paths            array of folders containing DB model
187
-     *                                                                  extensions
188
-     * @see      EE_Register_Model_Extension
189
-     * @type array                    $class_extension_paths            array of folders containing DB class
190
-     *                                                                  extensions
191
-     * @see      EE_Register_Model_Extension
192
-     * @type array message_types {
193
-     *                                                                  An array of message types with the key as
194
-     *                                                                  the message type name and the values as
195
-     *                                                                  below:
196
-     * @type string                   $mtfilename                       [Required] The filename of the message type
197
-     *                                                                  being registered. This will be the main
198
-     *                                                                  EE_{Message Type Name}_message_type class.
199
-     *                                                                  for example:
200
-     *                                                                  EE_Declined_Registration_message_type.class.php
201
-     * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
202
-     *                                                                  messages autoloader for the new message type.
203
-     * @type array                    $messengers_to_activate_with      An array of messengers that this message
204
-     *                                                                  type should activate with. Each value in
205
-     *                                                                  the
206
-     *                                                                  array
207
-     *                                                                  should match the name property of a
208
-     *                                                                  EE_messenger. Optional.
209
-     * @type array                    $messengers_to_validate_with      An array of messengers that this message
210
-     *                                                                  type should validate with. Each value in
211
-     *                                                                  the
212
-     *                                                                  array
213
-     *                                                                  should match the name property of an
214
-     *                                                                  EE_messenger.
215
-     *                                                                  Optional.
216
-     *                                                                  }
217
-     * @type array                    $custom_post_types
218
-     * @type array                    $custom_taxonomies
219
-     * @type array                    $payment_method_paths             each element is the folder containing the
220
-     *                                                                  EE_PMT_Base child class
221
-     *                                                                  (eg,
222
-     *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
223
-     *                                                                  which contains the files
224
-     *                                                                  EE_PMT_Payomatic.pm.php)
225
-     * @type array                    $default_terms
226
-     * @type array                    $namespace                        {
227
-     *                                                                  An array with two items for registering the
228
-     *                                                                  addon's namespace. (If, for some reason, you
229
-     *                                                                  require additional namespaces,
230
-     *                                                                  use
231
-     *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
232
-     *                                                                  directly)
233
-     * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
234
-     * @type string                   $FQNS                             the namespace prefix
235
-     * @type string                   $DIR                              a base directory for class files in the
236
-     *                                                                  namespace.
237
-     *                                                                  }
238
-     *                                                                  }
239
-     * @type string                   $privacy_policies                 FQNSs (namespaces, each of which contains only
240
-     *                                                                  privacy policy classes) or FQCNs (specific
241
-     *                                                                  classnames of privacy policy classes)
242
-     * @type string                   $personal_data_exporters          FQNSs (namespaces, each of which contains only
243
-     *                                                                  privacy policy classes) or FQCNs (specific
244
-     *                                                                  classnames of privacy policy classes)
245
-     * @type string                   $personal_data_erasers            FQNSs (namespaces, each of which contains only
246
-     *                                                                  privacy policy classes) or FQCNs (specific
247
-     *                                                                  classnames of privacy policy classes)
248
-     * @return void
249
-     * @throws DomainException
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws InvalidDataTypeException
253
-     * @throws InvalidInterfaceException
254
-     */
255
-    public static function register($addon_name = '', array $setup_args = array())
256
-    {
257
-        // required fields MUST be present, so let's make sure they are.
258
-        EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
259
-        // get class name for addon
260
-        $class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
261
-        // setup $_settings array from incoming values.
262
-        $addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
263
-        // setup PUE
264
-        EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
265
-        // does this addon work with this version of core or WordPress ?
266
-        // does this addon work with this version of core or WordPress ?
267
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268
-            return;
269
-        }
270
-        // register namespaces
271
-        EE_Register_Addon::_setup_namespaces($addon_settings);
272
-        // check if this is an activation request
273
-        if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
274
-            // dont bother setting up the rest of the addon atm
275
-            return;
276
-        }
277
-        // we need cars
278
-        EE_Register_Addon::_setup_autoloaders($addon_name);
279
-        // register new models and extensions
280
-        EE_Register_Addon::_register_models_and_extensions($addon_name);
281
-        // setup DMS
282
-        EE_Register_Addon::_register_data_migration_scripts($addon_name);
283
-        // if config_class is present let's register config.
284
-        EE_Register_Addon::_register_config($addon_name);
285
-        // register admin pages
286
-        EE_Register_Addon::_register_admin_pages($addon_name);
287
-        // add to list of modules to be registered
288
-        EE_Register_Addon::_register_modules($addon_name);
289
-        // add to list of shortcodes to be registered
290
-        EE_Register_Addon::_register_shortcodes($addon_name);
291
-        // add to list of widgets to be registered
292
-        EE_Register_Addon::_register_widgets($addon_name);
293
-        // register capability related stuff.
294
-        EE_Register_Addon::_register_capabilities($addon_name);
295
-        // any message type to register?
296
-        EE_Register_Addon::_register_message_types($addon_name);
297
-        // any custom post type/ custom capabilities or default terms to register
298
-        EE_Register_Addon::_register_custom_post_types($addon_name);
299
-        // and any payment methods
300
-        EE_Register_Addon::_register_payment_methods($addon_name);
301
-        // and privacy policy generators
302
-        EE_Register_Addon::registerPrivacyPolicies($addon_name);
303
-        // and privacy policy generators
304
-        EE_Register_Addon::registerPersonalDataExporters($addon_name);
305
-        // and privacy policy generators
306
-        EE_Register_Addon::registerPersonalDataErasers($addon_name);
307
-        // load and instantiate main addon class
308
-        $addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
309
-        // delay calling after_registration hook on each addon until after all add-ons have been registered.
310
-        add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
311
-    }
312
-
313
-
314
-    /**
315
-     * @param string $addon_name
316
-     * @param array  $setup_args
317
-     * @return void
318
-     * @throws EE_Error
319
-     */
320
-    private static function _verify_parameters($addon_name, array $setup_args)
321
-    {
322
-        // required fields MUST be present, so let's make sure they are.
323
-        if (empty($addon_name) || ! is_array($setup_args)) {
324
-            throw new EE_Error(
325
-                esc_html__(
326
-                    'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
327
-                    'event_espresso'
328
-                )
329
-            );
330
-        }
331
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332
-            throw new EE_Error(
333
-                sprintf(
334
-                    esc_html__(
335
-                        'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
336
-                        'event_espresso'
337
-                    ),
338
-                    implode(',', array_keys($setup_args))
339
-                )
340
-            );
341
-        }
342
-        // check that addon has not already been registered with that name
343
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
344
-            throw new EE_Error(
345
-                sprintf(
346
-                    esc_html__(
347
-                        'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
348
-                        'event_espresso'
349
-                    ),
350
-                    $addon_name
351
-                )
352
-            );
353
-        }
354
-    }
355
-
356
-
357
-    /**
358
-     * @param string $addon_name
359
-     * @param array  $setup_args
360
-     * @return string
361
-     */
362
-    private static function _parse_class_name($addon_name, array $setup_args)
363
-    {
364
-        if (empty($setup_args['class_name'])) {
365
-            // generate one by first separating name with spaces
366
-            $class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
367
-            // capitalize, then replace spaces with underscores
368
-            $class_name = str_replace(' ', '_', ucwords($class_name));
369
-        } else {
370
-            $class_name = $setup_args['class_name'];
371
-        }
372
-        // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373
-        return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374
-            ? $class_name
375
-            : 'EE_' . $class_name;
376
-    }
377
-
378
-
379
-    /**
380
-     * @param string $class_name
381
-     * @param array  $setup_args
382
-     * @return array
383
-     */
384
-    private static function _get_addon_settings($class_name, array $setup_args)
385
-    {
386
-        // setup $_settings array from incoming values.
387
-        $addon_settings = array(
388
-            // generated from the addon name, changes something like "calendar" to "EE_Calendar"
389
-            'class_name'            => $class_name,
390
-            // the addon slug for use in URLs, etc
391
-            'plugin_slug'           => isset($setup_args['plugin_slug'])
392
-                ? (string) $setup_args['plugin_slug']
393
-                : '',
394
-            // page slug to be used when generating the "Settings" link on the WP plugin page
395
-            'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
396
-                ? (string) $setup_args['plugin_action_slug']
397
-                : '',
398
-            // the "software" version for the addon
399
-            'version'               => isset($setup_args['version'])
400
-                ? (string) $setup_args['version']
401
-                : '',
402
-            // the minimum version of EE Core that the addon will work with
403
-            'min_core_version'      => isset($setup_args['min_core_version'])
404
-                ? (string) $setup_args['min_core_version']
405
-                : '',
406
-            // the minimum version of WordPress that the addon will work with
407
-            'min_wp_version'        => isset($setup_args['min_wp_version'])
408
-                ? (string) $setup_args['min_wp_version']
409
-                : EE_MIN_WP_VER_REQUIRED,
410
-            // full server path to main file (file loaded directly by WP)
411
-            'main_file_path'        => isset($setup_args['main_file_path'])
412
-                ? (string) $setup_args['main_file_path']
413
-                : '',
414
-            // instance of \EventEspresso\core\domain\DomainInterface
415
-            'domain'                => isset($setup_args['domain']) && $setup_args['domain'] instanceof DomainInterface
416
-                ? $setup_args['domain']
417
-                : null,
418
-            // Fully Qualified Class Name for the addon's Domain class
419
-            'domain_fqcn'           => isset($setup_args['domain_fqcn'])
420
-                ? (string) $setup_args['domain_fqcn']
421
-                : '',
422
-            // path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
423
-            'admin_path'            => isset($setup_args['admin_path'])
424
-                ? (string) $setup_args['admin_path'] : '',
425
-            // a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
426
-            'admin_callback'        => isset($setup_args['admin_callback'])
427
-                ? (string) $setup_args['admin_callback']
428
-                : '',
429
-            // the section name for this addon's configuration settings section (defaults to "addons")
430
-            'config_section'        => isset($setup_args['config_section'])
431
-                ? (string) $setup_args['config_section']
432
-                : 'addons',
433
-            // the class name for this addon's configuration settings object
434
-            'config_class'          => isset($setup_args['config_class'])
435
-                ? (string) $setup_args['config_class'] : '',
436
-            // the name given to the config for this addons' configuration settings object (optional)
437
-            'config_name'           => isset($setup_args['config_name'])
438
-                ? (string) $setup_args['config_name'] : '',
439
-            // an array of "class names" => "full server paths" for any classes that might be invoked by the addon
440
-            'autoloader_paths'      => isset($setup_args['autoloader_paths'])
441
-                ? (array) $setup_args['autoloader_paths']
442
-                : array(),
443
-            // an array of  "full server paths" for any folders containing classes that might be invoked by the addon
444
-            'autoloader_folders'    => isset($setup_args['autoloader_folders'])
445
-                ? (array) $setup_args['autoloader_folders']
446
-                : array(),
447
-            // array of full server paths to any EE_DMS data migration scripts used by the addon.
448
-            // The key should be the EE_Addon class name that this set of data migration scripts belongs to.
449
-            // If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
450
-            'dms_paths'             => isset($setup_args['dms_paths'])
451
-                ? (array) $setup_args['dms_paths']
452
-                : array(),
453
-            // array of full server paths to any EED_Modules used by the addon
454
-            'module_paths'          => isset($setup_args['module_paths'])
455
-                ? (array) $setup_args['module_paths']
456
-                : array(),
457
-            // array of full server paths to any EES_Shortcodes used by the addon
458
-            'shortcode_paths'       => isset($setup_args['shortcode_paths'])
459
-                ? (array) $setup_args['shortcode_paths']
460
-                : array(),
461
-            'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
462
-                ? (array) $setup_args['shortcode_fqcns']
463
-                : array(),
464
-            // array of full server paths to any WP_Widgets used by the addon
465
-            'widget_paths'          => isset($setup_args['widget_paths'])
466
-                ? (array) $setup_args['widget_paths']
467
-                : array(),
468
-            // array of PUE options used by the addon
469
-            'pue_options'           => isset($setup_args['pue_options'])
470
-                ? (array) $setup_args['pue_options']
471
-                : array(),
472
-            'message_types'         => isset($setup_args['message_types'])
473
-                ? (array) $setup_args['message_types']
474
-                : array(),
475
-            'capabilities'          => isset($setup_args['capabilities'])
476
-                ? (array) $setup_args['capabilities']
477
-                : array(),
478
-            'capability_maps'       => isset($setup_args['capability_maps'])
479
-                ? (array) $setup_args['capability_maps']
480
-                : array(),
481
-            'model_paths'           => isset($setup_args['model_paths'])
482
-                ? (array) $setup_args['model_paths']
483
-                : array(),
484
-            'class_paths'           => isset($setup_args['class_paths'])
485
-                ? (array) $setup_args['class_paths']
486
-                : array(),
487
-            'model_extension_paths' => isset($setup_args['model_extension_paths'])
488
-                ? (array) $setup_args['model_extension_paths']
489
-                : array(),
490
-            'class_extension_paths' => isset($setup_args['class_extension_paths'])
491
-                ? (array) $setup_args['class_extension_paths']
492
-                : array(),
493
-            'custom_post_types'     => isset($setup_args['custom_post_types'])
494
-                ? (array) $setup_args['custom_post_types']
495
-                : array(),
496
-            'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
497
-                ? (array) $setup_args['custom_taxonomies']
498
-                : array(),
499
-            'payment_method_paths'  => isset($setup_args['payment_method_paths'])
500
-                ? (array) $setup_args['payment_method_paths']
501
-                : array(),
502
-            'default_terms'         => isset($setup_args['default_terms'])
503
-                ? (array) $setup_args['default_terms']
504
-                : array(),
505
-            // if not empty, inserts a new table row after this plugin's row on the WP Plugins page
506
-            // that can be used for adding upgrading/marketing info
507
-            'plugins_page_row'      => isset($setup_args['plugins_page_row']) ? $setup_args['plugins_page_row'] : '',
508
-            'namespace'             => isset(
509
-                $setup_args['namespace']['FQNS'],
510
-                $setup_args['namespace']['DIR']
511
-            )
512
-                ? (array) $setup_args['namespace']
513
-                : array(),
514
-            'privacy_policies'      => isset($setup_args['privacy_policies'])
515
-                ? (array) $setup_args['privacy_policies']
516
-                : '',
517
-        );
518
-        // if plugin_action_slug is NOT set, but an admin page path IS set,
519
-        // then let's just use the plugin_slug since that will be used for linking to the admin page
520
-        $addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
521
-                                                && ! empty($addon_settings['admin_path'])
522
-            ? $addon_settings['plugin_slug']
523
-            : $addon_settings['plugin_action_slug'];
524
-        // full server path to main file (file loaded directly by WP)
525
-        $addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
526
-        return $addon_settings;
527
-    }
528
-
529
-
530
-    /**
531
-     * @param string $addon_name
532
-     * @param array  $addon_settings
533
-     * @return boolean
534
-     */
535
-    private static function _addon_is_compatible($addon_name, array $addon_settings)
536
-    {
537
-        global $wp_version;
538
-        $incompatibility_message = '';
539
-        // check whether this addon version is compatible with EE core
540
-        if (
541
-            isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
542
-            && ! self::_meets_min_core_version_requirement(
543
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
544
-                $addon_settings['version']
545
-            )
546
-        ) {
547
-            $incompatibility_message = sprintf(
548
-                esc_html__(
549
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.',
550
-                    'event_espresso'
551
-                ),
552
-                $addon_name,
553
-                '<br />',
554
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
555
-                '<span style="font-weight: bold; color: #D54E21;">',
556
-                '</span><br />'
557
-            );
558
-        } elseif (
559
-            ! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
560
-        ) {
561
-            $incompatibility_message = sprintf(
562
-                esc_html__(
563
-                    '%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
564
-                    'event_espresso'
565
-                ),
566
-                $addon_name,
567
-                self::_effective_version($addon_settings['min_core_version']),
568
-                self::_effective_version(espresso_version()),
569
-                '<br />',
570
-                '<span style="font-weight: bold; color: #D54E21;">',
571
-                '</span><br />'
572
-            );
573
-        } elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
574
-            $incompatibility_message = sprintf(
575
-                esc_html__(
576
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
577
-                    'event_espresso'
578
-                ),
579
-                $addon_name,
580
-                $addon_settings['min_wp_version'],
581
-                '<br />',
582
-                '<span style="font-weight: bold; color: #D54E21;">',
583
-                '</span><br />'
584
-            );
585
-        }
586
-        if (! empty($incompatibility_message)) {
587
-            // remove 'activate' from the REQUEST
588
-            // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589
-            /** @var RequestInterface $request */
590
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
591
-            $request->unSetRequestParam('activate', true);
592
-            if (current_user_can('activate_plugins')) {
593
-                // show an error message indicating the plugin didn't activate properly
594
-                EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
595
-            }
596
-            unset($_GET['activate'], $_REQUEST['activate']);
597
-            if (! function_exists('deactivate_plugins')) {
598
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
599
-            }
600
-            deactivate_plugins(plugin_basename($addon_settings['main_file_path']));
601
-            // BAIL FROM THE ADDON REGISTRATION PROCESS
602
-            return false;
603
-        }
604
-        // addon IS compatible
605
-        return true;
606
-    }
607
-
608
-
609
-    /**
610
-     * if plugin update engine is being used for auto-updates,
611
-     * then let's set that up now before going any further so that ALL addons can be updated
612
-     * (not needed if PUE is not being used)
613
-     *
614
-     * @param string $addon_name
615
-     * @param string $class_name
616
-     * @param array  $setup_args
617
-     * @return void
618
-     */
619
-    private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
620
-    {
621
-        if (! empty($setup_args['pue_options'])) {
622
-            self::$_settings[ $addon_name ]['pue_options'] = array(
623
-                'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
624
-                    ? (string) $setup_args['pue_options']['pue_plugin_slug']
625
-                    : 'espresso_' . strtolower($class_name),
626
-                'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
627
-                    ? (string) $setup_args['pue_options']['plugin_basename']
628
-                    : plugin_basename($setup_args['main_file_path']),
629
-                'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
630
-                    ? (string) $setup_args['pue_options']['checkPeriod']
631
-                    : '24',
632
-                'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
633
-                    ? (string) $setup_args['pue_options']['use_wp_update']
634
-                    : false,
635
-            );
636
-            add_action(
637
-                'AHEE__EE_System__brew_espresso__after_pue_init',
638
-                array('EE_Register_Addon', 'load_pue_update')
639
-            );
640
-        }
641
-    }
642
-
643
-
644
-    /**
645
-     * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
646
-     *
647
-     * @param array $addon_settings
648
-     * @return void
649
-     */
650
-    private static function _setup_namespaces(array $addon_settings)
651
-    {
652
-        //
653
-        if (
654
-            isset(
655
-                $addon_settings['namespace']['FQNS'],
656
-                $addon_settings['namespace']['DIR']
657
-            )
658
-        ) {
659
-            EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
660
-                $addon_settings['namespace']['FQNS'],
661
-                $addon_settings['namespace']['DIR']
662
-            );
663
-        }
664
-    }
665
-
666
-
667
-    /**
668
-     * @param string $addon_name
669
-     * @param array  $addon_settings
670
-     * @return bool
671
-     * @throws InvalidArgumentException
672
-     * @throws InvalidDataTypeException
673
-     * @throws InvalidInterfaceException
674
-     */
675
-    private static function _addon_activation($addon_name, array $addon_settings)
676
-    {
677
-        // this is an activation request
678
-        if (did_action('activate_plugin')) {
679
-            // to find if THIS is the addon that was activated, just check if we have already registered it or not
680
-            // (as the newly-activated addon wasn't around the first time addons were registered).
681
-            // Note: the presence of pue_options in the addon registration options will initialize the $_settings
682
-            // property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
683
-            if (
684
-                ! isset(self::$_settings[ $addon_name ])
685
-                || (isset(self::$_settings[ $addon_name ])
686
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
687
-                )
688
-            ) {
689
-                self::$_settings[ $addon_name ] = $addon_settings;
690
-                $addon = self::_load_and_init_addon_class($addon_name);
691
-                $addon->set_activation_indicator_option();
692
-                // dont bother setting up the rest of the addon.
693
-                // we know it was just activated and the request will end soon
694
-            }
695
-            return true;
696
-        }
697
-        // make sure this was called in the right place!
698
-        if (
699
-            ! did_action('AHEE__EE_System__load_espresso_addons')
700
-            || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
701
-        ) {
702
-            EE_Error::doing_it_wrong(
703
-                __METHOD__,
704
-                sprintf(
705
-                    esc_html__(
706
-                        'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
707
-                        'event_espresso'
708
-                    ),
709
-                    $addon_name
710
-                ),
711
-                '4.3.0'
712
-            );
713
-        }
714
-        // make sure addon settings are set correctly without overwriting anything existing
715
-        if (isset(self::$_settings[ $addon_name ])) {
716
-            self::$_settings[ $addon_name ] += $addon_settings;
717
-        } else {
718
-            self::$_settings[ $addon_name ] = $addon_settings;
719
-        }
720
-        return false;
721
-    }
722
-
723
-
724
-    /**
725
-     * @param string $addon_name
726
-     * @return void
727
-     * @throws EE_Error
728
-     */
729
-    private static function _setup_autoloaders($addon_name)
730
-    {
731
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
732
-            // setup autoloader for single file
733
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
734
-        }
735
-        // setup autoloaders for folders
736
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
737
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
738
-                EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
739
-            }
740
-        }
741
-    }
742
-
743
-
744
-    /**
745
-     * register new models and extensions
746
-     *
747
-     * @param string $addon_name
748
-     * @return void
749
-     * @throws EE_Error
750
-     */
751
-    private static function _register_models_and_extensions($addon_name)
752
-    {
753
-        // register new models
754
-        if (
755
-            ! empty(self::$_settings[ $addon_name ]['model_paths'])
756
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
757
-        ) {
758
-            EE_Register_Model::register(
759
-                $addon_name,
760
-                array(
761
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
762
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
763
-                )
764
-            );
765
-        }
766
-        // register model extensions
767
-        if (
768
-            ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
769
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
770
-        ) {
771
-            EE_Register_Model_Extensions::register(
772
-                $addon_name,
773
-                array(
774
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
775
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
776
-                )
777
-            );
778
-        }
779
-    }
780
-
781
-
782
-    /**
783
-     * @param string $addon_name
784
-     * @return void
785
-     * @throws EE_Error
786
-     */
787
-    private static function _register_data_migration_scripts($addon_name)
788
-    {
789
-        // setup DMS
790
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
791
-            EE_Register_Data_Migration_Scripts::register(
792
-                $addon_name,
793
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
794
-            );
795
-        }
796
-    }
797
-
798
-
799
-    /**
800
-     * @param string $addon_name
801
-     * @return void
802
-     * @throws EE_Error
803
-     */
804
-    private static function _register_config($addon_name)
805
-    {
806
-        // if config_class is present let's register config.
807
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
808
-            EE_Register_Config::register(
809
-                self::$_settings[ $addon_name ]['config_class'],
810
-                array(
811
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
812
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
813
-                )
814
-            );
815
-        }
816
-    }
817
-
818
-
819
-    /**
820
-     * @param string $addon_name
821
-     * @return void
822
-     * @throws EE_Error
823
-     */
824
-    private static function _register_admin_pages($addon_name)
825
-    {
826
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
827
-            EE_Register_Admin_Page::register(
828
-                $addon_name,
829
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
830
-            );
831
-        }
832
-    }
833
-
834
-
835
-    /**
836
-     * @param string $addon_name
837
-     * @return void
838
-     * @throws EE_Error
839
-     */
840
-    private static function _register_modules($addon_name)
841
-    {
842
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
843
-            EE_Register_Module::register(
844
-                $addon_name,
845
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
846
-            );
847
-        }
848
-    }
849
-
850
-
851
-    /**
852
-     * @param string $addon_name
853
-     * @return void
854
-     * @throws EE_Error
855
-     */
856
-    private static function _register_shortcodes($addon_name)
857
-    {
858
-        if (
859
-            ! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
860
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
861
-        ) {
862
-            EE_Register_Shortcode::register(
863
-                $addon_name,
864
-                array(
865
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
866
-                        ? self::$_settings[ $addon_name ]['shortcode_paths'] : array(),
867
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
868
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns'] : array(),
869
-                )
870
-            );
871
-        }
872
-    }
873
-
874
-
875
-    /**
876
-     * @param string $addon_name
877
-     * @return void
878
-     * @throws EE_Error
879
-     */
880
-    private static function _register_widgets($addon_name)
881
-    {
882
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
883
-            EE_Register_Widget::register(
884
-                $addon_name,
885
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
886
-            );
887
-        }
888
-    }
889
-
890
-
891
-    /**
892
-     * @param string $addon_name
893
-     * @return void
894
-     * @throws EE_Error
895
-     */
896
-    private static function _register_capabilities($addon_name)
897
-    {
898
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
899
-            EE_Register_Capabilities::register(
900
-                $addon_name,
901
-                array(
902
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
903
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
904
-                )
905
-            );
906
-        }
907
-    }
908
-
909
-
910
-    /**
911
-     * @param string $addon_name
912
-     * @return void
913
-     */
914
-    private static function _register_message_types($addon_name)
915
-    {
916
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
917
-            add_action(
918
-                'EE_Brewing_Regular___messages_caf',
919
-                array('EE_Register_Addon', 'register_message_types')
920
-            );
921
-        }
922
-    }
923
-
924
-
925
-    /**
926
-     * @param string $addon_name
927
-     * @return void
928
-     * @throws EE_Error
929
-     */
930
-    private static function _register_custom_post_types($addon_name)
931
-    {
932
-        if (
933
-            ! empty(self::$_settings[ $addon_name ]['custom_post_types'])
934
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
935
-        ) {
936
-            EE_Register_CPT::register(
937
-                $addon_name,
938
-                array(
939
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
940
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
941
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
942
-                )
943
-            );
944
-        }
945
-    }
946
-
947
-
948
-    /**
949
-     * @param string $addon_name
950
-     * @return void
951
-     * @throws InvalidArgumentException
952
-     * @throws InvalidInterfaceException
953
-     * @throws InvalidDataTypeException
954
-     * @throws DomainException
955
-     * @throws EE_Error
956
-     */
957
-    private static function _register_payment_methods($addon_name)
958
-    {
959
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
960
-            EE_Register_Payment_Method::register(
961
-                $addon_name,
962
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
963
-            );
964
-        }
965
-    }
966
-
967
-
968
-    /**
969
-     * @param string $addon_name
970
-     * @return void
971
-     * @throws InvalidArgumentException
972
-     * @throws InvalidInterfaceException
973
-     * @throws InvalidDataTypeException
974
-     * @throws DomainException
975
-     */
976
-    private static function registerPrivacyPolicies($addon_name)
977
-    {
978
-        if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
979
-            EE_Register_Privacy_Policy::register(
980
-                $addon_name,
981
-                self::$_settings[ $addon_name ]['privacy_policies']
982
-            );
983
-        }
984
-    }
985
-
986
-
987
-    /**
988
-     * @param string $addon_name
989
-     * @return void
990
-     */
991
-    private static function registerPersonalDataExporters($addon_name)
992
-    {
993
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
994
-            EE_Register_Personal_Data_Eraser::register(
995
-                $addon_name,
996
-                self::$_settings[ $addon_name ]['personal_data_exporters']
997
-            );
998
-        }
999
-    }
1000
-
1001
-
1002
-    /**
1003
-     * @param string $addon_name
1004
-     * @return void
1005
-     */
1006
-    private static function registerPersonalDataErasers($addon_name)
1007
-    {
1008
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1009
-            EE_Register_Personal_Data_Eraser::register(
1010
-                $addon_name,
1011
-                self::$_settings[ $addon_name ]['personal_data_erasers']
1012
-            );
1013
-        }
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * Loads and instantiates the EE_Addon class and adds it onto the registry
1019
-     *
1020
-     * @param string $addon_name
1021
-     * @return EE_Addon
1022
-     * @throws InvalidArgumentException
1023
-     * @throws InvalidInterfaceException
1024
-     * @throws InvalidDataTypeException
1025
-     */
1026
-    private static function _load_and_init_addon_class($addon_name)
1027
-    {
1028
-        $addon = LoaderFactory::getLoader()->getShared(
1029
-            self::$_settings[ $addon_name ]['class_name'],
1030
-            array('EE_Registry::create(addon)' => true)
1031
-        );
1032
-        if (! $addon instanceof EE_Addon) {
1033
-            throw new DomainException(
1034
-                sprintf(
1035
-                    esc_html__(
1036
-                        'Failed to instantiate the %1$s class. PLease check that the class exists.',
1037
-                        'event_espresso'
1038
-                    ),
1039
-                    $addon_name
1040
-                )
1041
-            );
1042
-        }
1043
-        // setter inject dep map if required
1044
-        if ($addon->dependencyMap() === null) {
1045
-            $addon->setDependencyMap(LoaderFactory::getLoader()->getShared('EE_Dependency_Map'));
1046
-        }
1047
-        // setter inject domain if required
1048
-        EE_Register_Addon::injectAddonDomain($addon_name, $addon);
1049
-
1050
-        $addon->set_name($addon_name);
1051
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1052
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1053
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1054
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1055
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1056
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
1057
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1058
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1059
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1060
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1061
-        // setup the add-on's pue_slug if we have one.
1062
-        if (! empty(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug'])) {
1063
-            $addon->setPueSlug(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug']);
1064
-        }
1065
-        // unfortunately this can't be hooked in upon construction,
1066
-        // because we don't have the plugin's mainfile path upon construction.
1067
-        register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1068
-        // call any additional admin_callback functions during load_admin_controller hook
1069
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1070
-            add_action(
1071
-                'AHEE__EE_System__load_controllers__load_admin_controllers',
1072
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1073
-            );
1074
-        }
1075
-        return $addon;
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * @param string   $addon_name
1081
-     * @param EE_Addon $addon
1082
-     * @since   4.10.13.p
1083
-     */
1084
-    private static function injectAddonDomain($addon_name, EE_Addon $addon)
1085
-    {
1086
-        if ($addon instanceof RequiresDomainInterface && $addon->domain() === null) {
1087
-            // using supplied Domain object
1088
-            $domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1089
-                ? self::$_settings[ $addon_name ]['domain']
1090
-                : null;
1091
-            // or construct one using Domain FQCN
1092
-            if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1093
-                $domain = LoaderFactory::getLoader()->getShared(
1094
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
1095
-                    [
1096
-                        new EventEspresso\core\domain\values\FilePath(
1097
-                            self::$_settings[ $addon_name ]['main_file_path']
1098
-                        ),
1099
-                        EventEspresso\core\domain\values\Version::fromString(
1100
-                            self::$_settings[ $addon_name ]['version']
1101
-                        ),
1102
-                    ]
1103
-                );
1104
-            }
1105
-            if ($domain instanceof DomainInterface) {
1106
-                $addon->setDomain($domain);
1107
-            }
1108
-        }
1109
-    }
1110
-
1111
-
1112
-    /**
1113
-     *    load_pue_update - Update notifications
1114
-     *
1115
-     * @return void
1116
-     * @throws InvalidArgumentException
1117
-     * @throws InvalidDataTypeException
1118
-     * @throws InvalidInterfaceException
1119
-     */
1120
-    public static function load_pue_update()
1121
-    {
1122
-        // PUE client existence
1123
-        if (! is_readable(EE_THIRD_PARTY . 'pue/pue-client.php')) {
1124
-            return;
1125
-        }
1126
-        // load PUE client
1127
-        require_once EE_THIRD_PARTY . 'pue/pue-client.php';
1128
-        $license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1129
-        // cycle thru settings
1130
-        foreach (self::$_settings as $settings) {
1131
-            if (empty($settings['pue_options'])) {
1132
-                continue;
1133
-            }
1134
-            // initiate the class and start the plugin update engine!
1135
-            new PluginUpdateEngineChecker(
1136
-                // host file URL
1137
-                $license_server,
1138
-                // plugin slug(s)
1139
-                array(
1140
-                    'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1141
-                    'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1142
-                ),
1143
-                // options
1144
-                array(
1145
-                    'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1146
-                    'lang_domain'       => 'event_espresso',
1147
-                    'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1148
-                    'option_key'        => 'ee_site_license_key',
1149
-                    'options_page_slug' => 'event_espresso',
1150
-                    'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1151
-                    // if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1152
-                    'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1153
-                )
1154
-            );
1155
-        }
1156
-    }
1157
-
1158
-
1159
-    /**
1160
-     * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1161
-     *
1162
-     * @since 4.4.0
1163
-     * @return void
1164
-     * @throws EE_Error
1165
-     */
1166
-    public static function register_message_types()
1167
-    {
1168
-        foreach (self::$_settings as $settings) {
1169
-            if (! empty($settings['message_types'])) {
1170
-                foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1171
-                    EE_Register_Message_Type::register($message_type, $message_type_settings);
1172
-                }
1173
-            }
1174
-        }
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * This deregisters an addon that was previously registered with a specific addon_name.
1180
-     *
1181
-     * @param string $addon_name the name for the addon that was previously registered
1182
-     * @throws DomainException
1183
-     * @throws InvalidArgumentException
1184
-     * @throws InvalidDataTypeException
1185
-     * @throws InvalidInterfaceException
1186
-     *@since    4.3.0
1187
-     */
1188
-    public static function deregister($addon_name = '')
1189
-    {
1190
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1191
-            try {
1192
-                do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1193
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1194
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1195
-                    // setup DMS
1196
-                    EE_Register_Data_Migration_Scripts::deregister($addon_name);
1197
-                }
1198
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1199
-                    // register admin page
1200
-                    EE_Register_Admin_Page::deregister($addon_name);
1201
-                }
1202
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1203
-                    // add to list of modules to be registered
1204
-                    EE_Register_Module::deregister($addon_name);
1205
-                }
1206
-                if (
1207
-                    ! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1208
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1209
-                ) {
1210
-                    // add to list of shortcodes to be registered
1211
-                    EE_Register_Shortcode::deregister($addon_name);
1212
-                }
1213
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1214
-                    // if config_class present let's register config.
1215
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1216
-                }
1217
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1218
-                    // add to list of widgets to be registered
1219
-                    EE_Register_Widget::deregister($addon_name);
1220
-                }
1221
-                if (
1222
-                    ! empty(self::$_settings[ $addon_name ]['model_paths'])
1223
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1224
-                ) {
1225
-                    // add to list of shortcodes to be registered
1226
-                    EE_Register_Model::deregister($addon_name);
1227
-                }
1228
-                if (
1229
-                    ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1230
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1231
-                ) {
1232
-                    // add to list of shortcodes to be registered
1233
-                    EE_Register_Model_Extensions::deregister($addon_name);
1234
-                }
1235
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1236
-                    foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1237
-                        EE_Register_Message_Type::deregister($message_type);
1238
-                    }
1239
-                }
1240
-                // deregister capabilities for addon
1241
-                if (
1242
-                    ! empty(self::$_settings[ $addon_name ]['capabilities'])
1243
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1244
-                ) {
1245
-                    EE_Register_Capabilities::deregister($addon_name);
1246
-                }
1247
-                // deregister custom_post_types for addon
1248
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1249
-                    EE_Register_CPT::deregister($addon_name);
1250
-                }
1251
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1252
-                    EE_Register_Payment_Method::deregister($addon_name);
1253
-                }
1254
-                $addon = EE_Registry::instance()->getAddon($class_name);
1255
-                if ($addon instanceof EE_Addon) {
1256
-                    remove_action(
1257
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1258
-                        array($addon, 'deactivation')
1259
-                    );
1260
-                    remove_action(
1261
-                        'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1262
-                        array($addon, 'initialize_db_if_no_migrations_required')
1263
-                    );
1264
-                    // remove `after_registration` call
1265
-                    remove_action(
1266
-                        'AHEE__EE_System__load_espresso_addons__complete',
1267
-                        array($addon, 'after_registration'),
1268
-                        999
1269
-                    );
1270
-                }
1271
-                EE_Registry::instance()->removeAddon($class_name);
1272
-                LoaderFactory::getLoader()->remove($class_name);
1273
-            } catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1274
-                // the add-on was not yet registered in the registry,
1275
-                // so RegistryContainer::__get() throws this exception.
1276
-                // also no need to worry about this or log it,
1277
-                // it's ok to deregister an add-on before its registered in the registry
1278
-            } catch (Exception $e) {
1279
-                new ExceptionLogger($e);
1280
-            }
1281
-            unset(self::$_settings[ $addon_name ]);
1282
-            do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1283
-        }
1284
-    }
25
+	/**
26
+	 * possibly truncated version of the EE core version string
27
+	 *
28
+	 * @var string
29
+	 */
30
+	protected static $_core_version = '';
31
+
32
+	/**
33
+	 * Holds values for registered addons
34
+	 *
35
+	 * @var array
36
+	 */
37
+	protected static $_settings = array();
38
+
39
+	/**
40
+	 * @var  array $_incompatible_addons keys are addon SLUGS
41
+	 * (first argument passed to EE_Register_Addon::register()), keys are
42
+	 * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
43
+	 * Generally this should be used sparingly, as we don't want to muddle up
44
+	 * EE core with knowledge of ALL the addons out there.
45
+	 * If you want NO versions of an addon to run with a certain version of core,
46
+	 * it's usually best to define the addon's "min_core_version" as part of its call
47
+	 * to EE_Register_Addon::register(), rather than using this array with a super high value for its
48
+	 * minimum plugin version.
49
+	 * @access    protected
50
+	 */
51
+	protected static $_incompatible_addons = array(
52
+		'Multi_Event_Registration' => '2.0.11.rc.002',
53
+		'Promotions'               => '1.0.0.rc.084',
54
+	);
55
+
56
+
57
+	/**
58
+	 * We should always be comparing core to a version like '4.3.0.rc.000',
59
+	 * not just '4.3.0'.
60
+	 * So if the addon developer doesn't provide that full version string,
61
+	 * fill in the blanks for them
62
+	 *
63
+	 * @param string $min_core_version
64
+	 * @return string always like '4.3.0.rc.000'
65
+	 */
66
+	protected static function _effective_version($min_core_version)
67
+	{
68
+		// versions: 4 . 3 . 1 . p . 123
69
+		// offsets:    0 . 1 . 2 . 3 . 4
70
+		$version_parts = explode('.', $min_core_version);
71
+		// check they specified the micro version (after 2nd period)
72
+		if (! isset($version_parts[2])) {
73
+			$version_parts[2] = '0';
74
+		}
75
+		// if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76
+		// soon we can assume that's 'rc', but this current version is 'alpha'
77
+		if (! isset($version_parts[3])) {
78
+			$version_parts[3] = 'dev';
79
+		}
80
+		if (! isset($version_parts[4])) {
81
+			$version_parts[4] = '000';
82
+		}
83
+		return implode('.', $version_parts);
84
+	}
85
+
86
+
87
+	/**
88
+	 * Returns whether or not the min core version requirement of the addon is met
89
+	 *
90
+	 * @param string $min_core_version    the minimum core version required by the addon
91
+	 * @param string $actual_core_version the actual core version, optional
92
+	 * @return boolean
93
+	 */
94
+	public static function _meets_min_core_version_requirement(
95
+		$min_core_version,
96
+		$actual_core_version = EVENT_ESPRESSO_VERSION
97
+	) {
98
+		return version_compare(
99
+			self::_effective_version($actual_core_version),
100
+			self::_effective_version($min_core_version),
101
+			'>='
102
+		);
103
+	}
104
+
105
+
106
+	/**
107
+	 * Method for registering new EE_Addons.
108
+	 * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
109
+	 * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
110
+	 * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
111
+	 * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
112
+	 * 'activate_plugin', it registers the addon still, but its components are not registered
113
+	 * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
114
+	 * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
115
+	 * (so that we can detect that the addon has activated on the subsequent request)
116
+	 *
117
+	 * @since    4.3.0
118
+	 * @param string                  $addon_name                       [Required] the EE_Addon's name.
119
+	 * @param  array                  $setup_args                       {
120
+	 *                                                                  An array of arguments provided for registering
121
+	 *                                                                  the message type.
122
+	 * @type  string                  $class_name                       the addon's main file name.
123
+	 *                                                                  If left blank, generated from the addon name,
124
+	 *                                                                  changes something like "calendar" to
125
+	 *                                                                  "EE_Calendar"
126
+	 * @type string                   $min_core_version                 the minimum version of EE Core that the
127
+	 *                                                                  addon will work with. eg "4.8.1.rc.084"
128
+	 * @type string                   $version                          the "software" version for the addon. eg
129
+	 *                                                                  "1.0.0.p" for a first stable release, or
130
+	 *                                                                  "1.0.0.rc.043" for a version in progress
131
+	 * @type string                   $main_file_path                   the full server path to the main file
132
+	 *                                                                  loaded directly by WP
133
+	 * @type DomainInterface $domain                                    child class of
134
+	 *                                                                  EventEspresso\core\domain\DomainBase
135
+	 * @type string                   $domain_fqcn                      Fully Qualified Class Name
136
+	 *                                                                  for the addon's Domain class
137
+	 *                                                                  (see EventEspresso\core\domain\Domain)
138
+	 * @type string                   $admin_path                       full server path to the folder where the
139
+	 *                                                                  addon\'s admin files reside
140
+	 * @type string                   $admin_callback                   a method to be called when the EE Admin is
141
+	 *                                                                  first invoked, can be used for hooking into
142
+	 *                                                                  any admin page
143
+	 * @type string                   $config_section                   the section name for this addon's
144
+	 *                                                                  configuration settings section
145
+	 *                                                                  (defaults to "addons")
146
+	 * @type string                   $config_class                     the class name for this addon's
147
+	 *                                                                  configuration settings object
148
+	 * @type string                   $config_name                      the class name for this addon's
149
+	 *                                                                  configuration settings object
150
+	 * @type string                   $autoloader_paths                 [Required] an array of class names and the full
151
+	 *                                                                  server paths to those files.
152
+	 * @type string                   $autoloader_folders               an array of  "full server paths" for any
153
+	 *                                                                  folders containing classes that might be
154
+	 *                                                                  invoked by the addon
155
+	 * @type string                   $dms_paths                        [Required] an array of full server paths to
156
+	 *                                                                  folders that contain data migration scripts.
157
+	 *                                                                  The key should be the EE_Addon class name that
158
+	 *                                                                  this set of data migration scripts belongs to.
159
+	 *                                                                  If the EE_Addon class is namespaced, then this
160
+	 *                                                                  needs to be the Fully Qualified Class Name
161
+	 * @type string                   $module_paths                     an array of full server paths to any
162
+	 *                                                                  EED_Modules used by the addon
163
+	 * @type string                   $shortcode_paths                  an array of full server paths to folders
164
+	 *                                                                  that contain EES_Shortcodes
165
+	 * @type string                   $widget_paths                     an array of full server paths to folders
166
+	 *                                                                  that contain WP_Widgets
167
+	 * @type string                   $pue_options
168
+	 * @type array                    $capabilities                     an array indexed by role name
169
+	 *                                                                  (i.e administrator,author ) and the values
170
+	 *                                                                  are an array of caps to add to the role.
171
+	 *                                                                  'administrator' => array(
172
+	 *                                                                  'read_addon',
173
+	 *                                                                  'edit_addon',
174
+	 *                                                                  etc.
175
+	 *                                                                  ).
176
+	 * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
177
+	 *                                                                  for any addons that need to register any
178
+	 *                                                                  special meta mapped capabilities.  Should
179
+	 *                                                                  be indexed where the key is the
180
+	 *                                                                  EE_Meta_Capability_Map class name and the
181
+	 *                                                                  values are the arguments sent to the class.
182
+	 * @type array                    $model_paths                      array of folders containing DB models
183
+	 * @see      EE_Register_Model
184
+	 * @type array                    $class_paths                      array of folders containing DB classes
185
+	 * @see      EE_Register_Model
186
+	 * @type array                    $model_extension_paths            array of folders containing DB model
187
+	 *                                                                  extensions
188
+	 * @see      EE_Register_Model_Extension
189
+	 * @type array                    $class_extension_paths            array of folders containing DB class
190
+	 *                                                                  extensions
191
+	 * @see      EE_Register_Model_Extension
192
+	 * @type array message_types {
193
+	 *                                                                  An array of message types with the key as
194
+	 *                                                                  the message type name and the values as
195
+	 *                                                                  below:
196
+	 * @type string                   $mtfilename                       [Required] The filename of the message type
197
+	 *                                                                  being registered. This will be the main
198
+	 *                                                                  EE_{Message Type Name}_message_type class.
199
+	 *                                                                  for example:
200
+	 *                                                                  EE_Declined_Registration_message_type.class.php
201
+	 * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
202
+	 *                                                                  messages autoloader for the new message type.
203
+	 * @type array                    $messengers_to_activate_with      An array of messengers that this message
204
+	 *                                                                  type should activate with. Each value in
205
+	 *                                                                  the
206
+	 *                                                                  array
207
+	 *                                                                  should match the name property of a
208
+	 *                                                                  EE_messenger. Optional.
209
+	 * @type array                    $messengers_to_validate_with      An array of messengers that this message
210
+	 *                                                                  type should validate with. Each value in
211
+	 *                                                                  the
212
+	 *                                                                  array
213
+	 *                                                                  should match the name property of an
214
+	 *                                                                  EE_messenger.
215
+	 *                                                                  Optional.
216
+	 *                                                                  }
217
+	 * @type array                    $custom_post_types
218
+	 * @type array                    $custom_taxonomies
219
+	 * @type array                    $payment_method_paths             each element is the folder containing the
220
+	 *                                                                  EE_PMT_Base child class
221
+	 *                                                                  (eg,
222
+	 *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
223
+	 *                                                                  which contains the files
224
+	 *                                                                  EE_PMT_Payomatic.pm.php)
225
+	 * @type array                    $default_terms
226
+	 * @type array                    $namespace                        {
227
+	 *                                                                  An array with two items for registering the
228
+	 *                                                                  addon's namespace. (If, for some reason, you
229
+	 *                                                                  require additional namespaces,
230
+	 *                                                                  use
231
+	 *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
232
+	 *                                                                  directly)
233
+	 * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
234
+	 * @type string                   $FQNS                             the namespace prefix
235
+	 * @type string                   $DIR                              a base directory for class files in the
236
+	 *                                                                  namespace.
237
+	 *                                                                  }
238
+	 *                                                                  }
239
+	 * @type string                   $privacy_policies                 FQNSs (namespaces, each of which contains only
240
+	 *                                                                  privacy policy classes) or FQCNs (specific
241
+	 *                                                                  classnames of privacy policy classes)
242
+	 * @type string                   $personal_data_exporters          FQNSs (namespaces, each of which contains only
243
+	 *                                                                  privacy policy classes) or FQCNs (specific
244
+	 *                                                                  classnames of privacy policy classes)
245
+	 * @type string                   $personal_data_erasers            FQNSs (namespaces, each of which contains only
246
+	 *                                                                  privacy policy classes) or FQCNs (specific
247
+	 *                                                                  classnames of privacy policy classes)
248
+	 * @return void
249
+	 * @throws DomainException
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws InvalidDataTypeException
253
+	 * @throws InvalidInterfaceException
254
+	 */
255
+	public static function register($addon_name = '', array $setup_args = array())
256
+	{
257
+		// required fields MUST be present, so let's make sure they are.
258
+		EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
259
+		// get class name for addon
260
+		$class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
261
+		// setup $_settings array from incoming values.
262
+		$addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
263
+		// setup PUE
264
+		EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
265
+		// does this addon work with this version of core or WordPress ?
266
+		// does this addon work with this version of core or WordPress ?
267
+		if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268
+			return;
269
+		}
270
+		// register namespaces
271
+		EE_Register_Addon::_setup_namespaces($addon_settings);
272
+		// check if this is an activation request
273
+		if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
274
+			// dont bother setting up the rest of the addon atm
275
+			return;
276
+		}
277
+		// we need cars
278
+		EE_Register_Addon::_setup_autoloaders($addon_name);
279
+		// register new models and extensions
280
+		EE_Register_Addon::_register_models_and_extensions($addon_name);
281
+		// setup DMS
282
+		EE_Register_Addon::_register_data_migration_scripts($addon_name);
283
+		// if config_class is present let's register config.
284
+		EE_Register_Addon::_register_config($addon_name);
285
+		// register admin pages
286
+		EE_Register_Addon::_register_admin_pages($addon_name);
287
+		// add to list of modules to be registered
288
+		EE_Register_Addon::_register_modules($addon_name);
289
+		// add to list of shortcodes to be registered
290
+		EE_Register_Addon::_register_shortcodes($addon_name);
291
+		// add to list of widgets to be registered
292
+		EE_Register_Addon::_register_widgets($addon_name);
293
+		// register capability related stuff.
294
+		EE_Register_Addon::_register_capabilities($addon_name);
295
+		// any message type to register?
296
+		EE_Register_Addon::_register_message_types($addon_name);
297
+		// any custom post type/ custom capabilities or default terms to register
298
+		EE_Register_Addon::_register_custom_post_types($addon_name);
299
+		// and any payment methods
300
+		EE_Register_Addon::_register_payment_methods($addon_name);
301
+		// and privacy policy generators
302
+		EE_Register_Addon::registerPrivacyPolicies($addon_name);
303
+		// and privacy policy generators
304
+		EE_Register_Addon::registerPersonalDataExporters($addon_name);
305
+		// and privacy policy generators
306
+		EE_Register_Addon::registerPersonalDataErasers($addon_name);
307
+		// load and instantiate main addon class
308
+		$addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
309
+		// delay calling after_registration hook on each addon until after all add-ons have been registered.
310
+		add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
311
+	}
312
+
313
+
314
+	/**
315
+	 * @param string $addon_name
316
+	 * @param array  $setup_args
317
+	 * @return void
318
+	 * @throws EE_Error
319
+	 */
320
+	private static function _verify_parameters($addon_name, array $setup_args)
321
+	{
322
+		// required fields MUST be present, so let's make sure they are.
323
+		if (empty($addon_name) || ! is_array($setup_args)) {
324
+			throw new EE_Error(
325
+				esc_html__(
326
+					'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
327
+					'event_espresso'
328
+				)
329
+			);
330
+		}
331
+		if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332
+			throw new EE_Error(
333
+				sprintf(
334
+					esc_html__(
335
+						'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
336
+						'event_espresso'
337
+					),
338
+					implode(',', array_keys($setup_args))
339
+				)
340
+			);
341
+		}
342
+		// check that addon has not already been registered with that name
343
+		if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
344
+			throw new EE_Error(
345
+				sprintf(
346
+					esc_html__(
347
+						'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
348
+						'event_espresso'
349
+					),
350
+					$addon_name
351
+				)
352
+			);
353
+		}
354
+	}
355
+
356
+
357
+	/**
358
+	 * @param string $addon_name
359
+	 * @param array  $setup_args
360
+	 * @return string
361
+	 */
362
+	private static function _parse_class_name($addon_name, array $setup_args)
363
+	{
364
+		if (empty($setup_args['class_name'])) {
365
+			// generate one by first separating name with spaces
366
+			$class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
367
+			// capitalize, then replace spaces with underscores
368
+			$class_name = str_replace(' ', '_', ucwords($class_name));
369
+		} else {
370
+			$class_name = $setup_args['class_name'];
371
+		}
372
+		// check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373
+		return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374
+			? $class_name
375
+			: 'EE_' . $class_name;
376
+	}
377
+
378
+
379
+	/**
380
+	 * @param string $class_name
381
+	 * @param array  $setup_args
382
+	 * @return array
383
+	 */
384
+	private static function _get_addon_settings($class_name, array $setup_args)
385
+	{
386
+		// setup $_settings array from incoming values.
387
+		$addon_settings = array(
388
+			// generated from the addon name, changes something like "calendar" to "EE_Calendar"
389
+			'class_name'            => $class_name,
390
+			// the addon slug for use in URLs, etc
391
+			'plugin_slug'           => isset($setup_args['plugin_slug'])
392
+				? (string) $setup_args['plugin_slug']
393
+				: '',
394
+			// page slug to be used when generating the "Settings" link on the WP plugin page
395
+			'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
396
+				? (string) $setup_args['plugin_action_slug']
397
+				: '',
398
+			// the "software" version for the addon
399
+			'version'               => isset($setup_args['version'])
400
+				? (string) $setup_args['version']
401
+				: '',
402
+			// the minimum version of EE Core that the addon will work with
403
+			'min_core_version'      => isset($setup_args['min_core_version'])
404
+				? (string) $setup_args['min_core_version']
405
+				: '',
406
+			// the minimum version of WordPress that the addon will work with
407
+			'min_wp_version'        => isset($setup_args['min_wp_version'])
408
+				? (string) $setup_args['min_wp_version']
409
+				: EE_MIN_WP_VER_REQUIRED,
410
+			// full server path to main file (file loaded directly by WP)
411
+			'main_file_path'        => isset($setup_args['main_file_path'])
412
+				? (string) $setup_args['main_file_path']
413
+				: '',
414
+			// instance of \EventEspresso\core\domain\DomainInterface
415
+			'domain'                => isset($setup_args['domain']) && $setup_args['domain'] instanceof DomainInterface
416
+				? $setup_args['domain']
417
+				: null,
418
+			// Fully Qualified Class Name for the addon's Domain class
419
+			'domain_fqcn'           => isset($setup_args['domain_fqcn'])
420
+				? (string) $setup_args['domain_fqcn']
421
+				: '',
422
+			// path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
423
+			'admin_path'            => isset($setup_args['admin_path'])
424
+				? (string) $setup_args['admin_path'] : '',
425
+			// a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
426
+			'admin_callback'        => isset($setup_args['admin_callback'])
427
+				? (string) $setup_args['admin_callback']
428
+				: '',
429
+			// the section name for this addon's configuration settings section (defaults to "addons")
430
+			'config_section'        => isset($setup_args['config_section'])
431
+				? (string) $setup_args['config_section']
432
+				: 'addons',
433
+			// the class name for this addon's configuration settings object
434
+			'config_class'          => isset($setup_args['config_class'])
435
+				? (string) $setup_args['config_class'] : '',
436
+			// the name given to the config for this addons' configuration settings object (optional)
437
+			'config_name'           => isset($setup_args['config_name'])
438
+				? (string) $setup_args['config_name'] : '',
439
+			// an array of "class names" => "full server paths" for any classes that might be invoked by the addon
440
+			'autoloader_paths'      => isset($setup_args['autoloader_paths'])
441
+				? (array) $setup_args['autoloader_paths']
442
+				: array(),
443
+			// an array of  "full server paths" for any folders containing classes that might be invoked by the addon
444
+			'autoloader_folders'    => isset($setup_args['autoloader_folders'])
445
+				? (array) $setup_args['autoloader_folders']
446
+				: array(),
447
+			// array of full server paths to any EE_DMS data migration scripts used by the addon.
448
+			// The key should be the EE_Addon class name that this set of data migration scripts belongs to.
449
+			// If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
450
+			'dms_paths'             => isset($setup_args['dms_paths'])
451
+				? (array) $setup_args['dms_paths']
452
+				: array(),
453
+			// array of full server paths to any EED_Modules used by the addon
454
+			'module_paths'          => isset($setup_args['module_paths'])
455
+				? (array) $setup_args['module_paths']
456
+				: array(),
457
+			// array of full server paths to any EES_Shortcodes used by the addon
458
+			'shortcode_paths'       => isset($setup_args['shortcode_paths'])
459
+				? (array) $setup_args['shortcode_paths']
460
+				: array(),
461
+			'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
462
+				? (array) $setup_args['shortcode_fqcns']
463
+				: array(),
464
+			// array of full server paths to any WP_Widgets used by the addon
465
+			'widget_paths'          => isset($setup_args['widget_paths'])
466
+				? (array) $setup_args['widget_paths']
467
+				: array(),
468
+			// array of PUE options used by the addon
469
+			'pue_options'           => isset($setup_args['pue_options'])
470
+				? (array) $setup_args['pue_options']
471
+				: array(),
472
+			'message_types'         => isset($setup_args['message_types'])
473
+				? (array) $setup_args['message_types']
474
+				: array(),
475
+			'capabilities'          => isset($setup_args['capabilities'])
476
+				? (array) $setup_args['capabilities']
477
+				: array(),
478
+			'capability_maps'       => isset($setup_args['capability_maps'])
479
+				? (array) $setup_args['capability_maps']
480
+				: array(),
481
+			'model_paths'           => isset($setup_args['model_paths'])
482
+				? (array) $setup_args['model_paths']
483
+				: array(),
484
+			'class_paths'           => isset($setup_args['class_paths'])
485
+				? (array) $setup_args['class_paths']
486
+				: array(),
487
+			'model_extension_paths' => isset($setup_args['model_extension_paths'])
488
+				? (array) $setup_args['model_extension_paths']
489
+				: array(),
490
+			'class_extension_paths' => isset($setup_args['class_extension_paths'])
491
+				? (array) $setup_args['class_extension_paths']
492
+				: array(),
493
+			'custom_post_types'     => isset($setup_args['custom_post_types'])
494
+				? (array) $setup_args['custom_post_types']
495
+				: array(),
496
+			'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
497
+				? (array) $setup_args['custom_taxonomies']
498
+				: array(),
499
+			'payment_method_paths'  => isset($setup_args['payment_method_paths'])
500
+				? (array) $setup_args['payment_method_paths']
501
+				: array(),
502
+			'default_terms'         => isset($setup_args['default_terms'])
503
+				? (array) $setup_args['default_terms']
504
+				: array(),
505
+			// if not empty, inserts a new table row after this plugin's row on the WP Plugins page
506
+			// that can be used for adding upgrading/marketing info
507
+			'plugins_page_row'      => isset($setup_args['plugins_page_row']) ? $setup_args['plugins_page_row'] : '',
508
+			'namespace'             => isset(
509
+				$setup_args['namespace']['FQNS'],
510
+				$setup_args['namespace']['DIR']
511
+			)
512
+				? (array) $setup_args['namespace']
513
+				: array(),
514
+			'privacy_policies'      => isset($setup_args['privacy_policies'])
515
+				? (array) $setup_args['privacy_policies']
516
+				: '',
517
+		);
518
+		// if plugin_action_slug is NOT set, but an admin page path IS set,
519
+		// then let's just use the plugin_slug since that will be used for linking to the admin page
520
+		$addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
521
+												&& ! empty($addon_settings['admin_path'])
522
+			? $addon_settings['plugin_slug']
523
+			: $addon_settings['plugin_action_slug'];
524
+		// full server path to main file (file loaded directly by WP)
525
+		$addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
526
+		return $addon_settings;
527
+	}
528
+
529
+
530
+	/**
531
+	 * @param string $addon_name
532
+	 * @param array  $addon_settings
533
+	 * @return boolean
534
+	 */
535
+	private static function _addon_is_compatible($addon_name, array $addon_settings)
536
+	{
537
+		global $wp_version;
538
+		$incompatibility_message = '';
539
+		// check whether this addon version is compatible with EE core
540
+		if (
541
+			isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
542
+			&& ! self::_meets_min_core_version_requirement(
543
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
544
+				$addon_settings['version']
545
+			)
546
+		) {
547
+			$incompatibility_message = sprintf(
548
+				esc_html__(
549
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.',
550
+					'event_espresso'
551
+				),
552
+				$addon_name,
553
+				'<br />',
554
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
555
+				'<span style="font-weight: bold; color: #D54E21;">',
556
+				'</span><br />'
557
+			);
558
+		} elseif (
559
+			! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
560
+		) {
561
+			$incompatibility_message = sprintf(
562
+				esc_html__(
563
+					'%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
564
+					'event_espresso'
565
+				),
566
+				$addon_name,
567
+				self::_effective_version($addon_settings['min_core_version']),
568
+				self::_effective_version(espresso_version()),
569
+				'<br />',
570
+				'<span style="font-weight: bold; color: #D54E21;">',
571
+				'</span><br />'
572
+			);
573
+		} elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
574
+			$incompatibility_message = sprintf(
575
+				esc_html__(
576
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
577
+					'event_espresso'
578
+				),
579
+				$addon_name,
580
+				$addon_settings['min_wp_version'],
581
+				'<br />',
582
+				'<span style="font-weight: bold; color: #D54E21;">',
583
+				'</span><br />'
584
+			);
585
+		}
586
+		if (! empty($incompatibility_message)) {
587
+			// remove 'activate' from the REQUEST
588
+			// so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589
+			/** @var RequestInterface $request */
590
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
591
+			$request->unSetRequestParam('activate', true);
592
+			if (current_user_can('activate_plugins')) {
593
+				// show an error message indicating the plugin didn't activate properly
594
+				EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
595
+			}
596
+			unset($_GET['activate'], $_REQUEST['activate']);
597
+			if (! function_exists('deactivate_plugins')) {
598
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
599
+			}
600
+			deactivate_plugins(plugin_basename($addon_settings['main_file_path']));
601
+			// BAIL FROM THE ADDON REGISTRATION PROCESS
602
+			return false;
603
+		}
604
+		// addon IS compatible
605
+		return true;
606
+	}
607
+
608
+
609
+	/**
610
+	 * if plugin update engine is being used for auto-updates,
611
+	 * then let's set that up now before going any further so that ALL addons can be updated
612
+	 * (not needed if PUE is not being used)
613
+	 *
614
+	 * @param string $addon_name
615
+	 * @param string $class_name
616
+	 * @param array  $setup_args
617
+	 * @return void
618
+	 */
619
+	private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
620
+	{
621
+		if (! empty($setup_args['pue_options'])) {
622
+			self::$_settings[ $addon_name ]['pue_options'] = array(
623
+				'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
624
+					? (string) $setup_args['pue_options']['pue_plugin_slug']
625
+					: 'espresso_' . strtolower($class_name),
626
+				'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
627
+					? (string) $setup_args['pue_options']['plugin_basename']
628
+					: plugin_basename($setup_args['main_file_path']),
629
+				'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
630
+					? (string) $setup_args['pue_options']['checkPeriod']
631
+					: '24',
632
+				'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
633
+					? (string) $setup_args['pue_options']['use_wp_update']
634
+					: false,
635
+			);
636
+			add_action(
637
+				'AHEE__EE_System__brew_espresso__after_pue_init',
638
+				array('EE_Register_Addon', 'load_pue_update')
639
+			);
640
+		}
641
+	}
642
+
643
+
644
+	/**
645
+	 * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
646
+	 *
647
+	 * @param array $addon_settings
648
+	 * @return void
649
+	 */
650
+	private static function _setup_namespaces(array $addon_settings)
651
+	{
652
+		//
653
+		if (
654
+			isset(
655
+				$addon_settings['namespace']['FQNS'],
656
+				$addon_settings['namespace']['DIR']
657
+			)
658
+		) {
659
+			EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
660
+				$addon_settings['namespace']['FQNS'],
661
+				$addon_settings['namespace']['DIR']
662
+			);
663
+		}
664
+	}
665
+
666
+
667
+	/**
668
+	 * @param string $addon_name
669
+	 * @param array  $addon_settings
670
+	 * @return bool
671
+	 * @throws InvalidArgumentException
672
+	 * @throws InvalidDataTypeException
673
+	 * @throws InvalidInterfaceException
674
+	 */
675
+	private static function _addon_activation($addon_name, array $addon_settings)
676
+	{
677
+		// this is an activation request
678
+		if (did_action('activate_plugin')) {
679
+			// to find if THIS is the addon that was activated, just check if we have already registered it or not
680
+			// (as the newly-activated addon wasn't around the first time addons were registered).
681
+			// Note: the presence of pue_options in the addon registration options will initialize the $_settings
682
+			// property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
683
+			if (
684
+				! isset(self::$_settings[ $addon_name ])
685
+				|| (isset(self::$_settings[ $addon_name ])
686
+					&& ! isset(self::$_settings[ $addon_name ]['class_name'])
687
+				)
688
+			) {
689
+				self::$_settings[ $addon_name ] = $addon_settings;
690
+				$addon = self::_load_and_init_addon_class($addon_name);
691
+				$addon->set_activation_indicator_option();
692
+				// dont bother setting up the rest of the addon.
693
+				// we know it was just activated and the request will end soon
694
+			}
695
+			return true;
696
+		}
697
+		// make sure this was called in the right place!
698
+		if (
699
+			! did_action('AHEE__EE_System__load_espresso_addons')
700
+			|| did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
701
+		) {
702
+			EE_Error::doing_it_wrong(
703
+				__METHOD__,
704
+				sprintf(
705
+					esc_html__(
706
+						'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
707
+						'event_espresso'
708
+					),
709
+					$addon_name
710
+				),
711
+				'4.3.0'
712
+			);
713
+		}
714
+		// make sure addon settings are set correctly without overwriting anything existing
715
+		if (isset(self::$_settings[ $addon_name ])) {
716
+			self::$_settings[ $addon_name ] += $addon_settings;
717
+		} else {
718
+			self::$_settings[ $addon_name ] = $addon_settings;
719
+		}
720
+		return false;
721
+	}
722
+
723
+
724
+	/**
725
+	 * @param string $addon_name
726
+	 * @return void
727
+	 * @throws EE_Error
728
+	 */
729
+	private static function _setup_autoloaders($addon_name)
730
+	{
731
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
732
+			// setup autoloader for single file
733
+			EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
734
+		}
735
+		// setup autoloaders for folders
736
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
737
+			foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
738
+				EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
739
+			}
740
+		}
741
+	}
742
+
743
+
744
+	/**
745
+	 * register new models and extensions
746
+	 *
747
+	 * @param string $addon_name
748
+	 * @return void
749
+	 * @throws EE_Error
750
+	 */
751
+	private static function _register_models_and_extensions($addon_name)
752
+	{
753
+		// register new models
754
+		if (
755
+			! empty(self::$_settings[ $addon_name ]['model_paths'])
756
+			|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
757
+		) {
758
+			EE_Register_Model::register(
759
+				$addon_name,
760
+				array(
761
+					'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
762
+					'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
763
+				)
764
+			);
765
+		}
766
+		// register model extensions
767
+		if (
768
+			! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
769
+			|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
770
+		) {
771
+			EE_Register_Model_Extensions::register(
772
+				$addon_name,
773
+				array(
774
+					'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
775
+					'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
776
+				)
777
+			);
778
+		}
779
+	}
780
+
781
+
782
+	/**
783
+	 * @param string $addon_name
784
+	 * @return void
785
+	 * @throws EE_Error
786
+	 */
787
+	private static function _register_data_migration_scripts($addon_name)
788
+	{
789
+		// setup DMS
790
+		if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
791
+			EE_Register_Data_Migration_Scripts::register(
792
+				$addon_name,
793
+				array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
794
+			);
795
+		}
796
+	}
797
+
798
+
799
+	/**
800
+	 * @param string $addon_name
801
+	 * @return void
802
+	 * @throws EE_Error
803
+	 */
804
+	private static function _register_config($addon_name)
805
+	{
806
+		// if config_class is present let's register config.
807
+		if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
808
+			EE_Register_Config::register(
809
+				self::$_settings[ $addon_name ]['config_class'],
810
+				array(
811
+					'config_section' => self::$_settings[ $addon_name ]['config_section'],
812
+					'config_name'    => self::$_settings[ $addon_name ]['config_name'],
813
+				)
814
+			);
815
+		}
816
+	}
817
+
818
+
819
+	/**
820
+	 * @param string $addon_name
821
+	 * @return void
822
+	 * @throws EE_Error
823
+	 */
824
+	private static function _register_admin_pages($addon_name)
825
+	{
826
+		if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
827
+			EE_Register_Admin_Page::register(
828
+				$addon_name,
829
+				array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
830
+			);
831
+		}
832
+	}
833
+
834
+
835
+	/**
836
+	 * @param string $addon_name
837
+	 * @return void
838
+	 * @throws EE_Error
839
+	 */
840
+	private static function _register_modules($addon_name)
841
+	{
842
+		if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
843
+			EE_Register_Module::register(
844
+				$addon_name,
845
+				array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
846
+			);
847
+		}
848
+	}
849
+
850
+
851
+	/**
852
+	 * @param string $addon_name
853
+	 * @return void
854
+	 * @throws EE_Error
855
+	 */
856
+	private static function _register_shortcodes($addon_name)
857
+	{
858
+		if (
859
+			! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
860
+			|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
861
+		) {
862
+			EE_Register_Shortcode::register(
863
+				$addon_name,
864
+				array(
865
+					'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
866
+						? self::$_settings[ $addon_name ]['shortcode_paths'] : array(),
867
+					'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
868
+						? self::$_settings[ $addon_name ]['shortcode_fqcns'] : array(),
869
+				)
870
+			);
871
+		}
872
+	}
873
+
874
+
875
+	/**
876
+	 * @param string $addon_name
877
+	 * @return void
878
+	 * @throws EE_Error
879
+	 */
880
+	private static function _register_widgets($addon_name)
881
+	{
882
+		if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
883
+			EE_Register_Widget::register(
884
+				$addon_name,
885
+				array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
886
+			);
887
+		}
888
+	}
889
+
890
+
891
+	/**
892
+	 * @param string $addon_name
893
+	 * @return void
894
+	 * @throws EE_Error
895
+	 */
896
+	private static function _register_capabilities($addon_name)
897
+	{
898
+		if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
899
+			EE_Register_Capabilities::register(
900
+				$addon_name,
901
+				array(
902
+					'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
903
+					'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
904
+				)
905
+			);
906
+		}
907
+	}
908
+
909
+
910
+	/**
911
+	 * @param string $addon_name
912
+	 * @return void
913
+	 */
914
+	private static function _register_message_types($addon_name)
915
+	{
916
+		if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
917
+			add_action(
918
+				'EE_Brewing_Regular___messages_caf',
919
+				array('EE_Register_Addon', 'register_message_types')
920
+			);
921
+		}
922
+	}
923
+
924
+
925
+	/**
926
+	 * @param string $addon_name
927
+	 * @return void
928
+	 * @throws EE_Error
929
+	 */
930
+	private static function _register_custom_post_types($addon_name)
931
+	{
932
+		if (
933
+			! empty(self::$_settings[ $addon_name ]['custom_post_types'])
934
+			|| ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
935
+		) {
936
+			EE_Register_CPT::register(
937
+				$addon_name,
938
+				array(
939
+					'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
940
+					'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
941
+					'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
942
+				)
943
+			);
944
+		}
945
+	}
946
+
947
+
948
+	/**
949
+	 * @param string $addon_name
950
+	 * @return void
951
+	 * @throws InvalidArgumentException
952
+	 * @throws InvalidInterfaceException
953
+	 * @throws InvalidDataTypeException
954
+	 * @throws DomainException
955
+	 * @throws EE_Error
956
+	 */
957
+	private static function _register_payment_methods($addon_name)
958
+	{
959
+		if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
960
+			EE_Register_Payment_Method::register(
961
+				$addon_name,
962
+				array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
963
+			);
964
+		}
965
+	}
966
+
967
+
968
+	/**
969
+	 * @param string $addon_name
970
+	 * @return void
971
+	 * @throws InvalidArgumentException
972
+	 * @throws InvalidInterfaceException
973
+	 * @throws InvalidDataTypeException
974
+	 * @throws DomainException
975
+	 */
976
+	private static function registerPrivacyPolicies($addon_name)
977
+	{
978
+		if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
979
+			EE_Register_Privacy_Policy::register(
980
+				$addon_name,
981
+				self::$_settings[ $addon_name ]['privacy_policies']
982
+			);
983
+		}
984
+	}
985
+
986
+
987
+	/**
988
+	 * @param string $addon_name
989
+	 * @return void
990
+	 */
991
+	private static function registerPersonalDataExporters($addon_name)
992
+	{
993
+		if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
994
+			EE_Register_Personal_Data_Eraser::register(
995
+				$addon_name,
996
+				self::$_settings[ $addon_name ]['personal_data_exporters']
997
+			);
998
+		}
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * @param string $addon_name
1004
+	 * @return void
1005
+	 */
1006
+	private static function registerPersonalDataErasers($addon_name)
1007
+	{
1008
+		if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1009
+			EE_Register_Personal_Data_Eraser::register(
1010
+				$addon_name,
1011
+				self::$_settings[ $addon_name ]['personal_data_erasers']
1012
+			);
1013
+		}
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * Loads and instantiates the EE_Addon class and adds it onto the registry
1019
+	 *
1020
+	 * @param string $addon_name
1021
+	 * @return EE_Addon
1022
+	 * @throws InvalidArgumentException
1023
+	 * @throws InvalidInterfaceException
1024
+	 * @throws InvalidDataTypeException
1025
+	 */
1026
+	private static function _load_and_init_addon_class($addon_name)
1027
+	{
1028
+		$addon = LoaderFactory::getLoader()->getShared(
1029
+			self::$_settings[ $addon_name ]['class_name'],
1030
+			array('EE_Registry::create(addon)' => true)
1031
+		);
1032
+		if (! $addon instanceof EE_Addon) {
1033
+			throw new DomainException(
1034
+				sprintf(
1035
+					esc_html__(
1036
+						'Failed to instantiate the %1$s class. PLease check that the class exists.',
1037
+						'event_espresso'
1038
+					),
1039
+					$addon_name
1040
+				)
1041
+			);
1042
+		}
1043
+		// setter inject dep map if required
1044
+		if ($addon->dependencyMap() === null) {
1045
+			$addon->setDependencyMap(LoaderFactory::getLoader()->getShared('EE_Dependency_Map'));
1046
+		}
1047
+		// setter inject domain if required
1048
+		EE_Register_Addon::injectAddonDomain($addon_name, $addon);
1049
+
1050
+		$addon->set_name($addon_name);
1051
+		$addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1052
+		$addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1053
+		$addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1054
+		$addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1055
+		$addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1056
+		$addon->set_version(self::$_settings[ $addon_name ]['version']);
1057
+		$addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1058
+		$addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1059
+		$addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1060
+		$addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1061
+		// setup the add-on's pue_slug if we have one.
1062
+		if (! empty(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug'])) {
1063
+			$addon->setPueSlug(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug']);
1064
+		}
1065
+		// unfortunately this can't be hooked in upon construction,
1066
+		// because we don't have the plugin's mainfile path upon construction.
1067
+		register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1068
+		// call any additional admin_callback functions during load_admin_controller hook
1069
+		if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1070
+			add_action(
1071
+				'AHEE__EE_System__load_controllers__load_admin_controllers',
1072
+				array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1073
+			);
1074
+		}
1075
+		return $addon;
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * @param string   $addon_name
1081
+	 * @param EE_Addon $addon
1082
+	 * @since   4.10.13.p
1083
+	 */
1084
+	private static function injectAddonDomain($addon_name, EE_Addon $addon)
1085
+	{
1086
+		if ($addon instanceof RequiresDomainInterface && $addon->domain() === null) {
1087
+			// using supplied Domain object
1088
+			$domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1089
+				? self::$_settings[ $addon_name ]['domain']
1090
+				: null;
1091
+			// or construct one using Domain FQCN
1092
+			if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1093
+				$domain = LoaderFactory::getLoader()->getShared(
1094
+					self::$_settings[ $addon_name ]['domain_fqcn'],
1095
+					[
1096
+						new EventEspresso\core\domain\values\FilePath(
1097
+							self::$_settings[ $addon_name ]['main_file_path']
1098
+						),
1099
+						EventEspresso\core\domain\values\Version::fromString(
1100
+							self::$_settings[ $addon_name ]['version']
1101
+						),
1102
+					]
1103
+				);
1104
+			}
1105
+			if ($domain instanceof DomainInterface) {
1106
+				$addon->setDomain($domain);
1107
+			}
1108
+		}
1109
+	}
1110
+
1111
+
1112
+	/**
1113
+	 *    load_pue_update - Update notifications
1114
+	 *
1115
+	 * @return void
1116
+	 * @throws InvalidArgumentException
1117
+	 * @throws InvalidDataTypeException
1118
+	 * @throws InvalidInterfaceException
1119
+	 */
1120
+	public static function load_pue_update()
1121
+	{
1122
+		// PUE client existence
1123
+		if (! is_readable(EE_THIRD_PARTY . 'pue/pue-client.php')) {
1124
+			return;
1125
+		}
1126
+		// load PUE client
1127
+		require_once EE_THIRD_PARTY . 'pue/pue-client.php';
1128
+		$license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1129
+		// cycle thru settings
1130
+		foreach (self::$_settings as $settings) {
1131
+			if (empty($settings['pue_options'])) {
1132
+				continue;
1133
+			}
1134
+			// initiate the class and start the plugin update engine!
1135
+			new PluginUpdateEngineChecker(
1136
+				// host file URL
1137
+				$license_server,
1138
+				// plugin slug(s)
1139
+				array(
1140
+					'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1141
+					'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1142
+				),
1143
+				// options
1144
+				array(
1145
+					'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1146
+					'lang_domain'       => 'event_espresso',
1147
+					'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1148
+					'option_key'        => 'ee_site_license_key',
1149
+					'options_page_slug' => 'event_espresso',
1150
+					'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1151
+					// if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1152
+					'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1153
+				)
1154
+			);
1155
+		}
1156
+	}
1157
+
1158
+
1159
+	/**
1160
+	 * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1161
+	 *
1162
+	 * @since 4.4.0
1163
+	 * @return void
1164
+	 * @throws EE_Error
1165
+	 */
1166
+	public static function register_message_types()
1167
+	{
1168
+		foreach (self::$_settings as $settings) {
1169
+			if (! empty($settings['message_types'])) {
1170
+				foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1171
+					EE_Register_Message_Type::register($message_type, $message_type_settings);
1172
+				}
1173
+			}
1174
+		}
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * This deregisters an addon that was previously registered with a specific addon_name.
1180
+	 *
1181
+	 * @param string $addon_name the name for the addon that was previously registered
1182
+	 * @throws DomainException
1183
+	 * @throws InvalidArgumentException
1184
+	 * @throws InvalidDataTypeException
1185
+	 * @throws InvalidInterfaceException
1186
+	 *@since    4.3.0
1187
+	 */
1188
+	public static function deregister($addon_name = '')
1189
+	{
1190
+		if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1191
+			try {
1192
+				do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1193
+				$class_name = self::$_settings[ $addon_name ]['class_name'];
1194
+				if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1195
+					// setup DMS
1196
+					EE_Register_Data_Migration_Scripts::deregister($addon_name);
1197
+				}
1198
+				if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1199
+					// register admin page
1200
+					EE_Register_Admin_Page::deregister($addon_name);
1201
+				}
1202
+				if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1203
+					// add to list of modules to be registered
1204
+					EE_Register_Module::deregister($addon_name);
1205
+				}
1206
+				if (
1207
+					! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1208
+					|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1209
+				) {
1210
+					// add to list of shortcodes to be registered
1211
+					EE_Register_Shortcode::deregister($addon_name);
1212
+				}
1213
+				if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1214
+					// if config_class present let's register config.
1215
+					EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1216
+				}
1217
+				if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1218
+					// add to list of widgets to be registered
1219
+					EE_Register_Widget::deregister($addon_name);
1220
+				}
1221
+				if (
1222
+					! empty(self::$_settings[ $addon_name ]['model_paths'])
1223
+					|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
1224
+				) {
1225
+					// add to list of shortcodes to be registered
1226
+					EE_Register_Model::deregister($addon_name);
1227
+				}
1228
+				if (
1229
+					! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1230
+					|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1231
+				) {
1232
+					// add to list of shortcodes to be registered
1233
+					EE_Register_Model_Extensions::deregister($addon_name);
1234
+				}
1235
+				if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1236
+					foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1237
+						EE_Register_Message_Type::deregister($message_type);
1238
+					}
1239
+				}
1240
+				// deregister capabilities for addon
1241
+				if (
1242
+					! empty(self::$_settings[ $addon_name ]['capabilities'])
1243
+					|| ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1244
+				) {
1245
+					EE_Register_Capabilities::deregister($addon_name);
1246
+				}
1247
+				// deregister custom_post_types for addon
1248
+				if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1249
+					EE_Register_CPT::deregister($addon_name);
1250
+				}
1251
+				if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1252
+					EE_Register_Payment_Method::deregister($addon_name);
1253
+				}
1254
+				$addon = EE_Registry::instance()->getAddon($class_name);
1255
+				if ($addon instanceof EE_Addon) {
1256
+					remove_action(
1257
+						'deactivate_' . $addon->get_main_plugin_file_basename(),
1258
+						array($addon, 'deactivation')
1259
+					);
1260
+					remove_action(
1261
+						'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1262
+						array($addon, 'initialize_db_if_no_migrations_required')
1263
+					);
1264
+					// remove `after_registration` call
1265
+					remove_action(
1266
+						'AHEE__EE_System__load_espresso_addons__complete',
1267
+						array($addon, 'after_registration'),
1268
+						999
1269
+					);
1270
+				}
1271
+				EE_Registry::instance()->removeAddon($class_name);
1272
+				LoaderFactory::getLoader()->remove($class_name);
1273
+			} catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1274
+				// the add-on was not yet registered in the registry,
1275
+				// so RegistryContainer::__get() throws this exception.
1276
+				// also no need to worry about this or log it,
1277
+				// it's ok to deregister an add-on before its registered in the registry
1278
+			} catch (Exception $e) {
1279
+				new ExceptionLogger($e);
1280
+			}
1281
+			unset(self::$_settings[ $addon_name ]);
1282
+			do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1283
+		}
1284
+	}
1285 1285
 }
Please login to merge, or discard this patch.
Spacing   +118 added lines, -118 removed lines patch added patch discarded remove patch
@@ -69,15 +69,15 @@  discard block
 block discarded – undo
69 69
         // offsets:    0 . 1 . 2 . 3 . 4
70 70
         $version_parts = explode('.', $min_core_version);
71 71
         // check they specified the micro version (after 2nd period)
72
-        if (! isset($version_parts[2])) {
72
+        if ( ! isset($version_parts[2])) {
73 73
             $version_parts[2] = '0';
74 74
         }
75 75
         // if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
76 76
         // soon we can assume that's 'rc', but this current version is 'alpha'
77
-        if (! isset($version_parts[3])) {
77
+        if ( ! isset($version_parts[3])) {
78 78
             $version_parts[3] = 'dev';
79 79
         }
80
-        if (! isset($version_parts[4])) {
80
+        if ( ! isset($version_parts[4])) {
81 81
             $version_parts[4] = '000';
82 82
         }
83 83
         return implode('.', $version_parts);
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
         EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
265 265
         // does this addon work with this version of core or WordPress ?
266 266
         // does this addon work with this version of core or WordPress ?
267
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
267
+        if ( ! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
268 268
             return;
269 269
         }
270 270
         // register namespaces
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
                 )
329 329
             );
330 330
         }
331
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
331
+        if ( ! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
332 332
             throw new EE_Error(
333 333
                 sprintf(
334 334
                     esc_html__(
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
             );
341 341
         }
342 342
         // check that addon has not already been registered with that name
343
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
343
+        if (isset(self::$_settings[$addon_name]) && ! did_action('activate_plugin')) {
344 344
             throw new EE_Error(
345 345
                 sprintf(
346 346
                     esc_html__(
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
         // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
373 373
         return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
374 374
             ? $class_name
375
-            : 'EE_' . $class_name;
375
+            : 'EE_'.$class_name;
376 376
     }
377 377
 
378 378
 
@@ -538,9 +538,9 @@  discard block
 block discarded – undo
538 538
         $incompatibility_message = '';
539 539
         // check whether this addon version is compatible with EE core
540 540
         if (
541
-            isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
541
+            isset(EE_Register_Addon::$_incompatible_addons[$addon_name])
542 542
             && ! self::_meets_min_core_version_requirement(
543
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
543
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
544 544
                 $addon_settings['version']
545 545
             )
546 546
         ) {
@@ -551,7 +551,7 @@  discard block
 block discarded – undo
551 551
                 ),
552 552
                 $addon_name,
553 553
                 '<br />',
554
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
554
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
555 555
                 '<span style="font-weight: bold; color: #D54E21;">',
556 556
                 '</span><br />'
557 557
             );
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
                 '</span><br />'
584 584
             );
585 585
         }
586
-        if (! empty($incompatibility_message)) {
586
+        if ( ! empty($incompatibility_message)) {
587 587
             // remove 'activate' from the REQUEST
588 588
             // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
589 589
             /** @var RequestInterface $request */
@@ -594,8 +594,8 @@  discard block
 block discarded – undo
594 594
                 EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
595 595
             }
596 596
             unset($_GET['activate'], $_REQUEST['activate']);
597
-            if (! function_exists('deactivate_plugins')) {
598
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
597
+            if ( ! function_exists('deactivate_plugins')) {
598
+                require_once ABSPATH.'wp-admin/includes/plugin.php';
599 599
             }
600 600
             deactivate_plugins(plugin_basename($addon_settings['main_file_path']));
601 601
             // BAIL FROM THE ADDON REGISTRATION PROCESS
@@ -618,11 +618,11 @@  discard block
 block discarded – undo
618 618
      */
619 619
     private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
620 620
     {
621
-        if (! empty($setup_args['pue_options'])) {
622
-            self::$_settings[ $addon_name ]['pue_options'] = array(
621
+        if ( ! empty($setup_args['pue_options'])) {
622
+            self::$_settings[$addon_name]['pue_options'] = array(
623 623
                 'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
624 624
                     ? (string) $setup_args['pue_options']['pue_plugin_slug']
625
-                    : 'espresso_' . strtolower($class_name),
625
+                    : 'espresso_'.strtolower($class_name),
626 626
                 'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
627 627
                     ? (string) $setup_args['pue_options']['plugin_basename']
628 628
                     : plugin_basename($setup_args['main_file_path']),
@@ -681,12 +681,12 @@  discard block
 block discarded – undo
681 681
             // Note: the presence of pue_options in the addon registration options will initialize the $_settings
682 682
             // property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
683 683
             if (
684
-                ! isset(self::$_settings[ $addon_name ])
685
-                || (isset(self::$_settings[ $addon_name ])
686
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
684
+                ! isset(self::$_settings[$addon_name])
685
+                || (isset(self::$_settings[$addon_name])
686
+                    && ! isset(self::$_settings[$addon_name]['class_name'])
687 687
                 )
688 688
             ) {
689
-                self::$_settings[ $addon_name ] = $addon_settings;
689
+                self::$_settings[$addon_name] = $addon_settings;
690 690
                 $addon = self::_load_and_init_addon_class($addon_name);
691 691
                 $addon->set_activation_indicator_option();
692 692
                 // dont bother setting up the rest of the addon.
@@ -712,10 +712,10 @@  discard block
 block discarded – undo
712 712
             );
713 713
         }
714 714
         // make sure addon settings are set correctly without overwriting anything existing
715
-        if (isset(self::$_settings[ $addon_name ])) {
716
-            self::$_settings[ $addon_name ] += $addon_settings;
715
+        if (isset(self::$_settings[$addon_name])) {
716
+            self::$_settings[$addon_name] += $addon_settings;
717 717
         } else {
718
-            self::$_settings[ $addon_name ] = $addon_settings;
718
+            self::$_settings[$addon_name] = $addon_settings;
719 719
         }
720 720
         return false;
721 721
     }
@@ -728,13 +728,13 @@  discard block
 block discarded – undo
728 728
      */
729 729
     private static function _setup_autoloaders($addon_name)
730 730
     {
731
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
731
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_paths'])) {
732 732
             // setup autoloader for single file
733
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
733
+            EEH_Autoloader::instance()->register_autoloader(self::$_settings[$addon_name]['autoloader_paths']);
734 734
         }
735 735
         // setup autoloaders for folders
736
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
737
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
736
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_folders'])) {
737
+            foreach ((array) self::$_settings[$addon_name]['autoloader_folders'] as $autoloader_folder) {
738 738
                 EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
739 739
             }
740 740
         }
@@ -752,27 +752,27 @@  discard block
 block discarded – undo
752 752
     {
753 753
         // register new models
754 754
         if (
755
-            ! empty(self::$_settings[ $addon_name ]['model_paths'])
756
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
755
+            ! empty(self::$_settings[$addon_name]['model_paths'])
756
+            || ! empty(self::$_settings[$addon_name]['class_paths'])
757 757
         ) {
758 758
             EE_Register_Model::register(
759 759
                 $addon_name,
760 760
                 array(
761
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
762
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
761
+                    'model_paths' => self::$_settings[$addon_name]['model_paths'],
762
+                    'class_paths' => self::$_settings[$addon_name]['class_paths'],
763 763
                 )
764 764
             );
765 765
         }
766 766
         // register model extensions
767 767
         if (
768
-            ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
769
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
768
+            ! empty(self::$_settings[$addon_name]['model_extension_paths'])
769
+            || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
770 770
         ) {
771 771
             EE_Register_Model_Extensions::register(
772 772
                 $addon_name,
773 773
                 array(
774
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
775
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
774
+                    'model_extension_paths' => self::$_settings[$addon_name]['model_extension_paths'],
775
+                    'class_extension_paths' => self::$_settings[$addon_name]['class_extension_paths'],
776 776
                 )
777 777
             );
778 778
         }
@@ -787,10 +787,10 @@  discard block
 block discarded – undo
787 787
     private static function _register_data_migration_scripts($addon_name)
788 788
     {
789 789
         // setup DMS
790
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
790
+        if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
791 791
             EE_Register_Data_Migration_Scripts::register(
792 792
                 $addon_name,
793
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
793
+                array('dms_paths' => self::$_settings[$addon_name]['dms_paths'])
794 794
             );
795 795
         }
796 796
     }
@@ -804,12 +804,12 @@  discard block
 block discarded – undo
804 804
     private static function _register_config($addon_name)
805 805
     {
806 806
         // if config_class is present let's register config.
807
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
807
+        if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
808 808
             EE_Register_Config::register(
809
-                self::$_settings[ $addon_name ]['config_class'],
809
+                self::$_settings[$addon_name]['config_class'],
810 810
                 array(
811
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
812
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
811
+                    'config_section' => self::$_settings[$addon_name]['config_section'],
812
+                    'config_name'    => self::$_settings[$addon_name]['config_name'],
813 813
                 )
814 814
             );
815 815
         }
@@ -823,10 +823,10 @@  discard block
 block discarded – undo
823 823
      */
824 824
     private static function _register_admin_pages($addon_name)
825 825
     {
826
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
826
+        if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
827 827
             EE_Register_Admin_Page::register(
828 828
                 $addon_name,
829
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
829
+                array('page_path' => self::$_settings[$addon_name]['admin_path'])
830 830
             );
831 831
         }
832 832
     }
@@ -839,10 +839,10 @@  discard block
 block discarded – undo
839 839
      */
840 840
     private static function _register_modules($addon_name)
841 841
     {
842
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
842
+        if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
843 843
             EE_Register_Module::register(
844 844
                 $addon_name,
845
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
845
+                array('module_paths' => self::$_settings[$addon_name]['module_paths'])
846 846
             );
847 847
         }
848 848
     }
@@ -856,16 +856,16 @@  discard block
 block discarded – undo
856 856
     private static function _register_shortcodes($addon_name)
857 857
     {
858 858
         if (
859
-            ! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
860
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
859
+            ! empty(self::$_settings[$addon_name]['shortcode_paths'])
860
+            || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
861 861
         ) {
862 862
             EE_Register_Shortcode::register(
863 863
                 $addon_name,
864 864
                 array(
865
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
866
-                        ? self::$_settings[ $addon_name ]['shortcode_paths'] : array(),
867
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
868
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns'] : array(),
865
+                    'shortcode_paths' => isset(self::$_settings[$addon_name]['shortcode_paths'])
866
+                        ? self::$_settings[$addon_name]['shortcode_paths'] : array(),
867
+                    'shortcode_fqcns' => isset(self::$_settings[$addon_name]['shortcode_fqcns'])
868
+                        ? self::$_settings[$addon_name]['shortcode_fqcns'] : array(),
869 869
                 )
870 870
             );
871 871
         }
@@ -879,10 +879,10 @@  discard block
 block discarded – undo
879 879
      */
880 880
     private static function _register_widgets($addon_name)
881 881
     {
882
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
882
+        if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
883 883
             EE_Register_Widget::register(
884 884
                 $addon_name,
885
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
885
+                array('widget_paths' => self::$_settings[$addon_name]['widget_paths'])
886 886
             );
887 887
         }
888 888
     }
@@ -895,12 +895,12 @@  discard block
 block discarded – undo
895 895
      */
896 896
     private static function _register_capabilities($addon_name)
897 897
     {
898
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
898
+        if ( ! empty(self::$_settings[$addon_name]['capabilities'])) {
899 899
             EE_Register_Capabilities::register(
900 900
                 $addon_name,
901 901
                 array(
902
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
903
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
902
+                    'capabilities'    => self::$_settings[$addon_name]['capabilities'],
903
+                    'capability_maps' => self::$_settings[$addon_name]['capability_maps'],
904 904
                 )
905 905
             );
906 906
         }
@@ -913,7 +913,7 @@  discard block
 block discarded – undo
913 913
      */
914 914
     private static function _register_message_types($addon_name)
915 915
     {
916
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
916
+        if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
917 917
             add_action(
918 918
                 'EE_Brewing_Regular___messages_caf',
919 919
                 array('EE_Register_Addon', 'register_message_types')
@@ -930,15 +930,15 @@  discard block
 block discarded – undo
930 930
     private static function _register_custom_post_types($addon_name)
931 931
     {
932 932
         if (
933
-            ! empty(self::$_settings[ $addon_name ]['custom_post_types'])
934
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
933
+            ! empty(self::$_settings[$addon_name]['custom_post_types'])
934
+            || ! empty(self::$_settings[$addon_name]['custom_taxonomies'])
935 935
         ) {
936 936
             EE_Register_CPT::register(
937 937
                 $addon_name,
938 938
                 array(
939
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
940
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
941
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
939
+                    'cpts'          => self::$_settings[$addon_name]['custom_post_types'],
940
+                    'cts'           => self::$_settings[$addon_name]['custom_taxonomies'],
941
+                    'default_terms' => self::$_settings[$addon_name]['default_terms'],
942 942
                 )
943 943
             );
944 944
         }
@@ -956,10 +956,10 @@  discard block
 block discarded – undo
956 956
      */
957 957
     private static function _register_payment_methods($addon_name)
958 958
     {
959
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
959
+        if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
960 960
             EE_Register_Payment_Method::register(
961 961
                 $addon_name,
962
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
962
+                array('payment_method_paths' => self::$_settings[$addon_name]['payment_method_paths'])
963 963
             );
964 964
         }
965 965
     }
@@ -975,10 +975,10 @@  discard block
 block discarded – undo
975 975
      */
976 976
     private static function registerPrivacyPolicies($addon_name)
977 977
     {
978
-        if (! empty(self::$_settings[ $addon_name ]['privacy_policies'])) {
978
+        if ( ! empty(self::$_settings[$addon_name]['privacy_policies'])) {
979 979
             EE_Register_Privacy_Policy::register(
980 980
                 $addon_name,
981
-                self::$_settings[ $addon_name ]['privacy_policies']
981
+                self::$_settings[$addon_name]['privacy_policies']
982 982
             );
983 983
         }
984 984
     }
@@ -990,10 +990,10 @@  discard block
 block discarded – undo
990 990
      */
991 991
     private static function registerPersonalDataExporters($addon_name)
992 992
     {
993
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_exporters'])) {
993
+        if ( ! empty(self::$_settings[$addon_name]['personal_data_exporters'])) {
994 994
             EE_Register_Personal_Data_Eraser::register(
995 995
                 $addon_name,
996
-                self::$_settings[ $addon_name ]['personal_data_exporters']
996
+                self::$_settings[$addon_name]['personal_data_exporters']
997 997
             );
998 998
         }
999 999
     }
@@ -1005,10 +1005,10 @@  discard block
 block discarded – undo
1005 1005
      */
1006 1006
     private static function registerPersonalDataErasers($addon_name)
1007 1007
     {
1008
-        if (! empty(self::$_settings[ $addon_name ]['personal_data_erasers'])) {
1008
+        if ( ! empty(self::$_settings[$addon_name]['personal_data_erasers'])) {
1009 1009
             EE_Register_Personal_Data_Eraser::register(
1010 1010
                 $addon_name,
1011
-                self::$_settings[ $addon_name ]['personal_data_erasers']
1011
+                self::$_settings[$addon_name]['personal_data_erasers']
1012 1012
             );
1013 1013
         }
1014 1014
     }
@@ -1026,10 +1026,10 @@  discard block
 block discarded – undo
1026 1026
     private static function _load_and_init_addon_class($addon_name)
1027 1027
     {
1028 1028
         $addon = LoaderFactory::getLoader()->getShared(
1029
-            self::$_settings[ $addon_name ]['class_name'],
1029
+            self::$_settings[$addon_name]['class_name'],
1030 1030
             array('EE_Registry::create(addon)' => true)
1031 1031
         );
1032
-        if (! $addon instanceof EE_Addon) {
1032
+        if ( ! $addon instanceof EE_Addon) {
1033 1033
             throw new DomainException(
1034 1034
                 sprintf(
1035 1035
                     esc_html__(
@@ -1048,28 +1048,28 @@  discard block
 block discarded – undo
1048 1048
         EE_Register_Addon::injectAddonDomain($addon_name, $addon);
1049 1049
 
1050 1050
         $addon->set_name($addon_name);
1051
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
1052
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
1053
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
1054
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
1055
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
1056
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
1057
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
1058
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
1059
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
1060
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
1051
+        $addon->set_plugin_slug(self::$_settings[$addon_name]['plugin_slug']);
1052
+        $addon->set_plugin_basename(self::$_settings[$addon_name]['plugin_basename']);
1053
+        $addon->set_main_plugin_file(self::$_settings[$addon_name]['main_file_path']);
1054
+        $addon->set_plugin_action_slug(self::$_settings[$addon_name]['plugin_action_slug']);
1055
+        $addon->set_plugins_page_row(self::$_settings[$addon_name]['plugins_page_row']);
1056
+        $addon->set_version(self::$_settings[$addon_name]['version']);
1057
+        $addon->set_min_core_version(self::_effective_version(self::$_settings[$addon_name]['min_core_version']));
1058
+        $addon->set_config_section(self::$_settings[$addon_name]['config_section']);
1059
+        $addon->set_config_class(self::$_settings[$addon_name]['config_class']);
1060
+        $addon->set_config_name(self::$_settings[$addon_name]['config_name']);
1061 1061
         // setup the add-on's pue_slug if we have one.
1062
-        if (! empty(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug'])) {
1063
-            $addon->setPueSlug(self::$_settings[ $addon_name ]['pue_options']['pue_plugin_slug']);
1062
+        if ( ! empty(self::$_settings[$addon_name]['pue_options']['pue_plugin_slug'])) {
1063
+            $addon->setPueSlug(self::$_settings[$addon_name]['pue_options']['pue_plugin_slug']);
1064 1064
         }
1065 1065
         // unfortunately this can't be hooked in upon construction,
1066 1066
         // because we don't have the plugin's mainfile path upon construction.
1067 1067
         register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
1068 1068
         // call any additional admin_callback functions during load_admin_controller hook
1069
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
1069
+        if ( ! empty(self::$_settings[$addon_name]['admin_callback'])) {
1070 1070
             add_action(
1071 1071
                 'AHEE__EE_System__load_controllers__load_admin_controllers',
1072
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1072
+                array($addon, self::$_settings[$addon_name]['admin_callback'])
1073 1073
             );
1074 1074
         }
1075 1075
         return $addon;
@@ -1085,19 +1085,19 @@  discard block
 block discarded – undo
1085 1085
     {
1086 1086
         if ($addon instanceof RequiresDomainInterface && $addon->domain() === null) {
1087 1087
             // using supplied Domain object
1088
-            $domain = self::$_settings[ $addon_name ]['domain'] instanceof DomainInterface
1089
-                ? self::$_settings[ $addon_name ]['domain']
1088
+            $domain = self::$_settings[$addon_name]['domain'] instanceof DomainInterface
1089
+                ? self::$_settings[$addon_name]['domain']
1090 1090
                 : null;
1091 1091
             // or construct one using Domain FQCN
1092
-            if ($domain === null && self::$_settings[ $addon_name ]['domain_fqcn'] !== '') {
1092
+            if ($domain === null && self::$_settings[$addon_name]['domain_fqcn'] !== '') {
1093 1093
                 $domain = LoaderFactory::getLoader()->getShared(
1094
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
1094
+                    self::$_settings[$addon_name]['domain_fqcn'],
1095 1095
                     [
1096 1096
                         new EventEspresso\core\domain\values\FilePath(
1097
-                            self::$_settings[ $addon_name ]['main_file_path']
1097
+                            self::$_settings[$addon_name]['main_file_path']
1098 1098
                         ),
1099 1099
                         EventEspresso\core\domain\values\Version::fromString(
1100
-                            self::$_settings[ $addon_name ]['version']
1100
+                            self::$_settings[$addon_name]['version']
1101 1101
                         ),
1102 1102
                     ]
1103 1103
                 );
@@ -1120,11 +1120,11 @@  discard block
 block discarded – undo
1120 1120
     public static function load_pue_update()
1121 1121
     {
1122 1122
         // PUE client existence
1123
-        if (! is_readable(EE_THIRD_PARTY . 'pue/pue-client.php')) {
1123
+        if ( ! is_readable(EE_THIRD_PARTY.'pue/pue-client.php')) {
1124 1124
             return;
1125 1125
         }
1126 1126
         // load PUE client
1127
-        require_once EE_THIRD_PARTY . 'pue/pue-client.php';
1127
+        require_once EE_THIRD_PARTY.'pue/pue-client.php';
1128 1128
         $license_server = defined('PUE_UPDATES_ENDPOINT') ? PUE_UPDATES_ENDPOINT : 'https://eventespresso.com';
1129 1129
         // cycle thru settings
1130 1130
         foreach (self::$_settings as $settings) {
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
                 // plugin slug(s)
1139 1139
                 array(
1140 1140
                     'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1141
-                    'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1141
+                    'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'].'-pr'),
1142 1142
                 ),
1143 1143
                 // options
1144 1144
                 array(
@@ -1166,7 +1166,7 @@  discard block
 block discarded – undo
1166 1166
     public static function register_message_types()
1167 1167
     {
1168 1168
         foreach (self::$_settings as $settings) {
1169
-            if (! empty($settings['message_types'])) {
1169
+            if ( ! empty($settings['message_types'])) {
1170 1170
                 foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1171 1171
                     EE_Register_Message_Type::register($message_type, $message_type_settings);
1172 1172
                 }
@@ -1187,74 +1187,74 @@  discard block
 block discarded – undo
1187 1187
      */
1188 1188
     public static function deregister($addon_name = '')
1189 1189
     {
1190
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1190
+        if (isset(self::$_settings[$addon_name]['class_name'])) {
1191 1191
             try {
1192 1192
                 do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1193
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1194
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1193
+                $class_name = self::$_settings[$addon_name]['class_name'];
1194
+                if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
1195 1195
                     // setup DMS
1196 1196
                     EE_Register_Data_Migration_Scripts::deregister($addon_name);
1197 1197
                 }
1198
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1198
+                if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
1199 1199
                     // register admin page
1200 1200
                     EE_Register_Admin_Page::deregister($addon_name);
1201 1201
                 }
1202
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1202
+                if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
1203 1203
                     // add to list of modules to be registered
1204 1204
                     EE_Register_Module::deregister($addon_name);
1205 1205
                 }
1206 1206
                 if (
1207
-                    ! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1208
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1207
+                    ! empty(self::$_settings[$addon_name]['shortcode_paths'])
1208
+                    || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
1209 1209
                 ) {
1210 1210
                     // add to list of shortcodes to be registered
1211 1211
                     EE_Register_Shortcode::deregister($addon_name);
1212 1212
                 }
1213
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1213
+                if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
1214 1214
                     // if config_class present let's register config.
1215
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1215
+                    EE_Register_Config::deregister(self::$_settings[$addon_name]['config_class']);
1216 1216
                 }
1217
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1217
+                if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
1218 1218
                     // add to list of widgets to be registered
1219 1219
                     EE_Register_Widget::deregister($addon_name);
1220 1220
                 }
1221 1221
                 if (
1222
-                    ! empty(self::$_settings[ $addon_name ]['model_paths'])
1223
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1222
+                    ! empty(self::$_settings[$addon_name]['model_paths'])
1223
+                    || ! empty(self::$_settings[$addon_name]['class_paths'])
1224 1224
                 ) {
1225 1225
                     // add to list of shortcodes to be registered
1226 1226
                     EE_Register_Model::deregister($addon_name);
1227 1227
                 }
1228 1228
                 if (
1229
-                    ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1230
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1229
+                    ! empty(self::$_settings[$addon_name]['model_extension_paths'])
1230
+                    || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
1231 1231
                 ) {
1232 1232
                     // add to list of shortcodes to be registered
1233 1233
                     EE_Register_Model_Extensions::deregister($addon_name);
1234 1234
                 }
1235
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1236
-                    foreach ((array) self::$_settings[ $addon_name ]['message_types'] as $message_type => $message_type_settings) {
1235
+                if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
1236
+                    foreach ((array) self::$_settings[$addon_name]['message_types'] as $message_type => $message_type_settings) {
1237 1237
                         EE_Register_Message_Type::deregister($message_type);
1238 1238
                     }
1239 1239
                 }
1240 1240
                 // deregister capabilities for addon
1241 1241
                 if (
1242
-                    ! empty(self::$_settings[ $addon_name ]['capabilities'])
1243
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1242
+                    ! empty(self::$_settings[$addon_name]['capabilities'])
1243
+                    || ! empty(self::$_settings[$addon_name]['capability_maps'])
1244 1244
                 ) {
1245 1245
                     EE_Register_Capabilities::deregister($addon_name);
1246 1246
                 }
1247 1247
                 // deregister custom_post_types for addon
1248
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1248
+                if ( ! empty(self::$_settings[$addon_name]['custom_post_types'])) {
1249 1249
                     EE_Register_CPT::deregister($addon_name);
1250 1250
                 }
1251
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1251
+                if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
1252 1252
                     EE_Register_Payment_Method::deregister($addon_name);
1253 1253
                 }
1254 1254
                 $addon = EE_Registry::instance()->getAddon($class_name);
1255 1255
                 if ($addon instanceof EE_Addon) {
1256 1256
                     remove_action(
1257
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1257
+                        'deactivate_'.$addon->get_main_plugin_file_basename(),
1258 1258
                         array($addon, 'deactivation')
1259 1259
                     );
1260 1260
                     remove_action(
@@ -1278,7 +1278,7 @@  discard block
 block discarded – undo
1278 1278
             } catch (Exception $e) {
1279 1279
                 new ExceptionLogger($e);
1280 1280
             }
1281
-            unset(self::$_settings[ $addon_name ]);
1281
+            unset(self::$_settings[$addon_name]);
1282 1282
             do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1283 1283
         }
1284 1284
     }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4104 added lines, -4104 removed lines patch added patch discarded remove patch
@@ -18,4180 +18,4180 @@
 block discarded – undo
18 18
  */
19 19
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
20 20
 {
21
-    /**
22
-     * @var LoaderInterface
23
-     */
24
-    protected $loader;
21
+	/**
22
+	 * @var LoaderInterface
23
+	 */
24
+	protected $loader;
25 25
 
26
-    /**
27
-     * @var RequestInterface
28
-     */
29
-    protected $request;
26
+	/**
27
+	 * @var RequestInterface
28
+	 */
29
+	protected $request;
30 30
 
31
-    // set in _init_page_props()
32
-    public $page_slug;
31
+	// set in _init_page_props()
32
+	public $page_slug;
33 33
 
34
-    public $page_label;
34
+	public $page_label;
35 35
 
36
-    public $page_folder;
36
+	public $page_folder;
37 37
 
38
-    // set in define_page_props()
39
-    protected $_admin_base_url;
38
+	// set in define_page_props()
39
+	protected $_admin_base_url;
40 40
 
41
-    protected $_admin_base_path;
41
+	protected $_admin_base_path;
42 42
 
43
-    protected $_admin_page_title;
43
+	protected $_admin_page_title;
44 44
 
45
-    protected $_labels;
45
+	protected $_labels;
46 46
 
47 47
 
48
-    // set early within EE_Admin_Init
49
-    protected $_wp_page_slug;
48
+	// set early within EE_Admin_Init
49
+	protected $_wp_page_slug;
50 50
 
51
-    // navtabs
52
-    protected $_nav_tabs;
51
+	// navtabs
52
+	protected $_nav_tabs;
53 53
 
54
-    protected $_default_nav_tab_name;
54
+	protected $_default_nav_tab_name;
55 55
 
56 56
 
57
-    // template variables (used by templates)
58
-    protected $_template_path;
57
+	// template variables (used by templates)
58
+	protected $_template_path;
59 59
 
60
-    protected $_column_template_path;
60
+	protected $_column_template_path;
61 61
 
62
-    /**
63
-     * @var array $_template_args
64
-     */
65
-    protected $_template_args = [];
62
+	/**
63
+	 * @var array $_template_args
64
+	 */
65
+	protected $_template_args = [];
66 66
 
67
-    /**
68
-     * this will hold the list table object for a given view.
69
-     *
70
-     * @var EE_Admin_List_Table $_list_table_object
71
-     */
72
-    protected $_list_table_object;
67
+	/**
68
+	 * this will hold the list table object for a given view.
69
+	 *
70
+	 * @var EE_Admin_List_Table $_list_table_object
71
+	 */
72
+	protected $_list_table_object;
73 73
 
74
-    // bools
75
-    protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
74
+	// bools
75
+	protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
76 76
 
77
-    protected $_routing;
77
+	protected $_routing;
78 78
 
79
-    // list table args
80
-    protected $_view;
79
+	// list table args
80
+	protected $_view;
81 81
 
82
-    protected $_views;
82
+	protected $_views;
83 83
 
84 84
 
85
-    // action => method pairs used for routing incoming requests
86
-    protected $_page_routes;
85
+	// action => method pairs used for routing incoming requests
86
+	protected $_page_routes;
87 87
 
88
-    /**
89
-     * @var array $_page_config
90
-     */
91
-    protected $_page_config;
88
+	/**
89
+	 * @var array $_page_config
90
+	 */
91
+	protected $_page_config;
92 92
 
93
-    /**
94
-     * the current page route and route config
95
-     *
96
-     * @var string $_route
97
-     */
98
-    protected $_route;
93
+	/**
94
+	 * the current page route and route config
95
+	 *
96
+	 * @var string $_route
97
+	 */
98
+	protected $_route;
99 99
 
100
-    /**
101
-     * @var string $_cpt_route
102
-     */
103
-    protected $_cpt_route;
100
+	/**
101
+	 * @var string $_cpt_route
102
+	 */
103
+	protected $_cpt_route;
104 104
 
105
-    /**
106
-     * @var array $_route_config
107
-     */
108
-    protected $_route_config;
105
+	/**
106
+	 * @var array $_route_config
107
+	 */
108
+	protected $_route_config;
109 109
 
110
-    /**
111
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
112
-     * actions.
113
-     *
114
-     * @since 4.6.x
115
-     * @var array.
116
-     */
117
-    protected $_default_route_query_args;
118
-
119
-    // set via request page and action args.
120
-    protected $_current_page;
121
-
122
-    protected $_current_view;
123
-
124
-    protected $_current_page_view_url;
125
-
126
-    /**
127
-     * unprocessed value for the 'action' request param (default '')
128
-     *
129
-     * @var string
130
-     */
131
-    protected $raw_req_action = '';
132
-
133
-    /**
134
-     * unprocessed value for the 'page' request param (default '')
135
-     *
136
-     * @var string
137
-     */
138
-    protected $raw_req_page = '';
139
-
140
-    /**
141
-     * sanitized request action (and nonce)
142
-     *
143
-     * @var string
144
-     */
145
-    protected $_req_action = '';
146
-
147
-    /**
148
-     * sanitized request action nonce
149
-     *
150
-     * @var string
151
-     */
152
-    protected $_req_nonce = '';
153
-
154
-    /**
155
-     * @var string
156
-     */
157
-    protected $_search_btn_label = '';
158
-
159
-    /**
160
-     * @var string
161
-     */
162
-    protected $_search_box_callback = '';
163
-
164
-    /**
165
-     * @var WP_Screen
166
-     */
167
-    protected $_current_screen;
168
-
169
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
170
-    protected $_hook_obj;
171
-
172
-    // for holding incoming request data
173
-    protected $_req_data = [];
174
-
175
-    // yes / no array for admin form fields
176
-    protected $_yes_no_values = [];
177
-
178
-    // some default things shared by all child classes
179
-    protected $_default_espresso_metaboxes;
180
-
181
-    /**
182
-     * @var EE_Registry
183
-     */
184
-    protected $EE = null;
185
-
186
-
187
-    /**
188
-     * This is just a property that flags whether the given route is a caffeinated route or not.
189
-     *
190
-     * @var boolean
191
-     */
192
-    protected $_is_caf = false;
193
-
194
-
195
-    /**
196
-     * @Constructor
197
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
198
-     * @throws EE_Error
199
-     * @throws InvalidArgumentException
200
-     * @throws ReflectionException
201
-     * @throws InvalidDataTypeException
202
-     * @throws InvalidInterfaceException
203
-     */
204
-    public function __construct($routing = true)
205
-    {
206
-        $this->loader  = LoaderFactory::getLoader();
207
-        $this->request = $this->loader->getShared(RequestInterface::class);
208
-        $this->_routing = $routing;
209
-
210
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
211
-            $this->_is_caf = true;
212
-        }
213
-        $this->_yes_no_values = [
214
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
215
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
216
-        ];
217
-        // set the _req_data property.
218
-        $this->_req_data = $this->request->requestParams();
219
-        // set initial page props (child method)
220
-        $this->_init_page_props();
221
-        // set global defaults
222
-        $this->_set_defaults();
223
-        // set early because incoming requests could be ajax related and we need to register those hooks.
224
-        $this->_global_ajax_hooks();
225
-        $this->_ajax_hooks();
226
-        // other_page_hooks have to be early too.
227
-        $this->_do_other_page_hooks();
228
-        // set up page dependencies
229
-        $this->_before_page_setup();
230
-        $this->_page_setup();
231
-        // die();
232
-    }
233
-
234
-
235
-    /**
236
-     * _init_page_props
237
-     * Child classes use to set at least the following properties:
238
-     * $page_slug.
239
-     * $page_label.
240
-     *
241
-     * @abstract
242
-     * @return void
243
-     */
244
-    abstract protected function _init_page_props();
245
-
246
-
247
-    /**
248
-     * _ajax_hooks
249
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
250
-     * Note: within the ajax callback methods.
251
-     *
252
-     * @abstract
253
-     * @return void
254
-     */
255
-    abstract protected function _ajax_hooks();
256
-
257
-
258
-    /**
259
-     * _define_page_props
260
-     * child classes define page properties in here.  Must include at least:
261
-     * $_admin_base_url = base_url for all admin pages
262
-     * $_admin_page_title = default admin_page_title for admin pages
263
-     * $_labels = array of default labels for various automatically generated elements:
264
-     *    array(
265
-     *        'buttons' => array(
266
-     *            'add' => esc_html__('label for add new button'),
267
-     *            'edit' => esc_html__('label for edit button'),
268
-     *            'delete' => esc_html__('label for delete button')
269
-     *            )
270
-     *        )
271
-     *
272
-     * @abstract
273
-     * @return void
274
-     */
275
-    abstract protected function _define_page_props();
276
-
277
-
278
-    /**
279
-     * _set_page_routes
280
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
281
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
282
-     * have a 'default' route. Here's the format
283
-     * $this->_page_routes = array(
284
-     *        'default' => array(
285
-     *            'func' => '_default_method_handling_route',
286
-     *            'args' => array('array','of','args'),
287
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
288
-     *            ajax request, backend processing)
289
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
290
-     *            headers route after.  The string you enter here should match the defined route reference for a
291
-     *            headers sent route.
292
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
293
-     *            this route.
294
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
295
-     *            checks).
296
-     *        ),
297
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
298
-     *        handling method.
299
-     *        )
300
-     * )
301
-     *
302
-     * @abstract
303
-     * @return void
304
-     */
305
-    abstract protected function _set_page_routes();
306
-
307
-
308
-    /**
309
-     * _set_page_config
310
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
311
-     * array corresponds to the page_route for the loaded page. Format:
312
-     * $this->_page_config = array(
313
-     *        'default' => array(
314
-     *            'labels' => array(
315
-     *                'buttons' => array(
316
-     *                    'add' => esc_html__('label for adding item'),
317
-     *                    'edit' => esc_html__('label for editing item'),
318
-     *                    'delete' => esc_html__('label for deleting item')
319
-     *                ),
320
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
321
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
322
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
323
-     *            _define_page_props() method
324
-     *            'nav' => array(
325
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
326
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
327
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
328
-     *                'order' => 10, //required to indicate tab position.
329
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
330
-     *                displayed then add this parameter.
331
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
332
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
333
-     *            metaboxes set for eventespresso admin pages.
334
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
335
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
336
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
337
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
338
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
339
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
340
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
341
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
342
-     *            want to display.
343
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
344
-     *                'tab_id' => array(
345
-     *                    'title' => 'tab_title',
346
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
347
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
348
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
349
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
350
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
351
-     *                    attempt to use the callback which should match the name of a method in the class
352
-     *                    ),
353
-     *                'tab2_id' => array(
354
-     *                    'title' => 'tab2 title',
355
-     *                    'filename' => 'file_name_2'
356
-     *                    'callback' => 'callback_method_for_content',
357
-     *                 ),
358
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
359
-     *            help tab area on an admin page. @return void
360
-     *
361
-     * @abstract
362
-     */
363
-    abstract protected function _set_page_config();
364
-
365
-
366
-    /**
367
-     * _add_screen_options
368
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
369
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
370
-     * to a particular view.
371
-     *
372
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
373
-     *         see also WP_Screen object documents...
374
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
375
-     * @abstract
376
-     * @return void
377
-     */
378
-    abstract protected function _add_screen_options();
379
-
380
-
381
-    /**
382
-     * _add_feature_pointers
383
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
384
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
385
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
386
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
387
-     * extended) also see:
388
-     *
389
-     * @link   http://eamann.com/tech/wordpress-portland/
390
-     * @abstract
391
-     * @return void
392
-     */
393
-    abstract protected function _add_feature_pointers();
394
-
395
-
396
-    /**
397
-     * load_scripts_styles
398
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
399
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
400
-     * scripts/styles per view by putting them in a dynamic function in this format
401
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
402
-     *
403
-     * @abstract
404
-     * @return void
405
-     */
406
-    abstract public function load_scripts_styles();
407
-
408
-
409
-    /**
410
-     * admin_init
411
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
412
-     * all pages/views loaded by child class.
413
-     *
414
-     * @abstract
415
-     * @return void
416
-     */
417
-    abstract public function admin_init();
418
-
419
-
420
-    /**
421
-     * admin_notices
422
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
423
-     * all pages/views loaded by child class.
424
-     *
425
-     * @abstract
426
-     * @return void
427
-     */
428
-    abstract public function admin_notices();
429
-
430
-
431
-    /**
432
-     * admin_footer_scripts
433
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
434
-     * will apply to all pages/views loaded by child class.
435
-     *
436
-     * @return void
437
-     */
438
-    abstract public function admin_footer_scripts();
439
-
440
-
441
-    /**
442
-     * admin_footer
443
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
444
-     * apply to all pages/views loaded by child class.
445
-     *
446
-     * @return void
447
-     */
448
-    public function admin_footer()
449
-    {
450
-    }
451
-
452
-
453
-    /**
454
-     * _global_ajax_hooks
455
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
456
-     * Note: within the ajax callback methods.
457
-     *
458
-     * @abstract
459
-     * @return void
460
-     */
461
-    protected function _global_ajax_hooks()
462
-    {
463
-        // for lazy loading of metabox content
464
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
465
-    }
466
-
467
-
468
-    public function ajax_metabox_content()
469
-    {
470
-        $content_id  = $this->request->getRequestParam('contentid', '');
471
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
472
-        self::cached_rss_display($content_id, $content_url);
473
-        wp_die();
474
-    }
475
-
476
-
477
-    /**
478
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
479
-     *
480
-     * @return void
481
-     */
482
-    protected function _before_page_setup()
483
-    {
484
-        // default is to do nothing
485
-    }
486
-
487
-
488
-    /**
489
-     * Makes sure any things that need to be loaded early get handled.
490
-     * We also escape early here if the page requested doesn't match the object.
491
-     *
492
-     * @final
493
-     * @return void
494
-     * @throws EE_Error
495
-     * @throws InvalidArgumentException
496
-     * @throws ReflectionException
497
-     * @throws InvalidDataTypeException
498
-     * @throws InvalidInterfaceException
499
-     */
500
-    final protected function _page_setup()
501
-    {
502
-        // requires?
503
-        // admin_init stuff - global - we're setting this REALLY early
504
-        // so if EE_Admin pages have to hook into other WP pages they can.
505
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
506
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
507
-        // next verify if we need to load anything...
508
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
509
-        $this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, 'key');
510
-
511
-        $this->page_folder   = strtolower(
512
-            str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
513
-        );
514
-        global $ee_menu_slugs;
515
-        $ee_menu_slugs = (array) $ee_menu_slugs;
516
-        if (
517
-            ! $this->request->isAjax()
518
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
519
-        ) {
520
-            return;
521
-        }
522
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
523
-        // we need to copy the action from the second to the first
524
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
525
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
526
-        $action     = $action !== '-1' ? $action : $action2;
527
-        $req_action = $action !== '-1' ? $action : 'default';
528
-
529
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
530
-        // then let's use the route as the action.
531
-        // This covers cases where we're coming in from a list table that isn't on the default route.
532
-        $route = $this->request->getRequestParam('route');
533
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
534
-            ? $route
535
-            : $req_action;
536
-
537
-        $this->_current_view = $this->_req_action;
538
-        $this->_req_nonce    = $this->_req_action . '_nonce';
539
-        $this->_define_page_props();
540
-        $this->_current_page_view_url = add_query_arg(
541
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
542
-            $this->_admin_base_url
543
-        );
544
-        // default things
545
-        $this->_default_espresso_metaboxes = [
546
-            '_espresso_news_post_box',
547
-            '_espresso_links_post_box',
548
-            '_espresso_ratings_request',
549
-            '_espresso_sponsors_post_box',
550
-        ];
551
-        // set page configs
552
-        $this->_set_page_routes();
553
-        $this->_set_page_config();
554
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
555
-        if ($this->request->requestParamIsSet('wp_referer')) {
556
-            $wp_referer = $this->request->getRequestParam('wp_referer');
557
-            if ($wp_referer) {
558
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
559
-            }
560
-        }
561
-        // for caffeinated and other extended functionality.
562
-        //  If there is a _extend_page_config method
563
-        // then let's run that to modify the all the various page configuration arrays
564
-        if (method_exists($this, '_extend_page_config')) {
565
-            $this->_extend_page_config();
566
-        }
567
-        // for CPT and other extended functionality.
568
-        // If there is an _extend_page_config_for_cpt
569
-        // then let's run that to modify all the various page configuration arrays.
570
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
571
-            $this->_extend_page_config_for_cpt();
572
-        }
573
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
574
-        $this->_page_routes = apply_filters(
575
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
-            $this->_page_routes,
577
-            $this
578
-        );
579
-        $this->_page_config = apply_filters(
580
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
581
-            $this->_page_config,
582
-            $this
583
-        );
584
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
587
-            add_action(
588
-                'AHEE__EE_Admin_Page__route_admin_request',
589
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
590
-                10,
591
-                2
592
-            );
593
-        }
594
-        // next route only if routing enabled
595
-        if ($this->_routing && ! $this->request->isAjax()) {
596
-            $this->_verify_routes();
597
-            // next let's just check user_access and kill if no access
598
-            $this->check_user_access();
599
-            if ($this->_is_UI_request) {
600
-                // admin_init stuff - global, all views for this page class, specific view
601
-                add_action('admin_init', [$this, 'admin_init'], 10);
602
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
603
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
604
-                }
605
-            } else {
606
-                // hijack regular WP loading and route admin request immediately
607
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
608
-                $this->route_admin_request();
609
-            }
610
-        }
611
-    }
612
-
613
-
614
-    /**
615
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
616
-     *
617
-     * @return void
618
-     * @throws EE_Error
619
-     */
620
-    private function _do_other_page_hooks()
621
-    {
622
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
623
-        foreach ($registered_pages as $page) {
624
-            // now let's setup the file name and class that should be present
625
-            $classname = str_replace('.class.php', '', $page);
626
-            // autoloaders should take care of loading file
627
-            if (! class_exists($classname)) {
628
-                $error_msg[] = sprintf(
629
-                    esc_html__(
630
-                        'Something went wrong with loading the %s admin hooks page.',
631
-                        'event_espresso'
632
-                    ),
633
-                    $page
634
-                );
635
-                $error_msg[] = $error_msg[0]
636
-                               . "\r\n"
637
-                               . sprintf(
638
-                                   esc_html__(
639
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
640
-                                       'event_espresso'
641
-                                   ),
642
-                                   $page,
643
-                                   '<br />',
644
-                                   '<strong>' . $classname . '</strong>'
645
-                               );
646
-                throw new EE_Error(implode('||', $error_msg));
647
-            }
648
-            // notice we are passing the instance of this class to the hook object.
649
-            $this->loader->getShared($classname, [$this]);
650
-        }
651
-    }
652
-
653
-
654
-    /**
655
-     * @throws ReflectionException
656
-     * @throws EE_Error
657
-     */
658
-    public function load_page_dependencies()
659
-    {
660
-        try {
661
-            $this->_load_page_dependencies();
662
-        } catch (EE_Error $e) {
663
-            $e->get_error();
664
-        }
665
-    }
666
-
667
-
668
-    /**
669
-     * load_page_dependencies
670
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
671
-     *
672
-     * @return void
673
-     * @throws DomainException
674
-     * @throws EE_Error
675
-     * @throws InvalidArgumentException
676
-     * @throws InvalidDataTypeException
677
-     * @throws InvalidInterfaceException
678
-     */
679
-    protected function _load_page_dependencies()
680
-    {
681
-        // let's set the current_screen and screen options to override what WP set
682
-        $this->_current_screen = get_current_screen();
683
-        // load admin_notices - global, page class, and view specific
684
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
685
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
686
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
687
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
688
-        }
689
-        // load network admin_notices - global, page class, and view specific
690
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
691
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
692
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
693
-        }
694
-        // this will save any per_page screen options if they are present
695
-        $this->_set_per_page_screen_options();
696
-        // setup list table properties
697
-        $this->_set_list_table();
698
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
699
-        // However in some cases the metaboxes will need to be added within a route handling callback.
700
-        $this->_add_registered_meta_boxes();
701
-        $this->_add_screen_columns();
702
-        // add screen options - global, page child class, and view specific
703
-        $this->_add_global_screen_options();
704
-        $this->_add_screen_options();
705
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
706
-        if (method_exists($this, $add_screen_options)) {
707
-            $this->{$add_screen_options}();
708
-        }
709
-        // add help tab(s) - set via page_config and qtips.
710
-        $this->_add_help_tabs();
711
-        $this->_add_qtips();
712
-        // add feature_pointers - global, page child class, and view specific
713
-        $this->_add_feature_pointers();
714
-        $this->_add_global_feature_pointers();
715
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
716
-        if (method_exists($this, $add_feature_pointer)) {
717
-            $this->{$add_feature_pointer}();
718
-        }
719
-        // enqueue scripts/styles - global, page class, and view specific
720
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
721
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
722
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
723
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
724
-        }
725
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
726
-        // admin_print_footer_scripts - global, page child class, and view specific.
727
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
728
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
729
-        // is a good use case. Notice the late priority we're giving these
730
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
731
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
732
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
733
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
734
-        }
735
-        // admin footer scripts
736
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
737
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
738
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
739
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
740
-        }
741
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
742
-        // targeted hook
743
-        do_action(
744
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
745
-        );
746
-    }
747
-
748
-
749
-    /**
750
-     * _set_defaults
751
-     * This sets some global defaults for class properties.
752
-     */
753
-    private function _set_defaults()
754
-    {
755
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
756
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
757
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
758
-        $this->_page_config          = $this->_default_route_query_args = [];
759
-        $this->_default_nav_tab_name = 'overview';
760
-        // init template args
761
-        $this->_template_args = [
762
-            'admin_page_header'  => '',
763
-            'admin_page_content' => '',
764
-            'post_body_content'  => '',
765
-            'before_list_table'  => '',
766
-            'after_list_table'   => '',
767
-        ];
768
-    }
769
-
770
-
771
-    /**
772
-     * route_admin_request
773
-     *
774
-     * @return void
775
-     * @throws InvalidArgumentException
776
-     * @throws InvalidInterfaceException
777
-     * @throws InvalidDataTypeException
778
-     * @throws EE_Error
779
-     * @throws ReflectionException
780
-     * @see    _route_admin_request()
781
-     */
782
-    public function route_admin_request()
783
-    {
784
-        try {
785
-            $this->_route_admin_request();
786
-        } catch (EE_Error $e) {
787
-            $e->get_error();
788
-        }
789
-    }
790
-
791
-
792
-    public function set_wp_page_slug($wp_page_slug)
793
-    {
794
-        $this->_wp_page_slug = $wp_page_slug;
795
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
796
-        if (is_network_admin()) {
797
-            $this->_wp_page_slug .= '-network';
798
-        }
799
-    }
800
-
801
-
802
-    /**
803
-     * _verify_routes
804
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
805
-     * we know if we need to drop out.
806
-     *
807
-     * @return bool
808
-     * @throws EE_Error
809
-     */
810
-    protected function _verify_routes()
811
-    {
812
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
813
-        if (! $this->_current_page && ! $this->request->isAjax()) {
814
-            return false;
815
-        }
816
-        $this->_route = false;
817
-        // check that the page_routes array is not empty
818
-        if (empty($this->_page_routes)) {
819
-            // user error msg
820
-            $error_msg = sprintf(
821
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
822
-                $this->_admin_page_title
823
-            );
824
-            // developer error msg
825
-            $error_msg .= '||' . $error_msg
826
-                          . esc_html__(
827
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
828
-                              'event_espresso'
829
-                          );
830
-            throw new EE_Error($error_msg);
831
-        }
832
-        // and that the requested page route exists
833
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
834
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
835
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
836
-                ? $this->_page_config[ $this->_req_action ]
837
-                : [];
838
-        } else {
839
-            // user error msg
840
-            $error_msg = sprintf(
841
-                esc_html__(
842
-                    'The requested page route does not exist for the %s admin page.',
843
-                    'event_espresso'
844
-                ),
845
-                $this->_admin_page_title
846
-            );
847
-            // developer error msg
848
-            $error_msg .= '||' . $error_msg
849
-                          . sprintf(
850
-                              esc_html__(
851
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
852
-                                  'event_espresso'
853
-                              ),
854
-                              $this->_req_action
855
-                          );
856
-            throw new EE_Error($error_msg);
857
-        }
858
-        // and that a default route exists
859
-        if (! array_key_exists('default', $this->_page_routes)) {
860
-            // user error msg
861
-            $error_msg = sprintf(
862
-                esc_html__(
863
-                    'A default page route has not been set for the % admin page.',
864
-                    'event_espresso'
865
-                ),
866
-                $this->_admin_page_title
867
-            );
868
-            // developer error msg
869
-            $error_msg .= '||' . $error_msg
870
-                          . esc_html__(
871
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
872
-                              'event_espresso'
873
-                          );
874
-            throw new EE_Error($error_msg);
875
-        }
876
-        // first lets' catch if the UI request has EVER been set.
877
-        if ($this->_is_UI_request === null) {
878
-            // lets set if this is a UI request or not.
879
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
880
-            // wait a minute... we might have a noheader in the route array
881
-            $this->_is_UI_request = ! (
882
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
883
-            )
884
-                ? $this->_is_UI_request
885
-                : false;
886
-        }
887
-        $this->_set_current_labels();
888
-        return true;
889
-    }
890
-
891
-
892
-    /**
893
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
894
-     *
895
-     * @param string $route the route name we're verifying
896
-     * @return bool we'll throw an exception if this isn't a valid route.
897
-     * @throws EE_Error
898
-     */
899
-    protected function _verify_route($route)
900
-    {
901
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
902
-            return true;
903
-        }
904
-        // user error msg
905
-        $error_msg = sprintf(
906
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
907
-            $this->_admin_page_title
908
-        );
909
-        // developer error msg
910
-        $error_msg .= '||' . $error_msg
911
-                      . sprintf(
912
-                          esc_html__(
913
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
914
-                              'event_espresso'
915
-                          ),
916
-                          $route
917
-                      );
918
-        throw new EE_Error($error_msg);
919
-    }
920
-
921
-
922
-    /**
923
-     * perform nonce verification
924
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
925
-     * using this method (and save retyping!)
926
-     *
927
-     * @param string $nonce     The nonce sent
928
-     * @param string $nonce_ref The nonce reference string (name0)
929
-     * @return void
930
-     * @throws EE_Error
931
-     */
932
-    protected function _verify_nonce($nonce, $nonce_ref)
933
-    {
934
-        // verify nonce against expected value
935
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
936
-            // these are not the droids you are looking for !!!
937
-            $msg = sprintf(
938
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
939
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
940
-                '</a>'
941
-            );
942
-            if (WP_DEBUG) {
943
-                $msg .= "\n  ";
944
-                $msg .= sprintf(
945
-                    esc_html__(
946
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
947
-                        'event_espresso'
948
-                    ),
949
-                    __CLASS__
950
-                );
951
-            }
952
-            if (! $this->request->isAjax()) {
953
-                wp_die($msg);
954
-            }
955
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
956
-            $this->_return_json();
957
-        }
958
-    }
959
-
960
-
961
-    /**
962
-     * _route_admin_request()
963
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
964
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
965
-     * in the page routes and then will try to load the corresponding method.
966
-     *
967
-     * @return void
968
-     * @throws EE_Error
969
-     * @throws InvalidArgumentException
970
-     * @throws InvalidDataTypeException
971
-     * @throws InvalidInterfaceException
972
-     * @throws ReflectionException
973
-     */
974
-    protected function _route_admin_request()
975
-    {
976
-        if (! $this->_is_UI_request) {
977
-            $this->_verify_routes();
978
-        }
979
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
980
-        if ($this->_req_action !== 'default' && $nonce_check) {
981
-            // set nonce from post data
982
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
983
-            $this->_verify_nonce($nonce, $this->_req_nonce);
984
-        }
985
-        // set the nav_tabs array but ONLY if this is  UI_request
986
-        if ($this->_is_UI_request) {
987
-            $this->_set_nav_tabs();
988
-        }
989
-        // grab callback function
990
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
991
-        // check if callback has args
992
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
993
-        $error_msg = '';
994
-        // action right before calling route
995
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
996
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
997
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
998
-        }
999
-        // right before calling the route, let's clean the _wp_http_referer
1000
-        $this->request->unSetRequestParam('_wp_http_referer');
1001
-        $this->request->unSetServerParam('_wp_http_referer');
1002
-        $cleaner_request_uri = remove_query_arg(
1003
-            '_wp_http_referer',
1004
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1005
-        );
1006
-        $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri);
1007
-        $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri);
1008
-        if (! empty($func)) {
1009
-            if (is_array($func)) {
1010
-                [$class, $method] = $func;
1011
-            } elseif (strpos($func, '::') !== false) {
1012
-                [$class, $method] = explode('::', $func);
1013
-            } else {
1014
-                $class  = $this;
1015
-                $method = $func;
1016
-            }
1017
-            if (! (is_object($class) && $class === $this) && ! in_array($this, $args)) {
1018
-                // send along this admin page object for access by addons.
1019
-                $args['admin_page'] = $this;
1020
-            }
1021
-            if (
1022
-                // is it a method on a class that doesn't work?
1023
-                (
1024
-                    (
1025
-                        method_exists($class, $method)
1026
-                        && call_user_func_array([$class, $method], $args) === false
1027
-                    )
1028
-                    && (
1029
-                        // is it a standalone function that doesn't work?
1030
-                        function_exists($method)
1031
-                        && call_user_func_array(
1032
-                            $func,
1033
-                            array_merge(['admin_page' => $this], $args)
1034
-                        ) === false
1035
-                    )
1036
-                )
1037
-                || (
1038
-                    // is it neither a class method NOR a standalone function?
1039
-                    ! method_exists($class, $method)
1040
-                    && ! function_exists($method)
1041
-                )
1042
-            ) {
1043
-                // user error msg
1044
-                $error_msg = esc_html__(
1045
-                    'An error occurred. The  requested page route could not be found.',
1046
-                    'event_espresso'
1047
-                );
1048
-                // developer error msg
1049
-                $error_msg .= '||';
1050
-                $error_msg .= sprintf(
1051
-                    esc_html__(
1052
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1053
-                        'event_espresso'
1054
-                    ),
1055
-                    $method
1056
-                );
1057
-            }
1058
-            if (! empty($error_msg)) {
1059
-                throw new EE_Error($error_msg);
1060
-            }
1061
-        }
1062
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1063
-        // then we need to reset the routing properties to the new route.
1064
-        // now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1065
-        if (
1066
-            $this->_is_UI_request === false
1067
-            && is_array($this->_route)
1068
-            && ! empty($this->_route['headers_sent_route'])
1069
-        ) {
1070
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1071
-        }
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * This method just allows the resetting of page properties in the case where a no headers
1077
-     * route redirects to a headers route in its route config.
1078
-     *
1079
-     * @param string $new_route New (non header) route to redirect to.
1080
-     * @return   void
1081
-     * @throws ReflectionException
1082
-     * @throws InvalidArgumentException
1083
-     * @throws InvalidInterfaceException
1084
-     * @throws InvalidDataTypeException
1085
-     * @throws EE_Error
1086
-     * @since   4.3.0
1087
-     */
1088
-    protected function _reset_routing_properties($new_route)
1089
-    {
1090
-        $this->_is_UI_request = true;
1091
-        // now we set the current route to whatever the headers_sent_route is set at
1092
-        $this->request->setRequestParam('action', $new_route);
1093
-        // rerun page setup
1094
-        $this->_page_setup();
1095
-    }
1096
-
1097
-
1098
-    /**
1099
-     * _add_query_arg
1100
-     * adds nonce to array of arguments then calls WP add_query_arg function
1101
-     *(internally just uses EEH_URL's function with the same name)
1102
-     *
1103
-     * @param array  $args
1104
-     * @param string $url
1105
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1106
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1107
-     *                                        Example usage: If the current page is:
1108
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1109
-     *                                        &action=default&event_id=20&month_range=March%202015
1110
-     *                                        &_wpnonce=5467821
1111
-     *                                        and you call:
1112
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1113
-     *                                        array(
1114
-     *                                        'action' => 'resend_something',
1115
-     *                                        'page=>espresso_registrations'
1116
-     *                                        ),
1117
-     *                                        $some_url,
1118
-     *                                        true
1119
-     *                                        );
1120
-     *                                        It will produce a url in this structure:
1121
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1122
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1123
-     *                                        month_range]=March%202015
1124
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1125
-     * @return string
1126
-     */
1127
-    public static function add_query_args_and_nonce(
1128
-        $args = [],
1129
-        $url = false,
1130
-        $sticky = false,
1131
-        $exclude_nonce = false
1132
-    ) {
1133
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1134
-        if ($sticky) {
1135
-            /** @var RequestInterface $request */
1136
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1137
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1138
-            foreach ($request->requestParams() as $key => $value) {
1139
-                // do not add nonces
1140
-                if (strpos($key, 'nonce') !== false) {
1141
-                    continue;
1142
-                }
1143
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1144
-            }
1145
-        }
1146
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * This returns a generated link that will load the related help tab.
1152
-     *
1153
-     * @param string $help_tab_id the id for the connected help tab
1154
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1155
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1156
-     * @return string              generated link
1157
-     * @uses EEH_Template::get_help_tab_link()
1158
-     */
1159
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1160
-    {
1161
-        return EEH_Template::get_help_tab_link(
1162
-            $help_tab_id,
1163
-            $this->page_slug,
1164
-            $this->_req_action,
1165
-            $icon_style,
1166
-            $help_text
1167
-        );
1168
-    }
1169
-
1170
-
1171
-    /**
1172
-     * _add_help_tabs
1173
-     * Note child classes define their help tabs within the page_config array.
1174
-     *
1175
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1176
-     * @return void
1177
-     * @throws DomainException
1178
-     * @throws EE_Error
1179
-     */
1180
-    protected function _add_help_tabs()
1181
-    {
1182
-        if (isset($this->_page_config[ $this->_req_action ])) {
1183
-            $config = $this->_page_config[ $this->_req_action ];
1184
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1185
-            if (is_array($config) && isset($config['help_sidebar'])) {
1186
-                // check that the callback given is valid
1187
-                if (! method_exists($this, $config['help_sidebar'])) {
1188
-                    throw new EE_Error(
1189
-                        sprintf(
1190
-                            esc_html__(
1191
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1192
-                                'event_espresso'
1193
-                            ),
1194
-                            $config['help_sidebar'],
1195
-                            get_class($this)
1196
-                        )
1197
-                    );
1198
-                }
1199
-                $content = apply_filters(
1200
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1201
-                    $this->{$config['help_sidebar']}()
1202
-                );
1203
-                $this->_current_screen->set_help_sidebar($content);
1204
-            }
1205
-            if (! isset($config['help_tabs'])) {
1206
-                return;
1207
-            } //no help tabs for this route
1208
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1209
-                // we're here so there ARE help tabs!
1210
-                // make sure we've got what we need
1211
-                if (! isset($cfg['title'])) {
1212
-                    throw new EE_Error(
1213
-                        esc_html__(
1214
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1215
-                            'event_espresso'
1216
-                        )
1217
-                    );
1218
-                }
1219
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1220
-                    throw new EE_Error(
1221
-                        esc_html__(
1222
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1223
-                            'event_espresso'
1224
-                        )
1225
-                    );
1226
-                }
1227
-                // first priority goes to content.
1228
-                if (! empty($cfg['content'])) {
1229
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1230
-                    // second priority goes to filename
1231
-                } elseif (! empty($cfg['filename'])) {
1232
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1233
-                    // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1234
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1235
-                                                             . basename($this->_get_dir())
1236
-                                                             . '/help_tabs/'
1237
-                                                             . $cfg['filename']
1238
-                                                             . '.help_tab.php' : $file_path;
1239
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1240
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1241
-                        EE_Error::add_error(
1242
-                            sprintf(
1243
-                                esc_html__(
1244
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1245
-                                    'event_espresso'
1246
-                                ),
1247
-                                $tab_id,
1248
-                                key($config),
1249
-                                $file_path
1250
-                            ),
1251
-                            __FILE__,
1252
-                            __FUNCTION__,
1253
-                            __LINE__
1254
-                        );
1255
-                        return;
1256
-                    }
1257
-                    $template_args['admin_page_obj'] = $this;
1258
-                    $content                         = EEH_Template::display_template(
1259
-                        $file_path,
1260
-                        $template_args,
1261
-                        true
1262
-                    );
1263
-                } else {
1264
-                    $content = '';
1265
-                }
1266
-                // check if callback is valid
1267
-                if (
1268
-                    empty($content)
1269
-                    && (
1270
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1271
-                    )
1272
-                ) {
1273
-                    EE_Error::add_error(
1274
-                        sprintf(
1275
-                            esc_html__(
1276
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1277
-                                'event_espresso'
1278
-                            ),
1279
-                            $cfg['title']
1280
-                        ),
1281
-                        __FILE__,
1282
-                        __FUNCTION__,
1283
-                        __LINE__
1284
-                    );
1285
-                    return;
1286
-                }
1287
-                // setup config array for help tab method
1288
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1289
-                $_ht = [
1290
-                    'id'       => $id,
1291
-                    'title'    => $cfg['title'],
1292
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1293
-                    'content'  => $content,
1294
-                ];
1295
-                $this->_current_screen->add_help_tab($_ht);
1296
-            }
1297
-        }
1298
-    }
1299
-
1300
-
1301
-    /**
1302
-     * This simply sets up any qtips that have been defined in the page config
1303
-     *
1304
-     * @return void
1305
-     */
1306
-    protected function _add_qtips()
1307
-    {
1308
-        if (isset($this->_route_config['qtips'])) {
1309
-            $qtips = (array) $this->_route_config['qtips'];
1310
-            // load qtip loader
1311
-            $path = [
1312
-                $this->_get_dir() . '/qtips/',
1313
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1314
-            ];
1315
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1316
-        }
1317
-    }
1318
-
1319
-
1320
-    /**
1321
-     * _set_nav_tabs
1322
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1323
-     * wish to add additional tabs or modify accordingly.
1324
-     *
1325
-     * @return void
1326
-     * @throws InvalidArgumentException
1327
-     * @throws InvalidInterfaceException
1328
-     * @throws InvalidDataTypeException
1329
-     */
1330
-    protected function _set_nav_tabs()
1331
-    {
1332
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1333
-        $i = 0;
1334
-        foreach ($this->_page_config as $slug => $config) {
1335
-            if (! is_array($config) || empty($config['nav'])) {
1336
-                continue;
1337
-            }
1338
-            // no nav tab for this config
1339
-            // check for persistent flag
1340
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1341
-                // nav tab is only to appear when route requested.
1342
-                continue;
1343
-            }
1344
-            if (! $this->check_user_access($slug, true)) {
1345
-                // no nav tab because current user does not have access.
1346
-                continue;
1347
-            }
1348
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1349
-            $this->_nav_tabs[ $slug ] = [
1350
-                'url'       => isset($config['nav']['url'])
1351
-                    ? $config['nav']['url']
1352
-                    : self::add_query_args_and_nonce(
1353
-                        ['action' => $slug],
1354
-                        $this->_admin_base_url
1355
-                    ),
1356
-                'link_text' => isset($config['nav']['label'])
1357
-                    ? $config['nav']['label']
1358
-                    : ucwords(
1359
-                        str_replace('_', ' ', $slug)
1360
-                    ),
1361
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1362
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1363
-            ];
1364
-            $i++;
1365
-        }
1366
-        // if $this->_nav_tabs is empty then lets set the default
1367
-        if (empty($this->_nav_tabs)) {
1368
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1369
-                'url'       => $this->_admin_base_url,
1370
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1371
-                'css_class' => 'nav-tab-active',
1372
-                'order'     => 10,
1373
-            ];
1374
-        }
1375
-        // now let's sort the tabs according to order
1376
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1377
-    }
1378
-
1379
-
1380
-    /**
1381
-     * _set_current_labels
1382
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1383
-     * property array
1384
-     *
1385
-     * @return void
1386
-     */
1387
-    private function _set_current_labels()
1388
-    {
1389
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1390
-            foreach ($this->_route_config['labels'] as $label => $text) {
1391
-                if (is_array($text)) {
1392
-                    foreach ($text as $sublabel => $subtext) {
1393
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1394
-                    }
1395
-                } else {
1396
-                    $this->_labels[ $label ] = $text;
1397
-                }
1398
-            }
1399
-        }
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     *        verifies user access for this admin page
1405
-     *
1406
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1407
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1408
-     *                               return false if verify fail.
1409
-     * @return bool
1410
-     * @throws InvalidArgumentException
1411
-     * @throws InvalidDataTypeException
1412
-     * @throws InvalidInterfaceException
1413
-     */
1414
-    public function check_user_access($route_to_check = '', $verify_only = false)
1415
-    {
1416
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1417
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1418
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1419
-                          && is_array(
1420
-                              $this->_page_routes[ $route_to_check ]
1421
-                          )
1422
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1423
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1424
-        if (empty($capability) && empty($route_to_check)) {
1425
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1426
-                : $this->_route['capability'];
1427
-        } else {
1428
-            $capability = empty($capability) ? 'manage_options' : $capability;
1429
-        }
1430
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1431
-        if (
1432
-            ! $this->request->isAjax()
1433
-            && (
1434
-                ! function_exists('is_admin')
1435
-                || ! EE_Registry::instance()->CAP->current_user_can(
1436
-                    $capability,
1437
-                    $this->page_slug
1438
-                    . '_'
1439
-                    . $route_to_check,
1440
-                    $id
1441
-                )
1442
-            )
1443
-        ) {
1444
-            if ($verify_only) {
1445
-                return false;
1446
-            }
1447
-            if (is_user_logged_in()) {
1448
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1449
-            } else {
1450
-                return false;
1451
-            }
1452
-        }
1453
-        return true;
1454
-    }
1455
-
1456
-
1457
-    /**
1458
-     * admin_init_global
1459
-     * This runs all the code that we want executed within the WP admin_init hook.
1460
-     * This method executes for ALL EE Admin pages.
1461
-     *
1462
-     * @return void
1463
-     */
1464
-    public function admin_init_global()
1465
-    {
1466
-    }
1467
-
1468
-
1469
-    /**
1470
-     * wp_loaded_global
1471
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1472
-     * EE_Admin page and will execute on every EE Admin Page load
1473
-     *
1474
-     * @return void
1475
-     */
1476
-    public function wp_loaded()
1477
-    {
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * admin_notices
1483
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1484
-     * ALL EE_Admin pages.
1485
-     *
1486
-     * @return void
1487
-     */
1488
-    public function admin_notices_global()
1489
-    {
1490
-        $this->_display_no_javascript_warning();
1491
-        $this->_display_espresso_notices();
1492
-    }
1493
-
1494
-
1495
-    public function network_admin_notices_global()
1496
-    {
1497
-        $this->_display_no_javascript_warning();
1498
-        $this->_display_espresso_notices();
1499
-    }
1500
-
1501
-
1502
-    /**
1503
-     * admin_footer_scripts_global
1504
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1505
-     * will apply on ALL EE_Admin pages.
1506
-     *
1507
-     * @return void
1508
-     */
1509
-    public function admin_footer_scripts_global()
1510
-    {
1511
-        $this->_add_admin_page_ajax_loading_img();
1512
-        $this->_add_admin_page_overlay();
1513
-        // if metaboxes are present we need to add the nonce field
1514
-        if (
1515
-            isset($this->_route_config['metaboxes'])
1516
-            || isset($this->_route_config['list_table'])
1517
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1518
-        ) {
1519
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1520
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1521
-        }
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * admin_footer_global
1527
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1528
-     * ALL EE_Admin Pages.
1529
-     *
1530
-     * @return void
1531
-     */
1532
-    public function admin_footer_global()
1533
-    {
1534
-        // dialog container for dialog helper
1535
-        echo '
110
+	/**
111
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
112
+	 * actions.
113
+	 *
114
+	 * @since 4.6.x
115
+	 * @var array.
116
+	 */
117
+	protected $_default_route_query_args;
118
+
119
+	// set via request page and action args.
120
+	protected $_current_page;
121
+
122
+	protected $_current_view;
123
+
124
+	protected $_current_page_view_url;
125
+
126
+	/**
127
+	 * unprocessed value for the 'action' request param (default '')
128
+	 *
129
+	 * @var string
130
+	 */
131
+	protected $raw_req_action = '';
132
+
133
+	/**
134
+	 * unprocessed value for the 'page' request param (default '')
135
+	 *
136
+	 * @var string
137
+	 */
138
+	protected $raw_req_page = '';
139
+
140
+	/**
141
+	 * sanitized request action (and nonce)
142
+	 *
143
+	 * @var string
144
+	 */
145
+	protected $_req_action = '';
146
+
147
+	/**
148
+	 * sanitized request action nonce
149
+	 *
150
+	 * @var string
151
+	 */
152
+	protected $_req_nonce = '';
153
+
154
+	/**
155
+	 * @var string
156
+	 */
157
+	protected $_search_btn_label = '';
158
+
159
+	/**
160
+	 * @var string
161
+	 */
162
+	protected $_search_box_callback = '';
163
+
164
+	/**
165
+	 * @var WP_Screen
166
+	 */
167
+	protected $_current_screen;
168
+
169
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
170
+	protected $_hook_obj;
171
+
172
+	// for holding incoming request data
173
+	protected $_req_data = [];
174
+
175
+	// yes / no array for admin form fields
176
+	protected $_yes_no_values = [];
177
+
178
+	// some default things shared by all child classes
179
+	protected $_default_espresso_metaboxes;
180
+
181
+	/**
182
+	 * @var EE_Registry
183
+	 */
184
+	protected $EE = null;
185
+
186
+
187
+	/**
188
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
189
+	 *
190
+	 * @var boolean
191
+	 */
192
+	protected $_is_caf = false;
193
+
194
+
195
+	/**
196
+	 * @Constructor
197
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
198
+	 * @throws EE_Error
199
+	 * @throws InvalidArgumentException
200
+	 * @throws ReflectionException
201
+	 * @throws InvalidDataTypeException
202
+	 * @throws InvalidInterfaceException
203
+	 */
204
+	public function __construct($routing = true)
205
+	{
206
+		$this->loader  = LoaderFactory::getLoader();
207
+		$this->request = $this->loader->getShared(RequestInterface::class);
208
+		$this->_routing = $routing;
209
+
210
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
211
+			$this->_is_caf = true;
212
+		}
213
+		$this->_yes_no_values = [
214
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
215
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
216
+		];
217
+		// set the _req_data property.
218
+		$this->_req_data = $this->request->requestParams();
219
+		// set initial page props (child method)
220
+		$this->_init_page_props();
221
+		// set global defaults
222
+		$this->_set_defaults();
223
+		// set early because incoming requests could be ajax related and we need to register those hooks.
224
+		$this->_global_ajax_hooks();
225
+		$this->_ajax_hooks();
226
+		// other_page_hooks have to be early too.
227
+		$this->_do_other_page_hooks();
228
+		// set up page dependencies
229
+		$this->_before_page_setup();
230
+		$this->_page_setup();
231
+		// die();
232
+	}
233
+
234
+
235
+	/**
236
+	 * _init_page_props
237
+	 * Child classes use to set at least the following properties:
238
+	 * $page_slug.
239
+	 * $page_label.
240
+	 *
241
+	 * @abstract
242
+	 * @return void
243
+	 */
244
+	abstract protected function _init_page_props();
245
+
246
+
247
+	/**
248
+	 * _ajax_hooks
249
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
250
+	 * Note: within the ajax callback methods.
251
+	 *
252
+	 * @abstract
253
+	 * @return void
254
+	 */
255
+	abstract protected function _ajax_hooks();
256
+
257
+
258
+	/**
259
+	 * _define_page_props
260
+	 * child classes define page properties in here.  Must include at least:
261
+	 * $_admin_base_url = base_url for all admin pages
262
+	 * $_admin_page_title = default admin_page_title for admin pages
263
+	 * $_labels = array of default labels for various automatically generated elements:
264
+	 *    array(
265
+	 *        'buttons' => array(
266
+	 *            'add' => esc_html__('label for add new button'),
267
+	 *            'edit' => esc_html__('label for edit button'),
268
+	 *            'delete' => esc_html__('label for delete button')
269
+	 *            )
270
+	 *        )
271
+	 *
272
+	 * @abstract
273
+	 * @return void
274
+	 */
275
+	abstract protected function _define_page_props();
276
+
277
+
278
+	/**
279
+	 * _set_page_routes
280
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
281
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
282
+	 * have a 'default' route. Here's the format
283
+	 * $this->_page_routes = array(
284
+	 *        'default' => array(
285
+	 *            'func' => '_default_method_handling_route',
286
+	 *            'args' => array('array','of','args'),
287
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
288
+	 *            ajax request, backend processing)
289
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
290
+	 *            headers route after.  The string you enter here should match the defined route reference for a
291
+	 *            headers sent route.
292
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
293
+	 *            this route.
294
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
295
+	 *            checks).
296
+	 *        ),
297
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
298
+	 *        handling method.
299
+	 *        )
300
+	 * )
301
+	 *
302
+	 * @abstract
303
+	 * @return void
304
+	 */
305
+	abstract protected function _set_page_routes();
306
+
307
+
308
+	/**
309
+	 * _set_page_config
310
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
311
+	 * array corresponds to the page_route for the loaded page. Format:
312
+	 * $this->_page_config = array(
313
+	 *        'default' => array(
314
+	 *            'labels' => array(
315
+	 *                'buttons' => array(
316
+	 *                    'add' => esc_html__('label for adding item'),
317
+	 *                    'edit' => esc_html__('label for editing item'),
318
+	 *                    'delete' => esc_html__('label for deleting item')
319
+	 *                ),
320
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
321
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
322
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
323
+	 *            _define_page_props() method
324
+	 *            'nav' => array(
325
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
326
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
327
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
328
+	 *                'order' => 10, //required to indicate tab position.
329
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
330
+	 *                displayed then add this parameter.
331
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
332
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
333
+	 *            metaboxes set for eventespresso admin pages.
334
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
335
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
336
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
337
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
338
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
339
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
340
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
341
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
342
+	 *            want to display.
343
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
344
+	 *                'tab_id' => array(
345
+	 *                    'title' => 'tab_title',
346
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
347
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
348
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
349
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
350
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
351
+	 *                    attempt to use the callback which should match the name of a method in the class
352
+	 *                    ),
353
+	 *                'tab2_id' => array(
354
+	 *                    'title' => 'tab2 title',
355
+	 *                    'filename' => 'file_name_2'
356
+	 *                    'callback' => 'callback_method_for_content',
357
+	 *                 ),
358
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
359
+	 *            help tab area on an admin page. @return void
360
+	 *
361
+	 * @abstract
362
+	 */
363
+	abstract protected function _set_page_config();
364
+
365
+
366
+	/**
367
+	 * _add_screen_options
368
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
369
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
370
+	 * to a particular view.
371
+	 *
372
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
373
+	 *         see also WP_Screen object documents...
374
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
375
+	 * @abstract
376
+	 * @return void
377
+	 */
378
+	abstract protected function _add_screen_options();
379
+
380
+
381
+	/**
382
+	 * _add_feature_pointers
383
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
384
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
385
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
386
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
387
+	 * extended) also see:
388
+	 *
389
+	 * @link   http://eamann.com/tech/wordpress-portland/
390
+	 * @abstract
391
+	 * @return void
392
+	 */
393
+	abstract protected function _add_feature_pointers();
394
+
395
+
396
+	/**
397
+	 * load_scripts_styles
398
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
399
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
400
+	 * scripts/styles per view by putting them in a dynamic function in this format
401
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
402
+	 *
403
+	 * @abstract
404
+	 * @return void
405
+	 */
406
+	abstract public function load_scripts_styles();
407
+
408
+
409
+	/**
410
+	 * admin_init
411
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
412
+	 * all pages/views loaded by child class.
413
+	 *
414
+	 * @abstract
415
+	 * @return void
416
+	 */
417
+	abstract public function admin_init();
418
+
419
+
420
+	/**
421
+	 * admin_notices
422
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
423
+	 * all pages/views loaded by child class.
424
+	 *
425
+	 * @abstract
426
+	 * @return void
427
+	 */
428
+	abstract public function admin_notices();
429
+
430
+
431
+	/**
432
+	 * admin_footer_scripts
433
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
434
+	 * will apply to all pages/views loaded by child class.
435
+	 *
436
+	 * @return void
437
+	 */
438
+	abstract public function admin_footer_scripts();
439
+
440
+
441
+	/**
442
+	 * admin_footer
443
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
444
+	 * apply to all pages/views loaded by child class.
445
+	 *
446
+	 * @return void
447
+	 */
448
+	public function admin_footer()
449
+	{
450
+	}
451
+
452
+
453
+	/**
454
+	 * _global_ajax_hooks
455
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
456
+	 * Note: within the ajax callback methods.
457
+	 *
458
+	 * @abstract
459
+	 * @return void
460
+	 */
461
+	protected function _global_ajax_hooks()
462
+	{
463
+		// for lazy loading of metabox content
464
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
465
+	}
466
+
467
+
468
+	public function ajax_metabox_content()
469
+	{
470
+		$content_id  = $this->request->getRequestParam('contentid', '');
471
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
472
+		self::cached_rss_display($content_id, $content_url);
473
+		wp_die();
474
+	}
475
+
476
+
477
+	/**
478
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
479
+	 *
480
+	 * @return void
481
+	 */
482
+	protected function _before_page_setup()
483
+	{
484
+		// default is to do nothing
485
+	}
486
+
487
+
488
+	/**
489
+	 * Makes sure any things that need to be loaded early get handled.
490
+	 * We also escape early here if the page requested doesn't match the object.
491
+	 *
492
+	 * @final
493
+	 * @return void
494
+	 * @throws EE_Error
495
+	 * @throws InvalidArgumentException
496
+	 * @throws ReflectionException
497
+	 * @throws InvalidDataTypeException
498
+	 * @throws InvalidInterfaceException
499
+	 */
500
+	final protected function _page_setup()
501
+	{
502
+		// requires?
503
+		// admin_init stuff - global - we're setting this REALLY early
504
+		// so if EE_Admin pages have to hook into other WP pages they can.
505
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
506
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
507
+		// next verify if we need to load anything...
508
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
509
+		$this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, 'key');
510
+
511
+		$this->page_folder   = strtolower(
512
+			str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
513
+		);
514
+		global $ee_menu_slugs;
515
+		$ee_menu_slugs = (array) $ee_menu_slugs;
516
+		if (
517
+			! $this->request->isAjax()
518
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
519
+		) {
520
+			return;
521
+		}
522
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
523
+		// we need to copy the action from the second to the first
524
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
525
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
526
+		$action     = $action !== '-1' ? $action : $action2;
527
+		$req_action = $action !== '-1' ? $action : 'default';
528
+
529
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
530
+		// then let's use the route as the action.
531
+		// This covers cases where we're coming in from a list table that isn't on the default route.
532
+		$route = $this->request->getRequestParam('route');
533
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
534
+			? $route
535
+			: $req_action;
536
+
537
+		$this->_current_view = $this->_req_action;
538
+		$this->_req_nonce    = $this->_req_action . '_nonce';
539
+		$this->_define_page_props();
540
+		$this->_current_page_view_url = add_query_arg(
541
+			['page' => $this->_current_page, 'action' => $this->_current_view],
542
+			$this->_admin_base_url
543
+		);
544
+		// default things
545
+		$this->_default_espresso_metaboxes = [
546
+			'_espresso_news_post_box',
547
+			'_espresso_links_post_box',
548
+			'_espresso_ratings_request',
549
+			'_espresso_sponsors_post_box',
550
+		];
551
+		// set page configs
552
+		$this->_set_page_routes();
553
+		$this->_set_page_config();
554
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
555
+		if ($this->request->requestParamIsSet('wp_referer')) {
556
+			$wp_referer = $this->request->getRequestParam('wp_referer');
557
+			if ($wp_referer) {
558
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
559
+			}
560
+		}
561
+		// for caffeinated and other extended functionality.
562
+		//  If there is a _extend_page_config method
563
+		// then let's run that to modify the all the various page configuration arrays
564
+		if (method_exists($this, '_extend_page_config')) {
565
+			$this->_extend_page_config();
566
+		}
567
+		// for CPT and other extended functionality.
568
+		// If there is an _extend_page_config_for_cpt
569
+		// then let's run that to modify all the various page configuration arrays.
570
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
571
+			$this->_extend_page_config_for_cpt();
572
+		}
573
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
574
+		$this->_page_routes = apply_filters(
575
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
+			$this->_page_routes,
577
+			$this
578
+		);
579
+		$this->_page_config = apply_filters(
580
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
581
+			$this->_page_config,
582
+			$this
583
+		);
584
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
587
+			add_action(
588
+				'AHEE__EE_Admin_Page__route_admin_request',
589
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
590
+				10,
591
+				2
592
+			);
593
+		}
594
+		// next route only if routing enabled
595
+		if ($this->_routing && ! $this->request->isAjax()) {
596
+			$this->_verify_routes();
597
+			// next let's just check user_access and kill if no access
598
+			$this->check_user_access();
599
+			if ($this->_is_UI_request) {
600
+				// admin_init stuff - global, all views for this page class, specific view
601
+				add_action('admin_init', [$this, 'admin_init'], 10);
602
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
603
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
604
+				}
605
+			} else {
606
+				// hijack regular WP loading and route admin request immediately
607
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
608
+				$this->route_admin_request();
609
+			}
610
+		}
611
+	}
612
+
613
+
614
+	/**
615
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
616
+	 *
617
+	 * @return void
618
+	 * @throws EE_Error
619
+	 */
620
+	private function _do_other_page_hooks()
621
+	{
622
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
623
+		foreach ($registered_pages as $page) {
624
+			// now let's setup the file name and class that should be present
625
+			$classname = str_replace('.class.php', '', $page);
626
+			// autoloaders should take care of loading file
627
+			if (! class_exists($classname)) {
628
+				$error_msg[] = sprintf(
629
+					esc_html__(
630
+						'Something went wrong with loading the %s admin hooks page.',
631
+						'event_espresso'
632
+					),
633
+					$page
634
+				);
635
+				$error_msg[] = $error_msg[0]
636
+							   . "\r\n"
637
+							   . sprintf(
638
+								   esc_html__(
639
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
640
+									   'event_espresso'
641
+								   ),
642
+								   $page,
643
+								   '<br />',
644
+								   '<strong>' . $classname . '</strong>'
645
+							   );
646
+				throw new EE_Error(implode('||', $error_msg));
647
+			}
648
+			// notice we are passing the instance of this class to the hook object.
649
+			$this->loader->getShared($classname, [$this]);
650
+		}
651
+	}
652
+
653
+
654
+	/**
655
+	 * @throws ReflectionException
656
+	 * @throws EE_Error
657
+	 */
658
+	public function load_page_dependencies()
659
+	{
660
+		try {
661
+			$this->_load_page_dependencies();
662
+		} catch (EE_Error $e) {
663
+			$e->get_error();
664
+		}
665
+	}
666
+
667
+
668
+	/**
669
+	 * load_page_dependencies
670
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
671
+	 *
672
+	 * @return void
673
+	 * @throws DomainException
674
+	 * @throws EE_Error
675
+	 * @throws InvalidArgumentException
676
+	 * @throws InvalidDataTypeException
677
+	 * @throws InvalidInterfaceException
678
+	 */
679
+	protected function _load_page_dependencies()
680
+	{
681
+		// let's set the current_screen and screen options to override what WP set
682
+		$this->_current_screen = get_current_screen();
683
+		// load admin_notices - global, page class, and view specific
684
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
685
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
686
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
687
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
688
+		}
689
+		// load network admin_notices - global, page class, and view specific
690
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
691
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
692
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
693
+		}
694
+		// this will save any per_page screen options if they are present
695
+		$this->_set_per_page_screen_options();
696
+		// setup list table properties
697
+		$this->_set_list_table();
698
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
699
+		// However in some cases the metaboxes will need to be added within a route handling callback.
700
+		$this->_add_registered_meta_boxes();
701
+		$this->_add_screen_columns();
702
+		// add screen options - global, page child class, and view specific
703
+		$this->_add_global_screen_options();
704
+		$this->_add_screen_options();
705
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
706
+		if (method_exists($this, $add_screen_options)) {
707
+			$this->{$add_screen_options}();
708
+		}
709
+		// add help tab(s) - set via page_config and qtips.
710
+		$this->_add_help_tabs();
711
+		$this->_add_qtips();
712
+		// add feature_pointers - global, page child class, and view specific
713
+		$this->_add_feature_pointers();
714
+		$this->_add_global_feature_pointers();
715
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
716
+		if (method_exists($this, $add_feature_pointer)) {
717
+			$this->{$add_feature_pointer}();
718
+		}
719
+		// enqueue scripts/styles - global, page class, and view specific
720
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
721
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
722
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
723
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
724
+		}
725
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
726
+		// admin_print_footer_scripts - global, page child class, and view specific.
727
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
728
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
729
+		// is a good use case. Notice the late priority we're giving these
730
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
731
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
732
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
733
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
734
+		}
735
+		// admin footer scripts
736
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
737
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
738
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
739
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
740
+		}
741
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
742
+		// targeted hook
743
+		do_action(
744
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
745
+		);
746
+	}
747
+
748
+
749
+	/**
750
+	 * _set_defaults
751
+	 * This sets some global defaults for class properties.
752
+	 */
753
+	private function _set_defaults()
754
+	{
755
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
756
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
757
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
758
+		$this->_page_config          = $this->_default_route_query_args = [];
759
+		$this->_default_nav_tab_name = 'overview';
760
+		// init template args
761
+		$this->_template_args = [
762
+			'admin_page_header'  => '',
763
+			'admin_page_content' => '',
764
+			'post_body_content'  => '',
765
+			'before_list_table'  => '',
766
+			'after_list_table'   => '',
767
+		];
768
+	}
769
+
770
+
771
+	/**
772
+	 * route_admin_request
773
+	 *
774
+	 * @return void
775
+	 * @throws InvalidArgumentException
776
+	 * @throws InvalidInterfaceException
777
+	 * @throws InvalidDataTypeException
778
+	 * @throws EE_Error
779
+	 * @throws ReflectionException
780
+	 * @see    _route_admin_request()
781
+	 */
782
+	public function route_admin_request()
783
+	{
784
+		try {
785
+			$this->_route_admin_request();
786
+		} catch (EE_Error $e) {
787
+			$e->get_error();
788
+		}
789
+	}
790
+
791
+
792
+	public function set_wp_page_slug($wp_page_slug)
793
+	{
794
+		$this->_wp_page_slug = $wp_page_slug;
795
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
796
+		if (is_network_admin()) {
797
+			$this->_wp_page_slug .= '-network';
798
+		}
799
+	}
800
+
801
+
802
+	/**
803
+	 * _verify_routes
804
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
805
+	 * we know if we need to drop out.
806
+	 *
807
+	 * @return bool
808
+	 * @throws EE_Error
809
+	 */
810
+	protected function _verify_routes()
811
+	{
812
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
813
+		if (! $this->_current_page && ! $this->request->isAjax()) {
814
+			return false;
815
+		}
816
+		$this->_route = false;
817
+		// check that the page_routes array is not empty
818
+		if (empty($this->_page_routes)) {
819
+			// user error msg
820
+			$error_msg = sprintf(
821
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
822
+				$this->_admin_page_title
823
+			);
824
+			// developer error msg
825
+			$error_msg .= '||' . $error_msg
826
+						  . esc_html__(
827
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
828
+							  'event_espresso'
829
+						  );
830
+			throw new EE_Error($error_msg);
831
+		}
832
+		// and that the requested page route exists
833
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
834
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
835
+			$this->_route_config = isset($this->_page_config[ $this->_req_action ])
836
+				? $this->_page_config[ $this->_req_action ]
837
+				: [];
838
+		} else {
839
+			// user error msg
840
+			$error_msg = sprintf(
841
+				esc_html__(
842
+					'The requested page route does not exist for the %s admin page.',
843
+					'event_espresso'
844
+				),
845
+				$this->_admin_page_title
846
+			);
847
+			// developer error msg
848
+			$error_msg .= '||' . $error_msg
849
+						  . sprintf(
850
+							  esc_html__(
851
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
852
+								  'event_espresso'
853
+							  ),
854
+							  $this->_req_action
855
+						  );
856
+			throw new EE_Error($error_msg);
857
+		}
858
+		// and that a default route exists
859
+		if (! array_key_exists('default', $this->_page_routes)) {
860
+			// user error msg
861
+			$error_msg = sprintf(
862
+				esc_html__(
863
+					'A default page route has not been set for the % admin page.',
864
+					'event_espresso'
865
+				),
866
+				$this->_admin_page_title
867
+			);
868
+			// developer error msg
869
+			$error_msg .= '||' . $error_msg
870
+						  . esc_html__(
871
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
872
+							  'event_espresso'
873
+						  );
874
+			throw new EE_Error($error_msg);
875
+		}
876
+		// first lets' catch if the UI request has EVER been set.
877
+		if ($this->_is_UI_request === null) {
878
+			// lets set if this is a UI request or not.
879
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
880
+			// wait a minute... we might have a noheader in the route array
881
+			$this->_is_UI_request = ! (
882
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
883
+			)
884
+				? $this->_is_UI_request
885
+				: false;
886
+		}
887
+		$this->_set_current_labels();
888
+		return true;
889
+	}
890
+
891
+
892
+	/**
893
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
894
+	 *
895
+	 * @param string $route the route name we're verifying
896
+	 * @return bool we'll throw an exception if this isn't a valid route.
897
+	 * @throws EE_Error
898
+	 */
899
+	protected function _verify_route($route)
900
+	{
901
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
902
+			return true;
903
+		}
904
+		// user error msg
905
+		$error_msg = sprintf(
906
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
907
+			$this->_admin_page_title
908
+		);
909
+		// developer error msg
910
+		$error_msg .= '||' . $error_msg
911
+					  . sprintf(
912
+						  esc_html__(
913
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
914
+							  'event_espresso'
915
+						  ),
916
+						  $route
917
+					  );
918
+		throw new EE_Error($error_msg);
919
+	}
920
+
921
+
922
+	/**
923
+	 * perform nonce verification
924
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
925
+	 * using this method (and save retyping!)
926
+	 *
927
+	 * @param string $nonce     The nonce sent
928
+	 * @param string $nonce_ref The nonce reference string (name0)
929
+	 * @return void
930
+	 * @throws EE_Error
931
+	 */
932
+	protected function _verify_nonce($nonce, $nonce_ref)
933
+	{
934
+		// verify nonce against expected value
935
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
936
+			// these are not the droids you are looking for !!!
937
+			$msg = sprintf(
938
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
939
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
940
+				'</a>'
941
+			);
942
+			if (WP_DEBUG) {
943
+				$msg .= "\n  ";
944
+				$msg .= sprintf(
945
+					esc_html__(
946
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
947
+						'event_espresso'
948
+					),
949
+					__CLASS__
950
+				);
951
+			}
952
+			if (! $this->request->isAjax()) {
953
+				wp_die($msg);
954
+			}
955
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
956
+			$this->_return_json();
957
+		}
958
+	}
959
+
960
+
961
+	/**
962
+	 * _route_admin_request()
963
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
964
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
965
+	 * in the page routes and then will try to load the corresponding method.
966
+	 *
967
+	 * @return void
968
+	 * @throws EE_Error
969
+	 * @throws InvalidArgumentException
970
+	 * @throws InvalidDataTypeException
971
+	 * @throws InvalidInterfaceException
972
+	 * @throws ReflectionException
973
+	 */
974
+	protected function _route_admin_request()
975
+	{
976
+		if (! $this->_is_UI_request) {
977
+			$this->_verify_routes();
978
+		}
979
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
980
+		if ($this->_req_action !== 'default' && $nonce_check) {
981
+			// set nonce from post data
982
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
983
+			$this->_verify_nonce($nonce, $this->_req_nonce);
984
+		}
985
+		// set the nav_tabs array but ONLY if this is  UI_request
986
+		if ($this->_is_UI_request) {
987
+			$this->_set_nav_tabs();
988
+		}
989
+		// grab callback function
990
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
991
+		// check if callback has args
992
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
993
+		$error_msg = '';
994
+		// action right before calling route
995
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
996
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
997
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
998
+		}
999
+		// right before calling the route, let's clean the _wp_http_referer
1000
+		$this->request->unSetRequestParam('_wp_http_referer');
1001
+		$this->request->unSetServerParam('_wp_http_referer');
1002
+		$cleaner_request_uri = remove_query_arg(
1003
+			'_wp_http_referer',
1004
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1005
+		);
1006
+		$this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri);
1007
+		$this->request->setServerParam('REQUEST_URI', $cleaner_request_uri);
1008
+		if (! empty($func)) {
1009
+			if (is_array($func)) {
1010
+				[$class, $method] = $func;
1011
+			} elseif (strpos($func, '::') !== false) {
1012
+				[$class, $method] = explode('::', $func);
1013
+			} else {
1014
+				$class  = $this;
1015
+				$method = $func;
1016
+			}
1017
+			if (! (is_object($class) && $class === $this) && ! in_array($this, $args)) {
1018
+				// send along this admin page object for access by addons.
1019
+				$args['admin_page'] = $this;
1020
+			}
1021
+			if (
1022
+				// is it a method on a class that doesn't work?
1023
+				(
1024
+					(
1025
+						method_exists($class, $method)
1026
+						&& call_user_func_array([$class, $method], $args) === false
1027
+					)
1028
+					&& (
1029
+						// is it a standalone function that doesn't work?
1030
+						function_exists($method)
1031
+						&& call_user_func_array(
1032
+							$func,
1033
+							array_merge(['admin_page' => $this], $args)
1034
+						) === false
1035
+					)
1036
+				)
1037
+				|| (
1038
+					// is it neither a class method NOR a standalone function?
1039
+					! method_exists($class, $method)
1040
+					&& ! function_exists($method)
1041
+				)
1042
+			) {
1043
+				// user error msg
1044
+				$error_msg = esc_html__(
1045
+					'An error occurred. The  requested page route could not be found.',
1046
+					'event_espresso'
1047
+				);
1048
+				// developer error msg
1049
+				$error_msg .= '||';
1050
+				$error_msg .= sprintf(
1051
+					esc_html__(
1052
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1053
+						'event_espresso'
1054
+					),
1055
+					$method
1056
+				);
1057
+			}
1058
+			if (! empty($error_msg)) {
1059
+				throw new EE_Error($error_msg);
1060
+			}
1061
+		}
1062
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1063
+		// then we need to reset the routing properties to the new route.
1064
+		// now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1065
+		if (
1066
+			$this->_is_UI_request === false
1067
+			&& is_array($this->_route)
1068
+			&& ! empty($this->_route['headers_sent_route'])
1069
+		) {
1070
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1071
+		}
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * This method just allows the resetting of page properties in the case where a no headers
1077
+	 * route redirects to a headers route in its route config.
1078
+	 *
1079
+	 * @param string $new_route New (non header) route to redirect to.
1080
+	 * @return   void
1081
+	 * @throws ReflectionException
1082
+	 * @throws InvalidArgumentException
1083
+	 * @throws InvalidInterfaceException
1084
+	 * @throws InvalidDataTypeException
1085
+	 * @throws EE_Error
1086
+	 * @since   4.3.0
1087
+	 */
1088
+	protected function _reset_routing_properties($new_route)
1089
+	{
1090
+		$this->_is_UI_request = true;
1091
+		// now we set the current route to whatever the headers_sent_route is set at
1092
+		$this->request->setRequestParam('action', $new_route);
1093
+		// rerun page setup
1094
+		$this->_page_setup();
1095
+	}
1096
+
1097
+
1098
+	/**
1099
+	 * _add_query_arg
1100
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1101
+	 *(internally just uses EEH_URL's function with the same name)
1102
+	 *
1103
+	 * @param array  $args
1104
+	 * @param string $url
1105
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1106
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1107
+	 *                                        Example usage: If the current page is:
1108
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1109
+	 *                                        &action=default&event_id=20&month_range=March%202015
1110
+	 *                                        &_wpnonce=5467821
1111
+	 *                                        and you call:
1112
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1113
+	 *                                        array(
1114
+	 *                                        'action' => 'resend_something',
1115
+	 *                                        'page=>espresso_registrations'
1116
+	 *                                        ),
1117
+	 *                                        $some_url,
1118
+	 *                                        true
1119
+	 *                                        );
1120
+	 *                                        It will produce a url in this structure:
1121
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1122
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1123
+	 *                                        month_range]=March%202015
1124
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1125
+	 * @return string
1126
+	 */
1127
+	public static function add_query_args_and_nonce(
1128
+		$args = [],
1129
+		$url = false,
1130
+		$sticky = false,
1131
+		$exclude_nonce = false
1132
+	) {
1133
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1134
+		if ($sticky) {
1135
+			/** @var RequestInterface $request */
1136
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1137
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1138
+			foreach ($request->requestParams() as $key => $value) {
1139
+				// do not add nonces
1140
+				if (strpos($key, 'nonce') !== false) {
1141
+					continue;
1142
+				}
1143
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1144
+			}
1145
+		}
1146
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * This returns a generated link that will load the related help tab.
1152
+	 *
1153
+	 * @param string $help_tab_id the id for the connected help tab
1154
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1155
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1156
+	 * @return string              generated link
1157
+	 * @uses EEH_Template::get_help_tab_link()
1158
+	 */
1159
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1160
+	{
1161
+		return EEH_Template::get_help_tab_link(
1162
+			$help_tab_id,
1163
+			$this->page_slug,
1164
+			$this->_req_action,
1165
+			$icon_style,
1166
+			$help_text
1167
+		);
1168
+	}
1169
+
1170
+
1171
+	/**
1172
+	 * _add_help_tabs
1173
+	 * Note child classes define their help tabs within the page_config array.
1174
+	 *
1175
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1176
+	 * @return void
1177
+	 * @throws DomainException
1178
+	 * @throws EE_Error
1179
+	 */
1180
+	protected function _add_help_tabs()
1181
+	{
1182
+		if (isset($this->_page_config[ $this->_req_action ])) {
1183
+			$config = $this->_page_config[ $this->_req_action ];
1184
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1185
+			if (is_array($config) && isset($config['help_sidebar'])) {
1186
+				// check that the callback given is valid
1187
+				if (! method_exists($this, $config['help_sidebar'])) {
1188
+					throw new EE_Error(
1189
+						sprintf(
1190
+							esc_html__(
1191
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1192
+								'event_espresso'
1193
+							),
1194
+							$config['help_sidebar'],
1195
+							get_class($this)
1196
+						)
1197
+					);
1198
+				}
1199
+				$content = apply_filters(
1200
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1201
+					$this->{$config['help_sidebar']}()
1202
+				);
1203
+				$this->_current_screen->set_help_sidebar($content);
1204
+			}
1205
+			if (! isset($config['help_tabs'])) {
1206
+				return;
1207
+			} //no help tabs for this route
1208
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1209
+				// we're here so there ARE help tabs!
1210
+				// make sure we've got what we need
1211
+				if (! isset($cfg['title'])) {
1212
+					throw new EE_Error(
1213
+						esc_html__(
1214
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1215
+							'event_espresso'
1216
+						)
1217
+					);
1218
+				}
1219
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1220
+					throw new EE_Error(
1221
+						esc_html__(
1222
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1223
+							'event_espresso'
1224
+						)
1225
+					);
1226
+				}
1227
+				// first priority goes to content.
1228
+				if (! empty($cfg['content'])) {
1229
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1230
+					// second priority goes to filename
1231
+				} elseif (! empty($cfg['filename'])) {
1232
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1233
+					// it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1234
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1235
+															 . basename($this->_get_dir())
1236
+															 . '/help_tabs/'
1237
+															 . $cfg['filename']
1238
+															 . '.help_tab.php' : $file_path;
1239
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1240
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1241
+						EE_Error::add_error(
1242
+							sprintf(
1243
+								esc_html__(
1244
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1245
+									'event_espresso'
1246
+								),
1247
+								$tab_id,
1248
+								key($config),
1249
+								$file_path
1250
+							),
1251
+							__FILE__,
1252
+							__FUNCTION__,
1253
+							__LINE__
1254
+						);
1255
+						return;
1256
+					}
1257
+					$template_args['admin_page_obj'] = $this;
1258
+					$content                         = EEH_Template::display_template(
1259
+						$file_path,
1260
+						$template_args,
1261
+						true
1262
+					);
1263
+				} else {
1264
+					$content = '';
1265
+				}
1266
+				// check if callback is valid
1267
+				if (
1268
+					empty($content)
1269
+					&& (
1270
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1271
+					)
1272
+				) {
1273
+					EE_Error::add_error(
1274
+						sprintf(
1275
+							esc_html__(
1276
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1277
+								'event_espresso'
1278
+							),
1279
+							$cfg['title']
1280
+						),
1281
+						__FILE__,
1282
+						__FUNCTION__,
1283
+						__LINE__
1284
+					);
1285
+					return;
1286
+				}
1287
+				// setup config array for help tab method
1288
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1289
+				$_ht = [
1290
+					'id'       => $id,
1291
+					'title'    => $cfg['title'],
1292
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1293
+					'content'  => $content,
1294
+				];
1295
+				$this->_current_screen->add_help_tab($_ht);
1296
+			}
1297
+		}
1298
+	}
1299
+
1300
+
1301
+	/**
1302
+	 * This simply sets up any qtips that have been defined in the page config
1303
+	 *
1304
+	 * @return void
1305
+	 */
1306
+	protected function _add_qtips()
1307
+	{
1308
+		if (isset($this->_route_config['qtips'])) {
1309
+			$qtips = (array) $this->_route_config['qtips'];
1310
+			// load qtip loader
1311
+			$path = [
1312
+				$this->_get_dir() . '/qtips/',
1313
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1314
+			];
1315
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1316
+		}
1317
+	}
1318
+
1319
+
1320
+	/**
1321
+	 * _set_nav_tabs
1322
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1323
+	 * wish to add additional tabs or modify accordingly.
1324
+	 *
1325
+	 * @return void
1326
+	 * @throws InvalidArgumentException
1327
+	 * @throws InvalidInterfaceException
1328
+	 * @throws InvalidDataTypeException
1329
+	 */
1330
+	protected function _set_nav_tabs()
1331
+	{
1332
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1333
+		$i = 0;
1334
+		foreach ($this->_page_config as $slug => $config) {
1335
+			if (! is_array($config) || empty($config['nav'])) {
1336
+				continue;
1337
+			}
1338
+			// no nav tab for this config
1339
+			// check for persistent flag
1340
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1341
+				// nav tab is only to appear when route requested.
1342
+				continue;
1343
+			}
1344
+			if (! $this->check_user_access($slug, true)) {
1345
+				// no nav tab because current user does not have access.
1346
+				continue;
1347
+			}
1348
+			$css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1349
+			$this->_nav_tabs[ $slug ] = [
1350
+				'url'       => isset($config['nav']['url'])
1351
+					? $config['nav']['url']
1352
+					: self::add_query_args_and_nonce(
1353
+						['action' => $slug],
1354
+						$this->_admin_base_url
1355
+					),
1356
+				'link_text' => isset($config['nav']['label'])
1357
+					? $config['nav']['label']
1358
+					: ucwords(
1359
+						str_replace('_', ' ', $slug)
1360
+					),
1361
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1362
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1363
+			];
1364
+			$i++;
1365
+		}
1366
+		// if $this->_nav_tabs is empty then lets set the default
1367
+		if (empty($this->_nav_tabs)) {
1368
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1369
+				'url'       => $this->_admin_base_url,
1370
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1371
+				'css_class' => 'nav-tab-active',
1372
+				'order'     => 10,
1373
+			];
1374
+		}
1375
+		// now let's sort the tabs according to order
1376
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1377
+	}
1378
+
1379
+
1380
+	/**
1381
+	 * _set_current_labels
1382
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1383
+	 * property array
1384
+	 *
1385
+	 * @return void
1386
+	 */
1387
+	private function _set_current_labels()
1388
+	{
1389
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1390
+			foreach ($this->_route_config['labels'] as $label => $text) {
1391
+				if (is_array($text)) {
1392
+					foreach ($text as $sublabel => $subtext) {
1393
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1394
+					}
1395
+				} else {
1396
+					$this->_labels[ $label ] = $text;
1397
+				}
1398
+			}
1399
+		}
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 *        verifies user access for this admin page
1405
+	 *
1406
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1407
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1408
+	 *                               return false if verify fail.
1409
+	 * @return bool
1410
+	 * @throws InvalidArgumentException
1411
+	 * @throws InvalidDataTypeException
1412
+	 * @throws InvalidInterfaceException
1413
+	 */
1414
+	public function check_user_access($route_to_check = '', $verify_only = false)
1415
+	{
1416
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1417
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1418
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1419
+						  && is_array(
1420
+							  $this->_page_routes[ $route_to_check ]
1421
+						  )
1422
+						  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1423
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1424
+		if (empty($capability) && empty($route_to_check)) {
1425
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1426
+				: $this->_route['capability'];
1427
+		} else {
1428
+			$capability = empty($capability) ? 'manage_options' : $capability;
1429
+		}
1430
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1431
+		if (
1432
+			! $this->request->isAjax()
1433
+			&& (
1434
+				! function_exists('is_admin')
1435
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1436
+					$capability,
1437
+					$this->page_slug
1438
+					. '_'
1439
+					. $route_to_check,
1440
+					$id
1441
+				)
1442
+			)
1443
+		) {
1444
+			if ($verify_only) {
1445
+				return false;
1446
+			}
1447
+			if (is_user_logged_in()) {
1448
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1449
+			} else {
1450
+				return false;
1451
+			}
1452
+		}
1453
+		return true;
1454
+	}
1455
+
1456
+
1457
+	/**
1458
+	 * admin_init_global
1459
+	 * This runs all the code that we want executed within the WP admin_init hook.
1460
+	 * This method executes for ALL EE Admin pages.
1461
+	 *
1462
+	 * @return void
1463
+	 */
1464
+	public function admin_init_global()
1465
+	{
1466
+	}
1467
+
1468
+
1469
+	/**
1470
+	 * wp_loaded_global
1471
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1472
+	 * EE_Admin page and will execute on every EE Admin Page load
1473
+	 *
1474
+	 * @return void
1475
+	 */
1476
+	public function wp_loaded()
1477
+	{
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * admin_notices
1483
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1484
+	 * ALL EE_Admin pages.
1485
+	 *
1486
+	 * @return void
1487
+	 */
1488
+	public function admin_notices_global()
1489
+	{
1490
+		$this->_display_no_javascript_warning();
1491
+		$this->_display_espresso_notices();
1492
+	}
1493
+
1494
+
1495
+	public function network_admin_notices_global()
1496
+	{
1497
+		$this->_display_no_javascript_warning();
1498
+		$this->_display_espresso_notices();
1499
+	}
1500
+
1501
+
1502
+	/**
1503
+	 * admin_footer_scripts_global
1504
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1505
+	 * will apply on ALL EE_Admin pages.
1506
+	 *
1507
+	 * @return void
1508
+	 */
1509
+	public function admin_footer_scripts_global()
1510
+	{
1511
+		$this->_add_admin_page_ajax_loading_img();
1512
+		$this->_add_admin_page_overlay();
1513
+		// if metaboxes are present we need to add the nonce field
1514
+		if (
1515
+			isset($this->_route_config['metaboxes'])
1516
+			|| isset($this->_route_config['list_table'])
1517
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1518
+		) {
1519
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1520
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1521
+		}
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * admin_footer_global
1527
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1528
+	 * ALL EE_Admin Pages.
1529
+	 *
1530
+	 * @return void
1531
+	 */
1532
+	public function admin_footer_global()
1533
+	{
1534
+		// dialog container for dialog helper
1535
+		echo '
1536 1536
         <div class="ee-admin-dialog-container auto-hide hidden">
1537 1537
             <div class="ee-notices"></div>
1538 1538
             <div class="ee-admin-dialog-container-inner-content"></div>
1539 1539
         </div>
1540 1540
         ';
1541 1541
 
1542
-        // current set timezone for timezone js
1543
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1544
-    }
1545
-
1546
-
1547
-    /**
1548
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1549
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1550
-     * help popups then in your templates or your content you set "triggers" for the content using the
1551
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1552
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1553
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1554
-     * for the
1555
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1556
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1557
-     *    'help_trigger_id' => array(
1558
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1559
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1560
-     *    )
1561
-     * );
1562
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1563
-     *
1564
-     * @param array $help_array
1565
-     * @param bool  $display
1566
-     * @return string content
1567
-     * @throws DomainException
1568
-     * @throws EE_Error
1569
-     */
1570
-    protected function _set_help_popup_content($help_array = [], $display = false)
1571
-    {
1572
-        $content    = '';
1573
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1574
-        // loop through the array and setup content
1575
-        foreach ($help_array as $trigger => $help) {
1576
-            // make sure the array is setup properly
1577
-            if (! isset($help['title']) || ! isset($help['content'])) {
1578
-                throw new EE_Error(
1579
-                    esc_html__(
1580
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1581
-                        'event_espresso'
1582
-                    )
1583
-                );
1584
-            }
1585
-            // we're good so let's setup the template vars and then assign parsed template content to our content.
1586
-            $template_args = [
1587
-                'help_popup_id'      => $trigger,
1588
-                'help_popup_title'   => $help['title'],
1589
-                'help_popup_content' => $help['content'],
1590
-            ];
1591
-            $content       .= EEH_Template::display_template(
1592
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1593
-                $template_args,
1594
-                true
1595
-            );
1596
-        }
1597
-        if ($display) {
1598
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1599
-            return '';
1600
-        }
1601
-        return $content;
1602
-    }
1603
-
1604
-
1605
-    /**
1606
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1607
-     *
1608
-     * @return array properly formatted array for help popup content
1609
-     * @throws EE_Error
1610
-     */
1611
-    private function _get_help_content()
1612
-    {
1613
-        // what is the method we're looking for?
1614
-        $method_name = '_help_popup_content_' . $this->_req_action;
1615
-        // if method doesn't exist let's get out.
1616
-        if (! method_exists($this, $method_name)) {
1617
-            return [];
1618
-        }
1619
-        // k we're good to go let's retrieve the help array
1620
-        $help_array = call_user_func([$this, $method_name]);
1621
-        // make sure we've got an array!
1622
-        if (! is_array($help_array)) {
1623
-            throw new EE_Error(
1624
-                esc_html__(
1625
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1626
-                    'event_espresso'
1627
-                )
1628
-            );
1629
-        }
1630
-        return $help_array;
1631
-    }
1632
-
1633
-
1634
-    /**
1635
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1636
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1637
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1638
-     *
1639
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1640
-     * @param boolean $display    if false then we return the trigger string
1641
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1642
-     * @return string
1643
-     * @throws DomainException
1644
-     * @throws EE_Error
1645
-     */
1646
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1647
-    {
1648
-        if ($this->request->isAjax()) {
1649
-            return '';
1650
-        }
1651
-        // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1652
-        $help_array   = $this->_get_help_content();
1653
-        $help_content = '';
1654
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1655
-            $help_array[ $trigger_id ] = [
1656
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1657
-                'content' => esc_html__(
1658
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1659
-                    'event_espresso'
1660
-                ),
1661
-            ];
1662
-            $help_content              = $this->_set_help_popup_content($help_array);
1663
-        }
1664
-        // let's setup the trigger
1665
-        $content = '<a class="ee-dialog" href="?height='
1666
-                   . esc_attr($dimensions[0])
1667
-                   . '&width='
1668
-                   . esc_attr($dimensions[1])
1669
-                   . '&inlineId='
1670
-                   . esc_attr($trigger_id)
1671
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1672
-        $content .= $help_content;
1673
-        if ($display) {
1674
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1675
-            return '';
1676
-        }
1677
-        return $content;
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     * _add_global_screen_options
1683
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1684
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1685
-     *
1686
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1687
-     *         see also WP_Screen object documents...
1688
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1689
-     * @abstract
1690
-     * @return void
1691
-     */
1692
-    private function _add_global_screen_options()
1693
-    {
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * _add_global_feature_pointers
1699
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1700
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1701
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1702
-     *
1703
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1704
-     *         extended) also see:
1705
-     * @link   http://eamann.com/tech/wordpress-portland/
1706
-     * @abstract
1707
-     * @return void
1708
-     */
1709
-    private function _add_global_feature_pointers()
1710
-    {
1711
-    }
1712
-
1713
-
1714
-    /**
1715
-     * load_global_scripts_styles
1716
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1717
-     *
1718
-     * @return void
1719
-     */
1720
-    public function load_global_scripts_styles()
1721
-    {
1722
-        /** STYLES **/
1723
-        // add debugging styles
1724
-        if (WP_DEBUG) {
1725
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1726
-        }
1727
-        // register all styles
1728
-        wp_register_style(
1729
-            'espresso-ui-theme',
1730
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1731
-            [],
1732
-            EVENT_ESPRESSO_VERSION
1733
-        );
1734
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1735
-        // helpers styles
1736
-        wp_register_style(
1737
-            'ee-text-links',
1738
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1739
-            [],
1740
-            EVENT_ESPRESSO_VERSION
1741
-        );
1742
-        /** SCRIPTS **/
1743
-        // register all scripts
1744
-        wp_register_script(
1745
-            'ee-dialog',
1746
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1747
-            ['jquery', 'jquery-ui-draggable'],
1748
-            EVENT_ESPRESSO_VERSION,
1749
-            true
1750
-        );
1751
-        wp_register_script(
1752
-            'ee_admin_js',
1753
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1754
-            ['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1755
-            EVENT_ESPRESSO_VERSION,
1756
-            true
1757
-        );
1758
-        wp_register_script(
1759
-            'jquery-ui-timepicker-addon',
1760
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1761
-            ['jquery-ui-datepicker', 'jquery-ui-slider'],
1762
-            EVENT_ESPRESSO_VERSION,
1763
-            true
1764
-        );
1765
-        // script for sorting tables
1766
-        wp_register_script(
1767
-            'espresso_ajax_table_sorting',
1768
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1769
-            ['ee_admin_js', 'jquery-ui-sortable'],
1770
-            EVENT_ESPRESSO_VERSION,
1771
-            true
1772
-        );
1773
-        // script for parsing uri's
1774
-        wp_register_script(
1775
-            'ee-parse-uri',
1776
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1777
-            [],
1778
-            EVENT_ESPRESSO_VERSION,
1779
-            true
1780
-        );
1781
-        // and parsing associative serialized form elements
1782
-        wp_register_script(
1783
-            'ee-serialize-full-array',
1784
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1785
-            ['jquery'],
1786
-            EVENT_ESPRESSO_VERSION,
1787
-            true
1788
-        );
1789
-        // helpers scripts
1790
-        wp_register_script(
1791
-            'ee-text-links',
1792
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1793
-            ['jquery'],
1794
-            EVENT_ESPRESSO_VERSION,
1795
-            true
1796
-        );
1797
-        wp_register_script(
1798
-            'ee-moment-core',
1799
-            EE_GLOBAL_ASSETS_URL . 'moment/moment-with-locales.min.js',
1800
-            [],
1801
-            EVENT_ESPRESSO_VERSION,
1802
-            true
1803
-        );
1804
-        wp_register_script(
1805
-            'ee-moment',
1806
-            EE_GLOBAL_ASSETS_URL . 'moment/moment-timezone-with-data.min.js',
1807
-            ['ee-moment-core'],
1808
-            EVENT_ESPRESSO_VERSION,
1809
-            true
1810
-        );
1811
-        wp_register_script(
1812
-            'ee-datepicker',
1813
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1814
-            ['jquery-ui-timepicker-addon', 'ee-moment'],
1815
-            EVENT_ESPRESSO_VERSION,
1816
-            true
1817
-        );
1818
-        // google charts
1819
-        wp_register_script(
1820
-            'google-charts',
1821
-            'https://www.gstatic.com/charts/loader.js',
1822
-            [],
1823
-            EVENT_ESPRESSO_VERSION
1824
-        );
1825
-        // ENQUEUE ALL BASICS BY DEFAULT
1826
-        wp_enqueue_style('ee-admin-css');
1827
-        wp_enqueue_script('ee_admin_js');
1828
-        wp_enqueue_script('ee-accounting');
1829
-        wp_enqueue_script('jquery-validate');
1830
-        // taking care of metaboxes
1831
-        if (
1832
-            empty($this->_cpt_route)
1833
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1834
-        ) {
1835
-            wp_enqueue_script('dashboard');
1836
-        }
1837
-        // LOCALIZED DATA
1838
-        // localize script for ajax lazy loading
1839
-        $lazy_loader_container_ids = apply_filters(
1840
-            'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1841
-            ['espresso_news_post_box_content']
1842
-        );
1843
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1844
-        add_filter(
1845
-            'admin_body_class',
1846
-            function ($classes) {
1847
-                if (strpos($classes, 'espresso-admin') === false) {
1848
-                    $classes .= ' espresso-admin';
1849
-                }
1850
-                return $classes;
1851
-            }
1852
-        );
1853
-    }
1854
-
1855
-
1856
-    /**
1857
-     *        admin_footer_scripts_eei18n_js_strings
1858
-     *
1859
-     * @return        void
1860
-     */
1861
-    public function admin_footer_scripts_eei18n_js_strings()
1862
-    {
1863
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1864
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1865
-            __(
1866
-                'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
1867
-                'event_espresso'
1868
-            )
1869
-        );
1870
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1871
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1872
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1873
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1874
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1875
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1876
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1877
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1878
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1879
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1880
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1881
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1882
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1883
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1884
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1885
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1886
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1887
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1888
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1889
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1890
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1891
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1892
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1893
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1894
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1895
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1896
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1897
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1898
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1899
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1900
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1901
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1902
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1903
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1904
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1905
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1906
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1907
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1908
-    }
1909
-
1910
-
1911
-    /**
1912
-     *        load enhanced xdebug styles for ppl with failing eyesight
1913
-     *
1914
-     * @return        void
1915
-     */
1916
-    public function add_xdebug_style()
1917
-    {
1918
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1919
-    }
1920
-
1921
-
1922
-    /************************/
1923
-    /** LIST TABLE METHODS **/
1924
-    /************************/
1925
-    /**
1926
-     * this sets up the list table if the current view requires it.
1927
-     *
1928
-     * @return void
1929
-     * @throws EE_Error
1930
-     */
1931
-    protected function _set_list_table()
1932
-    {
1933
-        // first is this a list_table view?
1934
-        if (! isset($this->_route_config['list_table'])) {
1935
-            return;
1936
-        } //not a list_table view so get out.
1937
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
1938
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1939
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1940
-            // user error msg
1941
-            $error_msg = esc_html__(
1942
-                'An error occurred. The requested list table views could not be found.',
1943
-                'event_espresso'
1944
-            );
1945
-            // developer error msg
1946
-            $error_msg .= '||'
1947
-                          . sprintf(
1948
-                              esc_html__(
1949
-                                  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
1950
-                                  'event_espresso'
1951
-                              ),
1952
-                              $this->_req_action,
1953
-                              $list_table_view
1954
-                          );
1955
-            throw new EE_Error($error_msg);
1956
-        }
1957
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1958
-        $this->_views = apply_filters(
1959
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
1960
-            $this->_views
1961
-        );
1962
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1963
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1964
-        $this->_set_list_table_view();
1965
-        $this->_set_list_table_object();
1966
-    }
1967
-
1968
-
1969
-    /**
1970
-     * set current view for List Table
1971
-     *
1972
-     * @return void
1973
-     */
1974
-    protected function _set_list_table_view()
1975
-    {
1976
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1977
-        $status = $this->request->getRequestParam('status', null, 'key');
1978
-        $this->_view = $status && array_key_exists($status, $this->_views)
1979
-            ? $status
1980
-            : $this->_view;
1981
-    }
1982
-
1983
-
1984
-    /**
1985
-     * _set_list_table_object
1986
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1987
-     *
1988
-     * @throws InvalidInterfaceException
1989
-     * @throws InvalidArgumentException
1990
-     * @throws InvalidDataTypeException
1991
-     * @throws EE_Error
1992
-     * @throws InvalidInterfaceException
1993
-     */
1994
-    protected function _set_list_table_object()
1995
-    {
1996
-        if (isset($this->_route_config['list_table'])) {
1997
-            if (! class_exists($this->_route_config['list_table'])) {
1998
-                throw new EE_Error(
1999
-                    sprintf(
2000
-                        esc_html__(
2001
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2002
-                            'event_espresso'
2003
-                        ),
2004
-                        $this->_route_config['list_table'],
2005
-                        get_class($this)
2006
-                    )
2007
-                );
2008
-            }
2009
-            $this->_list_table_object = $this->loader->getShared(
2010
-                $this->_route_config['list_table'],
2011
-                [$this]
2012
-            );
2013
-        }
2014
-    }
2015
-
2016
-
2017
-    /**
2018
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2019
-     *
2020
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2021
-     *                                                    urls.  The array should be indexed by the view it is being
2022
-     *                                                    added to.
2023
-     * @return array
2024
-     */
2025
-    public function get_list_table_view_RLs($extra_query_args = [])
2026
-    {
2027
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2028
-        if (empty($this->_views)) {
2029
-            $this->_views = [];
2030
-        }
2031
-        // cycle thru views
2032
-        foreach ($this->_views as $key => $view) {
2033
-            $query_args = [];
2034
-            // check for current view
2035
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2036
-            $query_args['action']                        = $this->_req_action;
2037
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2038
-            $query_args['status']                        = $view['slug'];
2039
-            // merge any other arguments sent in.
2040
-            if (isset($extra_query_args[ $view['slug'] ])) {
2041
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2042
-            }
2043
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2044
-        }
2045
-        return $this->_views;
2046
-    }
2047
-
2048
-
2049
-    /**
2050
-     * _entries_per_page_dropdown
2051
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2052
-     *
2053
-     * @param int $max_entries total number of rows in the table
2054
-     * @return string
2055
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2056
-     *         WP does it.
2057
-     */
2058
-    protected function _entries_per_page_dropdown($max_entries = 0)
2059
-    {
2060
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2061
-        $values   = [10, 25, 50, 100];
2062
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2063
-        if ($max_entries) {
2064
-            $values[] = $max_entries;
2065
-            sort($values);
2066
-        }
2067
-        $entries_per_page_dropdown = '
1542
+		// current set timezone for timezone js
1543
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1544
+	}
1545
+
1546
+
1547
+	/**
1548
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1549
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1550
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1551
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1552
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1553
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1554
+	 * for the
1555
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1556
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1557
+	 *    'help_trigger_id' => array(
1558
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1559
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1560
+	 *    )
1561
+	 * );
1562
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1563
+	 *
1564
+	 * @param array $help_array
1565
+	 * @param bool  $display
1566
+	 * @return string content
1567
+	 * @throws DomainException
1568
+	 * @throws EE_Error
1569
+	 */
1570
+	protected function _set_help_popup_content($help_array = [], $display = false)
1571
+	{
1572
+		$content    = '';
1573
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1574
+		// loop through the array and setup content
1575
+		foreach ($help_array as $trigger => $help) {
1576
+			// make sure the array is setup properly
1577
+			if (! isset($help['title']) || ! isset($help['content'])) {
1578
+				throw new EE_Error(
1579
+					esc_html__(
1580
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1581
+						'event_espresso'
1582
+					)
1583
+				);
1584
+			}
1585
+			// we're good so let's setup the template vars and then assign parsed template content to our content.
1586
+			$template_args = [
1587
+				'help_popup_id'      => $trigger,
1588
+				'help_popup_title'   => $help['title'],
1589
+				'help_popup_content' => $help['content'],
1590
+			];
1591
+			$content       .= EEH_Template::display_template(
1592
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1593
+				$template_args,
1594
+				true
1595
+			);
1596
+		}
1597
+		if ($display) {
1598
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1599
+			return '';
1600
+		}
1601
+		return $content;
1602
+	}
1603
+
1604
+
1605
+	/**
1606
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1607
+	 *
1608
+	 * @return array properly formatted array for help popup content
1609
+	 * @throws EE_Error
1610
+	 */
1611
+	private function _get_help_content()
1612
+	{
1613
+		// what is the method we're looking for?
1614
+		$method_name = '_help_popup_content_' . $this->_req_action;
1615
+		// if method doesn't exist let's get out.
1616
+		if (! method_exists($this, $method_name)) {
1617
+			return [];
1618
+		}
1619
+		// k we're good to go let's retrieve the help array
1620
+		$help_array = call_user_func([$this, $method_name]);
1621
+		// make sure we've got an array!
1622
+		if (! is_array($help_array)) {
1623
+			throw new EE_Error(
1624
+				esc_html__(
1625
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1626
+					'event_espresso'
1627
+				)
1628
+			);
1629
+		}
1630
+		return $help_array;
1631
+	}
1632
+
1633
+
1634
+	/**
1635
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1636
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1637
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1638
+	 *
1639
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1640
+	 * @param boolean $display    if false then we return the trigger string
1641
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1642
+	 * @return string
1643
+	 * @throws DomainException
1644
+	 * @throws EE_Error
1645
+	 */
1646
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1647
+	{
1648
+		if ($this->request->isAjax()) {
1649
+			return '';
1650
+		}
1651
+		// let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1652
+		$help_array   = $this->_get_help_content();
1653
+		$help_content = '';
1654
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1655
+			$help_array[ $trigger_id ] = [
1656
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1657
+				'content' => esc_html__(
1658
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1659
+					'event_espresso'
1660
+				),
1661
+			];
1662
+			$help_content              = $this->_set_help_popup_content($help_array);
1663
+		}
1664
+		// let's setup the trigger
1665
+		$content = '<a class="ee-dialog" href="?height='
1666
+				   . esc_attr($dimensions[0])
1667
+				   . '&width='
1668
+				   . esc_attr($dimensions[1])
1669
+				   . '&inlineId='
1670
+				   . esc_attr($trigger_id)
1671
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1672
+		$content .= $help_content;
1673
+		if ($display) {
1674
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1675
+			return '';
1676
+		}
1677
+		return $content;
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 * _add_global_screen_options
1683
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1684
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1685
+	 *
1686
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1687
+	 *         see also WP_Screen object documents...
1688
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1689
+	 * @abstract
1690
+	 * @return void
1691
+	 */
1692
+	private function _add_global_screen_options()
1693
+	{
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * _add_global_feature_pointers
1699
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1700
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1701
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1702
+	 *
1703
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1704
+	 *         extended) also see:
1705
+	 * @link   http://eamann.com/tech/wordpress-portland/
1706
+	 * @abstract
1707
+	 * @return void
1708
+	 */
1709
+	private function _add_global_feature_pointers()
1710
+	{
1711
+	}
1712
+
1713
+
1714
+	/**
1715
+	 * load_global_scripts_styles
1716
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1717
+	 *
1718
+	 * @return void
1719
+	 */
1720
+	public function load_global_scripts_styles()
1721
+	{
1722
+		/** STYLES **/
1723
+		// add debugging styles
1724
+		if (WP_DEBUG) {
1725
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1726
+		}
1727
+		// register all styles
1728
+		wp_register_style(
1729
+			'espresso-ui-theme',
1730
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1731
+			[],
1732
+			EVENT_ESPRESSO_VERSION
1733
+		);
1734
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1735
+		// helpers styles
1736
+		wp_register_style(
1737
+			'ee-text-links',
1738
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1739
+			[],
1740
+			EVENT_ESPRESSO_VERSION
1741
+		);
1742
+		/** SCRIPTS **/
1743
+		// register all scripts
1744
+		wp_register_script(
1745
+			'ee-dialog',
1746
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1747
+			['jquery', 'jquery-ui-draggable'],
1748
+			EVENT_ESPRESSO_VERSION,
1749
+			true
1750
+		);
1751
+		wp_register_script(
1752
+			'ee_admin_js',
1753
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
1754
+			['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1755
+			EVENT_ESPRESSO_VERSION,
1756
+			true
1757
+		);
1758
+		wp_register_script(
1759
+			'jquery-ui-timepicker-addon',
1760
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1761
+			['jquery-ui-datepicker', 'jquery-ui-slider'],
1762
+			EVENT_ESPRESSO_VERSION,
1763
+			true
1764
+		);
1765
+		// script for sorting tables
1766
+		wp_register_script(
1767
+			'espresso_ajax_table_sorting',
1768
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1769
+			['ee_admin_js', 'jquery-ui-sortable'],
1770
+			EVENT_ESPRESSO_VERSION,
1771
+			true
1772
+		);
1773
+		// script for parsing uri's
1774
+		wp_register_script(
1775
+			'ee-parse-uri',
1776
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1777
+			[],
1778
+			EVENT_ESPRESSO_VERSION,
1779
+			true
1780
+		);
1781
+		// and parsing associative serialized form elements
1782
+		wp_register_script(
1783
+			'ee-serialize-full-array',
1784
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1785
+			['jquery'],
1786
+			EVENT_ESPRESSO_VERSION,
1787
+			true
1788
+		);
1789
+		// helpers scripts
1790
+		wp_register_script(
1791
+			'ee-text-links',
1792
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1793
+			['jquery'],
1794
+			EVENT_ESPRESSO_VERSION,
1795
+			true
1796
+		);
1797
+		wp_register_script(
1798
+			'ee-moment-core',
1799
+			EE_GLOBAL_ASSETS_URL . 'moment/moment-with-locales.min.js',
1800
+			[],
1801
+			EVENT_ESPRESSO_VERSION,
1802
+			true
1803
+		);
1804
+		wp_register_script(
1805
+			'ee-moment',
1806
+			EE_GLOBAL_ASSETS_URL . 'moment/moment-timezone-with-data.min.js',
1807
+			['ee-moment-core'],
1808
+			EVENT_ESPRESSO_VERSION,
1809
+			true
1810
+		);
1811
+		wp_register_script(
1812
+			'ee-datepicker',
1813
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
1814
+			['jquery-ui-timepicker-addon', 'ee-moment'],
1815
+			EVENT_ESPRESSO_VERSION,
1816
+			true
1817
+		);
1818
+		// google charts
1819
+		wp_register_script(
1820
+			'google-charts',
1821
+			'https://www.gstatic.com/charts/loader.js',
1822
+			[],
1823
+			EVENT_ESPRESSO_VERSION
1824
+		);
1825
+		// ENQUEUE ALL BASICS BY DEFAULT
1826
+		wp_enqueue_style('ee-admin-css');
1827
+		wp_enqueue_script('ee_admin_js');
1828
+		wp_enqueue_script('ee-accounting');
1829
+		wp_enqueue_script('jquery-validate');
1830
+		// taking care of metaboxes
1831
+		if (
1832
+			empty($this->_cpt_route)
1833
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1834
+		) {
1835
+			wp_enqueue_script('dashboard');
1836
+		}
1837
+		// LOCALIZED DATA
1838
+		// localize script for ajax lazy loading
1839
+		$lazy_loader_container_ids = apply_filters(
1840
+			'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1841
+			['espresso_news_post_box_content']
1842
+		);
1843
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1844
+		add_filter(
1845
+			'admin_body_class',
1846
+			function ($classes) {
1847
+				if (strpos($classes, 'espresso-admin') === false) {
1848
+					$classes .= ' espresso-admin';
1849
+				}
1850
+				return $classes;
1851
+			}
1852
+		);
1853
+	}
1854
+
1855
+
1856
+	/**
1857
+	 *        admin_footer_scripts_eei18n_js_strings
1858
+	 *
1859
+	 * @return        void
1860
+	 */
1861
+	public function admin_footer_scripts_eei18n_js_strings()
1862
+	{
1863
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1864
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1865
+			__(
1866
+				'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
1867
+				'event_espresso'
1868
+			)
1869
+		);
1870
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1871
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1872
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1873
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1874
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1875
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1876
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1877
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1878
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1879
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1880
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1881
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1882
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1883
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1884
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1885
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1886
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1887
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1888
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1889
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1890
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1891
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1892
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1893
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1894
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1895
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1896
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1897
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1898
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1899
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1900
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1901
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1902
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1903
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1904
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1905
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1906
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1907
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1908
+	}
1909
+
1910
+
1911
+	/**
1912
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1913
+	 *
1914
+	 * @return        void
1915
+	 */
1916
+	public function add_xdebug_style()
1917
+	{
1918
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1919
+	}
1920
+
1921
+
1922
+	/************************/
1923
+	/** LIST TABLE METHODS **/
1924
+	/************************/
1925
+	/**
1926
+	 * this sets up the list table if the current view requires it.
1927
+	 *
1928
+	 * @return void
1929
+	 * @throws EE_Error
1930
+	 */
1931
+	protected function _set_list_table()
1932
+	{
1933
+		// first is this a list_table view?
1934
+		if (! isset($this->_route_config['list_table'])) {
1935
+			return;
1936
+		} //not a list_table view so get out.
1937
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
1938
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
1939
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1940
+			// user error msg
1941
+			$error_msg = esc_html__(
1942
+				'An error occurred. The requested list table views could not be found.',
1943
+				'event_espresso'
1944
+			);
1945
+			// developer error msg
1946
+			$error_msg .= '||'
1947
+						  . sprintf(
1948
+							  esc_html__(
1949
+								  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
1950
+								  'event_espresso'
1951
+							  ),
1952
+							  $this->_req_action,
1953
+							  $list_table_view
1954
+						  );
1955
+			throw new EE_Error($error_msg);
1956
+		}
1957
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1958
+		$this->_views = apply_filters(
1959
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
1960
+			$this->_views
1961
+		);
1962
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1963
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1964
+		$this->_set_list_table_view();
1965
+		$this->_set_list_table_object();
1966
+	}
1967
+
1968
+
1969
+	/**
1970
+	 * set current view for List Table
1971
+	 *
1972
+	 * @return void
1973
+	 */
1974
+	protected function _set_list_table_view()
1975
+	{
1976
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1977
+		$status = $this->request->getRequestParam('status', null, 'key');
1978
+		$this->_view = $status && array_key_exists($status, $this->_views)
1979
+			? $status
1980
+			: $this->_view;
1981
+	}
1982
+
1983
+
1984
+	/**
1985
+	 * _set_list_table_object
1986
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1987
+	 *
1988
+	 * @throws InvalidInterfaceException
1989
+	 * @throws InvalidArgumentException
1990
+	 * @throws InvalidDataTypeException
1991
+	 * @throws EE_Error
1992
+	 * @throws InvalidInterfaceException
1993
+	 */
1994
+	protected function _set_list_table_object()
1995
+	{
1996
+		if (isset($this->_route_config['list_table'])) {
1997
+			if (! class_exists($this->_route_config['list_table'])) {
1998
+				throw new EE_Error(
1999
+					sprintf(
2000
+						esc_html__(
2001
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2002
+							'event_espresso'
2003
+						),
2004
+						$this->_route_config['list_table'],
2005
+						get_class($this)
2006
+					)
2007
+				);
2008
+			}
2009
+			$this->_list_table_object = $this->loader->getShared(
2010
+				$this->_route_config['list_table'],
2011
+				[$this]
2012
+			);
2013
+		}
2014
+	}
2015
+
2016
+
2017
+	/**
2018
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2019
+	 *
2020
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2021
+	 *                                                    urls.  The array should be indexed by the view it is being
2022
+	 *                                                    added to.
2023
+	 * @return array
2024
+	 */
2025
+	public function get_list_table_view_RLs($extra_query_args = [])
2026
+	{
2027
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2028
+		if (empty($this->_views)) {
2029
+			$this->_views = [];
2030
+		}
2031
+		// cycle thru views
2032
+		foreach ($this->_views as $key => $view) {
2033
+			$query_args = [];
2034
+			// check for current view
2035
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2036
+			$query_args['action']                        = $this->_req_action;
2037
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2038
+			$query_args['status']                        = $view['slug'];
2039
+			// merge any other arguments sent in.
2040
+			if (isset($extra_query_args[ $view['slug'] ])) {
2041
+				$query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2042
+			}
2043
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2044
+		}
2045
+		return $this->_views;
2046
+	}
2047
+
2048
+
2049
+	/**
2050
+	 * _entries_per_page_dropdown
2051
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2052
+	 *
2053
+	 * @param int $max_entries total number of rows in the table
2054
+	 * @return string
2055
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2056
+	 *         WP does it.
2057
+	 */
2058
+	protected function _entries_per_page_dropdown($max_entries = 0)
2059
+	{
2060
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2061
+		$values   = [10, 25, 50, 100];
2062
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2063
+		if ($max_entries) {
2064
+			$values[] = $max_entries;
2065
+			sort($values);
2066
+		}
2067
+		$entries_per_page_dropdown = '
2068 2068
 			<div id="entries-per-page-dv" class="alignleft actions">
2069 2069
 				<label class="hide-if-no-js">
2070 2070
 					Show
2071 2071
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2072
-        foreach ($values as $value) {
2073
-            if ($value < $max_entries) {
2074
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2075
-                $entries_per_page_dropdown .= '
2072
+		foreach ($values as $value) {
2073
+			if ($value < $max_entries) {
2074
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2075
+				$entries_per_page_dropdown .= '
2076 2076
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2077
-            }
2078
-        }
2079
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2080
-        $entries_per_page_dropdown .= '
2077
+			}
2078
+		}
2079
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2080
+		$entries_per_page_dropdown .= '
2081 2081
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2082
-        $entries_per_page_dropdown .= '
2082
+		$entries_per_page_dropdown .= '
2083 2083
 					</select>
2084 2084
 					entries
2085 2085
 				</label>
2086 2086
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2087 2087
 			</div>
2088 2088
 		';
2089
-        return $entries_per_page_dropdown;
2090
-    }
2091
-
2092
-
2093
-    /**
2094
-     *        _set_search_attributes
2095
-     *
2096
-     * @return        void
2097
-     */
2098
-    public function _set_search_attributes()
2099
-    {
2100
-        $this->_template_args['search']['btn_label'] = sprintf(
2101
-            esc_html__('Search %s', 'event_espresso'),
2102
-            empty($this->_search_btn_label) ? $this->page_label
2103
-                : $this->_search_btn_label
2104
-        );
2105
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2106
-    }
2107
-
2108
-
2109
-
2110
-    /*** END LIST TABLE METHODS **/
2111
-
2112
-
2113
-    /**
2114
-     * _add_registered_metaboxes
2115
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2116
-     *
2117
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2118
-     * @return void
2119
-     * @throws EE_Error
2120
-     */
2121
-    private function _add_registered_meta_boxes()
2122
-    {
2123
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2124
-        // we only add meta boxes if the page_route calls for it
2125
-        if (
2126
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2127
-            && is_array(
2128
-                $this->_route_config['metaboxes']
2129
-            )
2130
-        ) {
2131
-            // this simply loops through the callbacks provided
2132
-            // and checks if there is a corresponding callback registered by the child
2133
-            // if there is then we go ahead and process the metabox loader.
2134
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2135
-                // first check for Closures
2136
-                if ($metabox_callback instanceof Closure) {
2137
-                    $result = $metabox_callback();
2138
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2139
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2140
-                } else {
2141
-                    $result = call_user_func([$this, &$metabox_callback]);
2142
-                }
2143
-                if ($result === false) {
2144
-                    // user error msg
2145
-                    $error_msg = esc_html__(
2146
-                        'An error occurred. The  requested metabox could not be found.',
2147
-                        'event_espresso'
2148
-                    );
2149
-                    // developer error msg
2150
-                    $error_msg .= '||'
2151
-                                  . sprintf(
2152
-                                      esc_html__(
2153
-                                          'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2154
-                                          'event_espresso'
2155
-                                      ),
2156
-                                      $metabox_callback
2157
-                                  );
2158
-                    throw new EE_Error($error_msg);
2159
-                }
2160
-            }
2161
-        }
2162
-    }
2163
-
2164
-
2165
-    /**
2166
-     * _add_screen_columns
2167
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2168
-     * the dynamic column template and we'll setup the column options for the page.
2169
-     *
2170
-     * @return void
2171
-     */
2172
-    private function _add_screen_columns()
2173
-    {
2174
-        if (
2175
-            is_array($this->_route_config)
2176
-            && isset($this->_route_config['columns'])
2177
-            && is_array($this->_route_config['columns'])
2178
-            && count($this->_route_config['columns']) === 2
2179
-        ) {
2180
-            add_screen_option(
2181
-                'layout_columns',
2182
-                [
2183
-                    'max'     => (int) $this->_route_config['columns'][0],
2184
-                    'default' => (int) $this->_route_config['columns'][1],
2185
-                ]
2186
-            );
2187
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2188
-            $screen_id                                           = $this->_current_screen->id;
2189
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2190
-            $total_columns                                       = ! empty($screen_columns)
2191
-                ? $screen_columns
2192
-                : $this->_route_config['columns'][1];
2193
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2194
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2195
-            $this->_template_args['screen']                      = $this->_current_screen;
2196
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2197
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2198
-            // finally if we don't have has_metaboxes set in the route config
2199
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2200
-            $this->_route_config['has_metaboxes'] = true;
2201
-        }
2202
-    }
2203
-
2204
-
2205
-
2206
-    /** GLOBALLY AVAILABLE METABOXES **/
2207
-
2208
-
2209
-    /**
2210
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2211
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2212
-     * these get loaded on.
2213
-     */
2214
-    private function _espresso_news_post_box()
2215
-    {
2216
-        $news_box_title = apply_filters(
2217
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2218
-            esc_html__('New @ Event Espresso', 'event_espresso')
2219
-        );
2220
-        add_meta_box(
2221
-            'espresso_news_post_box',
2222
-            $news_box_title,
2223
-            [
2224
-                $this,
2225
-                'espresso_news_post_box',
2226
-            ],
2227
-            $this->_wp_page_slug,
2228
-            'side'
2229
-        );
2230
-    }
2231
-
2232
-
2233
-    /**
2234
-     * Code for setting up espresso ratings request metabox.
2235
-     */
2236
-    protected function _espresso_ratings_request()
2237
-    {
2238
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2239
-            return;
2240
-        }
2241
-        $ratings_box_title = apply_filters(
2242
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2243
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2244
-        );
2245
-        add_meta_box(
2246
-            'espresso_ratings_request',
2247
-            $ratings_box_title,
2248
-            [
2249
-                $this,
2250
-                'espresso_ratings_request',
2251
-            ],
2252
-            $this->_wp_page_slug,
2253
-            'side'
2254
-        );
2255
-    }
2256
-
2257
-
2258
-    /**
2259
-     * Code for setting up espresso ratings request metabox content.
2260
-     *
2261
-     * @throws DomainException
2262
-     */
2263
-    public function espresso_ratings_request()
2264
-    {
2265
-        EEH_Template::display_template(
2266
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2267
-            []
2268
-        );
2269
-    }
2270
-
2271
-
2272
-    public static function cached_rss_display($rss_id, $url)
2273
-    {
2274
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2275
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2276
-                     . '</p><p class="hide-if-js">'
2277
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2278
-                     . '</p>';
2279
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2280
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2281
-        $post      = '</div>' . "\n";
2282
-        $cache_key = 'ee_rss_' . md5($rss_id);
2283
-        $output    = get_transient($cache_key);
2284
-        if ($output !== false) {
2285
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2286
-            return true;
2287
-        }
2288
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2289
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2290
-            return false;
2291
-        }
2292
-        ob_start();
2293
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2294
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2295
-        return true;
2296
-    }
2297
-
2298
-
2299
-    public function espresso_news_post_box()
2300
-    {
2301
-        ?>
2089
+		return $entries_per_page_dropdown;
2090
+	}
2091
+
2092
+
2093
+	/**
2094
+	 *        _set_search_attributes
2095
+	 *
2096
+	 * @return        void
2097
+	 */
2098
+	public function _set_search_attributes()
2099
+	{
2100
+		$this->_template_args['search']['btn_label'] = sprintf(
2101
+			esc_html__('Search %s', 'event_espresso'),
2102
+			empty($this->_search_btn_label) ? $this->page_label
2103
+				: $this->_search_btn_label
2104
+		);
2105
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2106
+	}
2107
+
2108
+
2109
+
2110
+	/*** END LIST TABLE METHODS **/
2111
+
2112
+
2113
+	/**
2114
+	 * _add_registered_metaboxes
2115
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2116
+	 *
2117
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2118
+	 * @return void
2119
+	 * @throws EE_Error
2120
+	 */
2121
+	private function _add_registered_meta_boxes()
2122
+	{
2123
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2124
+		// we only add meta boxes if the page_route calls for it
2125
+		if (
2126
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2127
+			&& is_array(
2128
+				$this->_route_config['metaboxes']
2129
+			)
2130
+		) {
2131
+			// this simply loops through the callbacks provided
2132
+			// and checks if there is a corresponding callback registered by the child
2133
+			// if there is then we go ahead and process the metabox loader.
2134
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2135
+				// first check for Closures
2136
+				if ($metabox_callback instanceof Closure) {
2137
+					$result = $metabox_callback();
2138
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2139
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2140
+				} else {
2141
+					$result = call_user_func([$this, &$metabox_callback]);
2142
+				}
2143
+				if ($result === false) {
2144
+					// user error msg
2145
+					$error_msg = esc_html__(
2146
+						'An error occurred. The  requested metabox could not be found.',
2147
+						'event_espresso'
2148
+					);
2149
+					// developer error msg
2150
+					$error_msg .= '||'
2151
+								  . sprintf(
2152
+									  esc_html__(
2153
+										  'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2154
+										  'event_espresso'
2155
+									  ),
2156
+									  $metabox_callback
2157
+								  );
2158
+					throw new EE_Error($error_msg);
2159
+				}
2160
+			}
2161
+		}
2162
+	}
2163
+
2164
+
2165
+	/**
2166
+	 * _add_screen_columns
2167
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2168
+	 * the dynamic column template and we'll setup the column options for the page.
2169
+	 *
2170
+	 * @return void
2171
+	 */
2172
+	private function _add_screen_columns()
2173
+	{
2174
+		if (
2175
+			is_array($this->_route_config)
2176
+			&& isset($this->_route_config['columns'])
2177
+			&& is_array($this->_route_config['columns'])
2178
+			&& count($this->_route_config['columns']) === 2
2179
+		) {
2180
+			add_screen_option(
2181
+				'layout_columns',
2182
+				[
2183
+					'max'     => (int) $this->_route_config['columns'][0],
2184
+					'default' => (int) $this->_route_config['columns'][1],
2185
+				]
2186
+			);
2187
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2188
+			$screen_id                                           = $this->_current_screen->id;
2189
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2190
+			$total_columns                                       = ! empty($screen_columns)
2191
+				? $screen_columns
2192
+				: $this->_route_config['columns'][1];
2193
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2194
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2195
+			$this->_template_args['screen']                      = $this->_current_screen;
2196
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2197
+																   . 'admin_details_metabox_column_wrapper.template.php';
2198
+			// finally if we don't have has_metaboxes set in the route config
2199
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2200
+			$this->_route_config['has_metaboxes'] = true;
2201
+		}
2202
+	}
2203
+
2204
+
2205
+
2206
+	/** GLOBALLY AVAILABLE METABOXES **/
2207
+
2208
+
2209
+	/**
2210
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2211
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2212
+	 * these get loaded on.
2213
+	 */
2214
+	private function _espresso_news_post_box()
2215
+	{
2216
+		$news_box_title = apply_filters(
2217
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2218
+			esc_html__('New @ Event Espresso', 'event_espresso')
2219
+		);
2220
+		add_meta_box(
2221
+			'espresso_news_post_box',
2222
+			$news_box_title,
2223
+			[
2224
+				$this,
2225
+				'espresso_news_post_box',
2226
+			],
2227
+			$this->_wp_page_slug,
2228
+			'side'
2229
+		);
2230
+	}
2231
+
2232
+
2233
+	/**
2234
+	 * Code for setting up espresso ratings request metabox.
2235
+	 */
2236
+	protected function _espresso_ratings_request()
2237
+	{
2238
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2239
+			return;
2240
+		}
2241
+		$ratings_box_title = apply_filters(
2242
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2243
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2244
+		);
2245
+		add_meta_box(
2246
+			'espresso_ratings_request',
2247
+			$ratings_box_title,
2248
+			[
2249
+				$this,
2250
+				'espresso_ratings_request',
2251
+			],
2252
+			$this->_wp_page_slug,
2253
+			'side'
2254
+		);
2255
+	}
2256
+
2257
+
2258
+	/**
2259
+	 * Code for setting up espresso ratings request metabox content.
2260
+	 *
2261
+	 * @throws DomainException
2262
+	 */
2263
+	public function espresso_ratings_request()
2264
+	{
2265
+		EEH_Template::display_template(
2266
+			EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2267
+			[]
2268
+		);
2269
+	}
2270
+
2271
+
2272
+	public static function cached_rss_display($rss_id, $url)
2273
+	{
2274
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2275
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2276
+					 . '</p><p class="hide-if-js">'
2277
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2278
+					 . '</p>';
2279
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2280
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2281
+		$post      = '</div>' . "\n";
2282
+		$cache_key = 'ee_rss_' . md5($rss_id);
2283
+		$output    = get_transient($cache_key);
2284
+		if ($output !== false) {
2285
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2286
+			return true;
2287
+		}
2288
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2289
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2290
+			return false;
2291
+		}
2292
+		ob_start();
2293
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2294
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2295
+		return true;
2296
+	}
2297
+
2298
+
2299
+	public function espresso_news_post_box()
2300
+	{
2301
+		?>
2302 2302
         <div class="padding">
2303 2303
             <div id="espresso_news_post_box_content" class="infolinks">
2304 2304
                 <?php
2305
-                // Get RSS Feed(s)
2306
-                self::cached_rss_display(
2307
-                    'espresso_news_post_box_content',
2308
-                    esc_url_raw(
2309
-                        apply_filters(
2310
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2311
-                            'https://eventespresso.com/feed/'
2312
-                        )
2313
-                    )
2314
-                );
2315
-                ?>
2305
+				// Get RSS Feed(s)
2306
+				self::cached_rss_display(
2307
+					'espresso_news_post_box_content',
2308
+					esc_url_raw(
2309
+						apply_filters(
2310
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2311
+							'https://eventespresso.com/feed/'
2312
+						)
2313
+					)
2314
+				);
2315
+				?>
2316 2316
             </div>
2317 2317
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2318 2318
         </div>
2319 2319
         <?php
2320
-    }
2321
-
2322
-
2323
-    private function _espresso_links_post_box()
2324
-    {
2325
-        // Hiding until we actually have content to put in here...
2326
-        // add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2327
-    }
2328
-
2329
-
2330
-    public function espresso_links_post_box()
2331
-    {
2332
-        // Hiding until we actually have content to put in here...
2333
-        // EEH_Template::display_template(
2334
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2335
-        // );
2336
-    }
2337
-
2338
-
2339
-    protected function _espresso_sponsors_post_box()
2340
-    {
2341
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2342
-            add_meta_box(
2343
-                'espresso_sponsors_post_box',
2344
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2345
-                [$this, 'espresso_sponsors_post_box'],
2346
-                $this->_wp_page_slug,
2347
-                'side'
2348
-            );
2349
-        }
2350
-    }
2351
-
2352
-
2353
-    public function espresso_sponsors_post_box()
2354
-    {
2355
-        EEH_Template::display_template(
2356
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2357
-        );
2358
-    }
2359
-
2360
-
2361
-    private function _publish_post_box()
2362
-    {
2363
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2364
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2365
-        // then we'll use that for the metabox label.
2366
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2367
-        if (! empty($this->_labels['publishbox'])) {
2368
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2369
-                : $this->_labels['publishbox'];
2370
-        } else {
2371
-            $box_label = esc_html__('Publish', 'event_espresso');
2372
-        }
2373
-        $box_label = apply_filters(
2374
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2375
-            $box_label,
2376
-            $this->_req_action,
2377
-            $this
2378
-        );
2379
-        add_meta_box(
2380
-            $meta_box_ref,
2381
-            $box_label,
2382
-            [$this, 'editor_overview'],
2383
-            $this->_current_screen->id,
2384
-            'side',
2385
-            'high'
2386
-        );
2387
-    }
2388
-
2389
-
2390
-    public function editor_overview()
2391
-    {
2392
-        // if we have extra content set let's add it in if not make sure its empty
2393
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2394
-            ? $this->_template_args['publish_box_extra_content']
2395
-            : '';
2396
-        echo EEH_Template::display_template(
2397
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2398
-            $this->_template_args,
2399
-            true
2400
-        );
2401
-    }
2402
-
2403
-
2404
-    /** end of globally available metaboxes section **/
2405
-
2406
-
2407
-    /**
2408
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2409
-     * protected method.
2410
-     *
2411
-     * @param string $name
2412
-     * @param int    $id
2413
-     * @param bool   $delete
2414
-     * @param string $save_close_redirect_URL
2415
-     * @param bool   $both_btns
2416
-     * @throws EE_Error
2417
-     * @throws InvalidArgumentException
2418
-     * @throws InvalidDataTypeException
2419
-     * @throws InvalidInterfaceException
2420
-     * @see   $this->_set_publish_post_box_vars for param details
2421
-     * @since 4.6.0
2422
-     */
2423
-    public function set_publish_post_box_vars(
2424
-        $name = '',
2425
-        $id = 0,
2426
-        $delete = false,
2427
-        $save_close_redirect_URL = '',
2428
-        $both_btns = true
2429
-    ) {
2430
-        $this->_set_publish_post_box_vars(
2431
-            $name,
2432
-            $id,
2433
-            $delete,
2434
-            $save_close_redirect_URL,
2435
-            $both_btns
2436
-        );
2437
-    }
2438
-
2439
-
2440
-    /**
2441
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2442
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2443
-     * save, and save and close buttons to work properly, then you will want to include a
2444
-     * values for the name and id arguments.
2445
-     *
2446
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2447
-     * @param int     $id                         id attached to the item published
2448
-     * @param string  $delete                     page route callback for the delete action
2449
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2450
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2451
-     *                                            the Save button
2452
-     * @throws EE_Error
2453
-     * @throws InvalidArgumentException
2454
-     * @throws InvalidDataTypeException
2455
-     * @throws InvalidInterfaceException
2456
-     * @todo  Add in validation for name/id arguments.
2457
-     */
2458
-    protected function _set_publish_post_box_vars(
2459
-        $name = '',
2460
-        $id = 0,
2461
-        $delete = '',
2462
-        $save_close_redirect_URL = '',
2463
-        $both_btns = true
2464
-    ) {
2465
-        // if Save & Close, use a custom redirect URL or default to the main page?
2466
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2467
-            ? $save_close_redirect_URL
2468
-            : $this->_admin_base_url;
2469
-        // create the Save & Close and Save buttons
2470
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2471
-        // if we have extra content set let's add it in if not make sure its empty
2472
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2473
-            ? $this->_template_args['publish_box_extra_content']
2474
-            : '';
2475
-        if ($delete && ! empty($id)) {
2476
-            // make sure we have a default if just true is sent.
2477
-            $delete           = ! empty($delete) ? $delete : 'delete';
2478
-            $delete_link_args = [$name => $id];
2479
-            $delete           = $this->get_action_link_or_button(
2480
-                $delete,
2481
-                $delete,
2482
-                $delete_link_args,
2483
-                'submitdelete deletion',
2484
-                '',
2485
-                false
2486
-            );
2487
-        }
2488
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2489
-        if (! empty($name) && ! empty($id)) {
2490
-            $hidden_field_arr[ $name ] = [
2491
-                'type'  => 'hidden',
2492
-                'value' => $id,
2493
-            ];
2494
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2495
-        } else {
2496
-            $hf = '';
2497
-        }
2498
-        // add hidden field
2499
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2500
-            ? $hf[ $name ]['field']
2501
-            : $hf;
2502
-    }
2503
-
2504
-
2505
-    /**
2506
-     * displays an error message to ppl who have javascript disabled
2507
-     *
2508
-     * @return void
2509
-     */
2510
-    private function _display_no_javascript_warning()
2511
-    {
2512
-        ?>
2320
+	}
2321
+
2322
+
2323
+	private function _espresso_links_post_box()
2324
+	{
2325
+		// Hiding until we actually have content to put in here...
2326
+		// add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2327
+	}
2328
+
2329
+
2330
+	public function espresso_links_post_box()
2331
+	{
2332
+		// Hiding until we actually have content to put in here...
2333
+		// EEH_Template::display_template(
2334
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2335
+		// );
2336
+	}
2337
+
2338
+
2339
+	protected function _espresso_sponsors_post_box()
2340
+	{
2341
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2342
+			add_meta_box(
2343
+				'espresso_sponsors_post_box',
2344
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2345
+				[$this, 'espresso_sponsors_post_box'],
2346
+				$this->_wp_page_slug,
2347
+				'side'
2348
+			);
2349
+		}
2350
+	}
2351
+
2352
+
2353
+	public function espresso_sponsors_post_box()
2354
+	{
2355
+		EEH_Template::display_template(
2356
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2357
+		);
2358
+	}
2359
+
2360
+
2361
+	private function _publish_post_box()
2362
+	{
2363
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2364
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2365
+		// then we'll use that for the metabox label.
2366
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2367
+		if (! empty($this->_labels['publishbox'])) {
2368
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2369
+				: $this->_labels['publishbox'];
2370
+		} else {
2371
+			$box_label = esc_html__('Publish', 'event_espresso');
2372
+		}
2373
+		$box_label = apply_filters(
2374
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2375
+			$box_label,
2376
+			$this->_req_action,
2377
+			$this
2378
+		);
2379
+		add_meta_box(
2380
+			$meta_box_ref,
2381
+			$box_label,
2382
+			[$this, 'editor_overview'],
2383
+			$this->_current_screen->id,
2384
+			'side',
2385
+			'high'
2386
+		);
2387
+	}
2388
+
2389
+
2390
+	public function editor_overview()
2391
+	{
2392
+		// if we have extra content set let's add it in if not make sure its empty
2393
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2394
+			? $this->_template_args['publish_box_extra_content']
2395
+			: '';
2396
+		echo EEH_Template::display_template(
2397
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2398
+			$this->_template_args,
2399
+			true
2400
+		);
2401
+	}
2402
+
2403
+
2404
+	/** end of globally available metaboxes section **/
2405
+
2406
+
2407
+	/**
2408
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2409
+	 * protected method.
2410
+	 *
2411
+	 * @param string $name
2412
+	 * @param int    $id
2413
+	 * @param bool   $delete
2414
+	 * @param string $save_close_redirect_URL
2415
+	 * @param bool   $both_btns
2416
+	 * @throws EE_Error
2417
+	 * @throws InvalidArgumentException
2418
+	 * @throws InvalidDataTypeException
2419
+	 * @throws InvalidInterfaceException
2420
+	 * @see   $this->_set_publish_post_box_vars for param details
2421
+	 * @since 4.6.0
2422
+	 */
2423
+	public function set_publish_post_box_vars(
2424
+		$name = '',
2425
+		$id = 0,
2426
+		$delete = false,
2427
+		$save_close_redirect_URL = '',
2428
+		$both_btns = true
2429
+	) {
2430
+		$this->_set_publish_post_box_vars(
2431
+			$name,
2432
+			$id,
2433
+			$delete,
2434
+			$save_close_redirect_URL,
2435
+			$both_btns
2436
+		);
2437
+	}
2438
+
2439
+
2440
+	/**
2441
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2442
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2443
+	 * save, and save and close buttons to work properly, then you will want to include a
2444
+	 * values for the name and id arguments.
2445
+	 *
2446
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2447
+	 * @param int     $id                         id attached to the item published
2448
+	 * @param string  $delete                     page route callback for the delete action
2449
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2450
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2451
+	 *                                            the Save button
2452
+	 * @throws EE_Error
2453
+	 * @throws InvalidArgumentException
2454
+	 * @throws InvalidDataTypeException
2455
+	 * @throws InvalidInterfaceException
2456
+	 * @todo  Add in validation for name/id arguments.
2457
+	 */
2458
+	protected function _set_publish_post_box_vars(
2459
+		$name = '',
2460
+		$id = 0,
2461
+		$delete = '',
2462
+		$save_close_redirect_URL = '',
2463
+		$both_btns = true
2464
+	) {
2465
+		// if Save & Close, use a custom redirect URL or default to the main page?
2466
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2467
+			? $save_close_redirect_URL
2468
+			: $this->_admin_base_url;
2469
+		// create the Save & Close and Save buttons
2470
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2471
+		// if we have extra content set let's add it in if not make sure its empty
2472
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2473
+			? $this->_template_args['publish_box_extra_content']
2474
+			: '';
2475
+		if ($delete && ! empty($id)) {
2476
+			// make sure we have a default if just true is sent.
2477
+			$delete           = ! empty($delete) ? $delete : 'delete';
2478
+			$delete_link_args = [$name => $id];
2479
+			$delete           = $this->get_action_link_or_button(
2480
+				$delete,
2481
+				$delete,
2482
+				$delete_link_args,
2483
+				'submitdelete deletion',
2484
+				'',
2485
+				false
2486
+			);
2487
+		}
2488
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2489
+		if (! empty($name) && ! empty($id)) {
2490
+			$hidden_field_arr[ $name ] = [
2491
+				'type'  => 'hidden',
2492
+				'value' => $id,
2493
+			];
2494
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2495
+		} else {
2496
+			$hf = '';
2497
+		}
2498
+		// add hidden field
2499
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2500
+			? $hf[ $name ]['field']
2501
+			: $hf;
2502
+	}
2503
+
2504
+
2505
+	/**
2506
+	 * displays an error message to ppl who have javascript disabled
2507
+	 *
2508
+	 * @return void
2509
+	 */
2510
+	private function _display_no_javascript_warning()
2511
+	{
2512
+		?>
2513 2513
         <noscript>
2514 2514
             <div id="no-js-message" class="error">
2515 2515
                 <p style="font-size:1.3em;">
2516 2516
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2517 2517
                     <?php esc_html_e(
2518
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2519
-                        'event_espresso'
2520
-                    ); ?>
2518
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2519
+						'event_espresso'
2520
+					); ?>
2521 2521
                 </p>
2522 2522
             </div>
2523 2523
         </noscript>
2524 2524
         <?php
2525
-    }
2526
-
2527
-
2528
-    /**
2529
-     * displays espresso success and/or error notices
2530
-     *
2531
-     * @return void
2532
-     */
2533
-    protected function _display_espresso_notices()
2534
-    {
2535
-        $notices = $this->_get_transient(true);
2536
-        echo wp_kses(stripslashes($notices), AllowedTags::getWithFormTags());
2537
-    }
2538
-
2539
-
2540
-    /**
2541
-     * spinny things pacify the masses
2542
-     *
2543
-     * @return void
2544
-     */
2545
-    protected function _add_admin_page_ajax_loading_img()
2546
-    {
2547
-        ?>
2525
+	}
2526
+
2527
+
2528
+	/**
2529
+	 * displays espresso success and/or error notices
2530
+	 *
2531
+	 * @return void
2532
+	 */
2533
+	protected function _display_espresso_notices()
2534
+	{
2535
+		$notices = $this->_get_transient(true);
2536
+		echo wp_kses(stripslashes($notices), AllowedTags::getWithFormTags());
2537
+	}
2538
+
2539
+
2540
+	/**
2541
+	 * spinny things pacify the masses
2542
+	 *
2543
+	 * @return void
2544
+	 */
2545
+	protected function _add_admin_page_ajax_loading_img()
2546
+	{
2547
+		?>
2548 2548
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2549 2549
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2550
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2550
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2551 2551
         </div>
2552 2552
         <?php
2553
-    }
2553
+	}
2554 2554
 
2555 2555
 
2556
-    /**
2557
-     * add admin page overlay for modal boxes
2558
-     *
2559
-     * @return void
2560
-     */
2561
-    protected function _add_admin_page_overlay()
2562
-    {
2563
-        ?>
2556
+	/**
2557
+	 * add admin page overlay for modal boxes
2558
+	 *
2559
+	 * @return void
2560
+	 */
2561
+	protected function _add_admin_page_overlay()
2562
+	{
2563
+		?>
2564 2564
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2565 2565
         <?php
2566
-    }
2567
-
2568
-
2569
-    /**
2570
-     * facade for add_meta_box
2571
-     *
2572
-     * @param string  $action        where the metabox gets displayed
2573
-     * @param string  $title         Title of Metabox (output in metabox header)
2574
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2575
-     *                               instead of the one created in here.
2576
-     * @param array   $callback_args an array of args supplied for the metabox
2577
-     * @param string  $column        what metabox column
2578
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2579
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2580
-     *                               created but just set our own callback for wp's add_meta_box.
2581
-     * @throws DomainException
2582
-     */
2583
-    public function _add_admin_page_meta_box(
2584
-        $action,
2585
-        $title,
2586
-        $callback,
2587
-        $callback_args,
2588
-        $column = 'normal',
2589
-        $priority = 'high',
2590
-        $create_func = true
2591
-    ) {
2592
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2593
-        // if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2594
-        if (empty($callback_args) && $create_func) {
2595
-            $callback_args = [
2596
-                'template_path' => $this->_template_path,
2597
-                'template_args' => $this->_template_args,
2598
-            ];
2599
-        }
2600
-        // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2601
-        $call_back_func = $create_func
2602
-            ? function ($post, $metabox) {
2603
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2604
-                echo EEH_Template::display_template(
2605
-                    $metabox['args']['template_path'],
2606
-                    $metabox['args']['template_args'],
2607
-                    true
2608
-                );
2609
-            }
2610
-            : $callback;
2611
-        add_meta_box(
2612
-            str_replace('_', '-', $action) . '-mbox',
2613
-            $title,
2614
-            $call_back_func,
2615
-            $this->_wp_page_slug,
2616
-            $column,
2617
-            $priority,
2618
-            $callback_args
2619
-        );
2620
-    }
2621
-
2622
-
2623
-    /**
2624
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2625
-     *
2626
-     * @throws DomainException
2627
-     * @throws EE_Error
2628
-     */
2629
-    public function display_admin_page_with_metabox_columns()
2630
-    {
2631
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2632
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2633
-            $this->_column_template_path,
2634
-            $this->_template_args,
2635
-            true
2636
-        );
2637
-        // the final wrapper
2638
-        $this->admin_page_wrapper();
2639
-    }
2640
-
2641
-
2642
-    /**
2643
-     * generates  HTML wrapper for an admin details page
2644
-     *
2645
-     * @return void
2646
-     * @throws EE_Error
2647
-     * @throws DomainException
2648
-     */
2649
-    public function display_admin_page_with_sidebar()
2650
-    {
2651
-        $this->_display_admin_page(true);
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2657
-     *
2658
-     * @return void
2659
-     * @throws EE_Error
2660
-     * @throws DomainException
2661
-     */
2662
-    public function display_admin_page_with_no_sidebar()
2663
-    {
2664
-        $this->_display_admin_page();
2665
-    }
2666
-
2667
-
2668
-    /**
2669
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2670
-     *
2671
-     * @return void
2672
-     * @throws EE_Error
2673
-     * @throws DomainException
2674
-     */
2675
-    public function display_about_admin_page()
2676
-    {
2677
-        $this->_display_admin_page(false, true);
2678
-    }
2679
-
2680
-
2681
-    /**
2682
-     * display_admin_page
2683
-     * contains the code for actually displaying an admin page
2684
-     *
2685
-     * @param boolean $sidebar true with sidebar, false without
2686
-     * @param boolean $about   use the about_admin_wrapper instead of the default.
2687
-     * @return void
2688
-     * @throws DomainException
2689
-     * @throws EE_Error
2690
-     */
2691
-    private function _display_admin_page($sidebar = false, $about = false)
2692
-    {
2693
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2694
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2695
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2696
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2697
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2698
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2699
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2700
-            ? 'poststuff'
2701
-            : 'espresso-default-admin';
2702
-        $template_path                                     = $sidebar
2703
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2704
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2705
-        if ($this->request->isAjax()) {
2706
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2707
-        }
2708
-        $template_path                                     = ! empty($this->_column_template_path)
2709
-            ? $this->_column_template_path : $template_path;
2710
-        $this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2711
-            ? $this->_template_args['admin_page_content']
2712
-            : '';
2713
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2714
-            ? $this->_template_args['before_admin_page_content']
2715
-            : '';
2716
-        $this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2717
-            ? $this->_template_args['after_admin_page_content']
2718
-            : '';
2719
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2720
-            $template_path,
2721
-            $this->_template_args,
2722
-            true
2723
-        );
2724
-        // the final template wrapper
2725
-        $this->admin_page_wrapper($about);
2726
-    }
2727
-
2728
-
2729
-    /**
2730
-     * This is used to display caf preview pages.
2731
-     *
2732
-     * @param string $utm_campaign_source what is the key used for google analytics link
2733
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2734
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2735
-     * @return void
2736
-     * @throws DomainException
2737
-     * @throws EE_Error
2738
-     * @throws InvalidArgumentException
2739
-     * @throws InvalidDataTypeException
2740
-     * @throws InvalidInterfaceException
2741
-     * @since 4.3.2
2742
-     */
2743
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2744
-    {
2745
-        // let's generate a default preview action button if there isn't one already present.
2746
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2747
-            'Upgrade to Event Espresso 4 Right Now',
2748
-            'event_espresso'
2749
-        );
2750
-        $buy_now_url                                   = add_query_arg(
2751
-            [
2752
-                'ee_ver'       => 'ee4',
2753
-                'utm_source'   => 'ee4_plugin_admin',
2754
-                'utm_medium'   => 'link',
2755
-                'utm_campaign' => $utm_campaign_source,
2756
-                'utm_content'  => 'buy_now_button',
2757
-            ],
2758
-            'https://eventespresso.com/pricing/'
2759
-        );
2760
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2761
-            ? $this->get_action_link_or_button(
2762
-                '',
2763
-                'buy_now',
2764
-                [],
2765
-                'button-primary button-large',
2766
-                esc_url_raw($buy_now_url),
2767
-                true
2768
-            )
2769
-            : $this->_template_args['preview_action_button'];
2770
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2771
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2772
-            $this->_template_args,
2773
-            true
2774
-        );
2775
-        $this->_display_admin_page($display_sidebar);
2776
-    }
2777
-
2778
-
2779
-    /**
2780
-     * display_admin_list_table_page_with_sidebar
2781
-     * generates HTML wrapper for an admin_page with list_table
2782
-     *
2783
-     * @return void
2784
-     * @throws EE_Error
2785
-     * @throws DomainException
2786
-     */
2787
-    public function display_admin_list_table_page_with_sidebar()
2788
-    {
2789
-        $this->_display_admin_list_table_page(true);
2790
-    }
2791
-
2792
-
2793
-    /**
2794
-     * display_admin_list_table_page_with_no_sidebar
2795
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2796
-     *
2797
-     * @return void
2798
-     * @throws EE_Error
2799
-     * @throws DomainException
2800
-     */
2801
-    public function display_admin_list_table_page_with_no_sidebar()
2802
-    {
2803
-        $this->_display_admin_list_table_page();
2804
-    }
2805
-
2806
-
2807
-    /**
2808
-     * generates html wrapper for an admin_list_table page
2809
-     *
2810
-     * @param boolean $sidebar whether to display with sidebar or not.
2811
-     * @return void
2812
-     * @throws DomainException
2813
-     * @throws EE_Error
2814
-     */
2815
-    private function _display_admin_list_table_page($sidebar = false)
2816
-    {
2817
-        // setup search attributes
2818
-        $this->_set_search_attributes();
2819
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2820
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2821
-        $this->_template_args['table_url']        = $this->request->isAjax()
2822
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2823
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2824
-        $this->_template_args['list_table']       = $this->_list_table_object;
2825
-        $this->_template_args['current_route']    = $this->_req_action;
2826
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2827
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2828
-        if (! empty($ajax_sorting_callback)) {
2829
-            $sortable_list_table_form_fields = wp_nonce_field(
2830
-                $ajax_sorting_callback . '_nonce',
2831
-                $ajax_sorting_callback . '_nonce',
2832
-                false,
2833
-                false
2834
-            );
2835
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2836
-                                                . $this->page_slug
2837
-                                                . '" />';
2838
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2839
-                                                . $ajax_sorting_callback
2840
-                                                . '" />';
2841
-        } else {
2842
-            $sortable_list_table_form_fields = '';
2843
-        }
2844
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2845
-        $hidden_form_fields                                      =
2846
-            isset($this->_template_args['list_table_hidden_fields'])
2847
-                ? $this->_template_args['list_table_hidden_fields']
2848
-                : '';
2849
-
2850
-        $nonce_ref          = $this->_req_action . '_nonce';
2851
-        $hidden_form_fields .= '
2566
+	}
2567
+
2568
+
2569
+	/**
2570
+	 * facade for add_meta_box
2571
+	 *
2572
+	 * @param string  $action        where the metabox gets displayed
2573
+	 * @param string  $title         Title of Metabox (output in metabox header)
2574
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2575
+	 *                               instead of the one created in here.
2576
+	 * @param array   $callback_args an array of args supplied for the metabox
2577
+	 * @param string  $column        what metabox column
2578
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2579
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2580
+	 *                               created but just set our own callback for wp's add_meta_box.
2581
+	 * @throws DomainException
2582
+	 */
2583
+	public function _add_admin_page_meta_box(
2584
+		$action,
2585
+		$title,
2586
+		$callback,
2587
+		$callback_args,
2588
+		$column = 'normal',
2589
+		$priority = 'high',
2590
+		$create_func = true
2591
+	) {
2592
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2593
+		// if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2594
+		if (empty($callback_args) && $create_func) {
2595
+			$callback_args = [
2596
+				'template_path' => $this->_template_path,
2597
+				'template_args' => $this->_template_args,
2598
+			];
2599
+		}
2600
+		// if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2601
+		$call_back_func = $create_func
2602
+			? function ($post, $metabox) {
2603
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2604
+				echo EEH_Template::display_template(
2605
+					$metabox['args']['template_path'],
2606
+					$metabox['args']['template_args'],
2607
+					true
2608
+				);
2609
+			}
2610
+			: $callback;
2611
+		add_meta_box(
2612
+			str_replace('_', '-', $action) . '-mbox',
2613
+			$title,
2614
+			$call_back_func,
2615
+			$this->_wp_page_slug,
2616
+			$column,
2617
+			$priority,
2618
+			$callback_args
2619
+		);
2620
+	}
2621
+
2622
+
2623
+	/**
2624
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2625
+	 *
2626
+	 * @throws DomainException
2627
+	 * @throws EE_Error
2628
+	 */
2629
+	public function display_admin_page_with_metabox_columns()
2630
+	{
2631
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2632
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2633
+			$this->_column_template_path,
2634
+			$this->_template_args,
2635
+			true
2636
+		);
2637
+		// the final wrapper
2638
+		$this->admin_page_wrapper();
2639
+	}
2640
+
2641
+
2642
+	/**
2643
+	 * generates  HTML wrapper for an admin details page
2644
+	 *
2645
+	 * @return void
2646
+	 * @throws EE_Error
2647
+	 * @throws DomainException
2648
+	 */
2649
+	public function display_admin_page_with_sidebar()
2650
+	{
2651
+		$this->_display_admin_page(true);
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2657
+	 *
2658
+	 * @return void
2659
+	 * @throws EE_Error
2660
+	 * @throws DomainException
2661
+	 */
2662
+	public function display_admin_page_with_no_sidebar()
2663
+	{
2664
+		$this->_display_admin_page();
2665
+	}
2666
+
2667
+
2668
+	/**
2669
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2670
+	 *
2671
+	 * @return void
2672
+	 * @throws EE_Error
2673
+	 * @throws DomainException
2674
+	 */
2675
+	public function display_about_admin_page()
2676
+	{
2677
+		$this->_display_admin_page(false, true);
2678
+	}
2679
+
2680
+
2681
+	/**
2682
+	 * display_admin_page
2683
+	 * contains the code for actually displaying an admin page
2684
+	 *
2685
+	 * @param boolean $sidebar true with sidebar, false without
2686
+	 * @param boolean $about   use the about_admin_wrapper instead of the default.
2687
+	 * @return void
2688
+	 * @throws DomainException
2689
+	 * @throws EE_Error
2690
+	 */
2691
+	private function _display_admin_page($sidebar = false, $about = false)
2692
+	{
2693
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2694
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2695
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2696
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2697
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2698
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2699
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2700
+			? 'poststuff'
2701
+			: 'espresso-default-admin';
2702
+		$template_path                                     = $sidebar
2703
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2704
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2705
+		if ($this->request->isAjax()) {
2706
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2707
+		}
2708
+		$template_path                                     = ! empty($this->_column_template_path)
2709
+			? $this->_column_template_path : $template_path;
2710
+		$this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2711
+			? $this->_template_args['admin_page_content']
2712
+			: '';
2713
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2714
+			? $this->_template_args['before_admin_page_content']
2715
+			: '';
2716
+		$this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2717
+			? $this->_template_args['after_admin_page_content']
2718
+			: '';
2719
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2720
+			$template_path,
2721
+			$this->_template_args,
2722
+			true
2723
+		);
2724
+		// the final template wrapper
2725
+		$this->admin_page_wrapper($about);
2726
+	}
2727
+
2728
+
2729
+	/**
2730
+	 * This is used to display caf preview pages.
2731
+	 *
2732
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2733
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2734
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2735
+	 * @return void
2736
+	 * @throws DomainException
2737
+	 * @throws EE_Error
2738
+	 * @throws InvalidArgumentException
2739
+	 * @throws InvalidDataTypeException
2740
+	 * @throws InvalidInterfaceException
2741
+	 * @since 4.3.2
2742
+	 */
2743
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2744
+	{
2745
+		// let's generate a default preview action button if there isn't one already present.
2746
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2747
+			'Upgrade to Event Espresso 4 Right Now',
2748
+			'event_espresso'
2749
+		);
2750
+		$buy_now_url                                   = add_query_arg(
2751
+			[
2752
+				'ee_ver'       => 'ee4',
2753
+				'utm_source'   => 'ee4_plugin_admin',
2754
+				'utm_medium'   => 'link',
2755
+				'utm_campaign' => $utm_campaign_source,
2756
+				'utm_content'  => 'buy_now_button',
2757
+			],
2758
+			'https://eventespresso.com/pricing/'
2759
+		);
2760
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2761
+			? $this->get_action_link_or_button(
2762
+				'',
2763
+				'buy_now',
2764
+				[],
2765
+				'button-primary button-large',
2766
+				esc_url_raw($buy_now_url),
2767
+				true
2768
+			)
2769
+			: $this->_template_args['preview_action_button'];
2770
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2771
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2772
+			$this->_template_args,
2773
+			true
2774
+		);
2775
+		$this->_display_admin_page($display_sidebar);
2776
+	}
2777
+
2778
+
2779
+	/**
2780
+	 * display_admin_list_table_page_with_sidebar
2781
+	 * generates HTML wrapper for an admin_page with list_table
2782
+	 *
2783
+	 * @return void
2784
+	 * @throws EE_Error
2785
+	 * @throws DomainException
2786
+	 */
2787
+	public function display_admin_list_table_page_with_sidebar()
2788
+	{
2789
+		$this->_display_admin_list_table_page(true);
2790
+	}
2791
+
2792
+
2793
+	/**
2794
+	 * display_admin_list_table_page_with_no_sidebar
2795
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2796
+	 *
2797
+	 * @return void
2798
+	 * @throws EE_Error
2799
+	 * @throws DomainException
2800
+	 */
2801
+	public function display_admin_list_table_page_with_no_sidebar()
2802
+	{
2803
+		$this->_display_admin_list_table_page();
2804
+	}
2805
+
2806
+
2807
+	/**
2808
+	 * generates html wrapper for an admin_list_table page
2809
+	 *
2810
+	 * @param boolean $sidebar whether to display with sidebar or not.
2811
+	 * @return void
2812
+	 * @throws DomainException
2813
+	 * @throws EE_Error
2814
+	 */
2815
+	private function _display_admin_list_table_page($sidebar = false)
2816
+	{
2817
+		// setup search attributes
2818
+		$this->_set_search_attributes();
2819
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2820
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2821
+		$this->_template_args['table_url']        = $this->request->isAjax()
2822
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2823
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2824
+		$this->_template_args['list_table']       = $this->_list_table_object;
2825
+		$this->_template_args['current_route']    = $this->_req_action;
2826
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2827
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2828
+		if (! empty($ajax_sorting_callback)) {
2829
+			$sortable_list_table_form_fields = wp_nonce_field(
2830
+				$ajax_sorting_callback . '_nonce',
2831
+				$ajax_sorting_callback . '_nonce',
2832
+				false,
2833
+				false
2834
+			);
2835
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2836
+												. $this->page_slug
2837
+												. '" />';
2838
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2839
+												. $ajax_sorting_callback
2840
+												. '" />';
2841
+		} else {
2842
+			$sortable_list_table_form_fields = '';
2843
+		}
2844
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2845
+		$hidden_form_fields                                      =
2846
+			isset($this->_template_args['list_table_hidden_fields'])
2847
+				? $this->_template_args['list_table_hidden_fields']
2848
+				: '';
2849
+
2850
+		$nonce_ref          = $this->_req_action . '_nonce';
2851
+		$hidden_form_fields .= '
2852 2852
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2853 2853
 
2854
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2855
-        // display message about search results?
2856
-        $search = $this->request->getRequestParam('s');
2857
-        $this->_template_args['before_list_table'] .= ! empty($search)
2858
-            ? '<p class="ee-search-results">' . sprintf(
2859
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2860
-                trim($search, '%')
2861
-            ) . '</p>'
2862
-            : '';
2863
-        // filter before_list_table template arg
2864
-        $this->_template_args['before_list_table'] = apply_filters(
2865
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2866
-            $this->_template_args['before_list_table'],
2867
-            $this->page_slug,
2868
-            $this->request->requestParams(),
2869
-            $this->_req_action
2870
-        );
2871
-        // convert to array and filter again
2872
-        // arrays are easier to inject new items in a specific location,
2873
-        // but would not be backwards compatible, so we have to add a new filter
2874
-        $this->_template_args['before_list_table'] = implode(
2875
-            " \n",
2876
-            (array) apply_filters(
2877
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2878
-                (array) $this->_template_args['before_list_table'],
2879
-                $this->page_slug,
2880
-                $this->request->requestParams(),
2881
-                $this->_req_action
2882
-            )
2883
-        );
2884
-        // filter after_list_table template arg
2885
-        $this->_template_args['after_list_table'] = apply_filters(
2886
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2887
-            $this->_template_args['after_list_table'],
2888
-            $this->page_slug,
2889
-            $this->request->requestParams(),
2890
-            $this->_req_action
2891
-        );
2892
-        // convert to array and filter again
2893
-        // arrays are easier to inject new items in a specific location,
2894
-        // but would not be backwards compatible, so we have to add a new filter
2895
-        $this->_template_args['after_list_table']   = implode(
2896
-            " \n",
2897
-            (array) apply_filters(
2898
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2899
-                (array) $this->_template_args['after_list_table'],
2900
-                $this->page_slug,
2901
-                $this->request->requestParams(),
2902
-                $this->_req_action
2903
-            )
2904
-        );
2905
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2906
-            $template_path,
2907
-            $this->_template_args,
2908
-            true
2909
-        );
2910
-        // the final template wrapper
2911
-        if ($sidebar) {
2912
-            $this->display_admin_page_with_sidebar();
2913
-        } else {
2914
-            $this->display_admin_page_with_no_sidebar();
2915
-        }
2916
-    }
2917
-
2918
-
2919
-    /**
2920
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
2921
-     * html string for the legend.
2922
-     * $items are expected in an array in the following format:
2923
-     * $legend_items = array(
2924
-     *        'item_id' => array(
2925
-     *            'icon' => 'http://url_to_icon_being_described.png',
2926
-     *            'desc' => esc_html__('localized description of item');
2927
-     *        )
2928
-     * );
2929
-     *
2930
-     * @param array $items see above for format of array
2931
-     * @return string html string of legend
2932
-     * @throws DomainException
2933
-     */
2934
-    protected function _display_legend($items)
2935
-    {
2936
-        $this->_template_args['items'] = apply_filters(
2937
-            'FHEE__EE_Admin_Page___display_legend__items',
2938
-            (array) $items,
2939
-            $this
2940
-        );
2941
-        return EEH_Template::display_template(
2942
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
2943
-            $this->_template_args,
2944
-            true
2945
-        );
2946
-    }
2947
-
2948
-
2949
-    /**
2950
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2951
-     * The returned json object is created from an array in the following format:
2952
-     * array(
2953
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2954
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
2955
-     *  'notices' => '', // - contains any EE_Error formatted notices
2956
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
2957
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
2958
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
2959
-     *  that might be included in here)
2960
-     * )
2961
-     * The json object is populated by whatever is set in the $_template_args property.
2962
-     *
2963
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
2964
-     *                                 instead of displayed.
2965
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
2966
-     * @return void
2967
-     * @throws EE_Error
2968
-     */
2969
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
2970
-    {
2971
-        // make sure any EE_Error notices have been handled.
2972
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
2973
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
2974
-        unset($this->_template_args['data']);
2975
-        $json = [
2976
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2977
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2978
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2979
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2980
-            'notices'   => EE_Error::get_notices(),
2981
-            'content'   => isset($this->_template_args['admin_page_content'])
2982
-                ? $this->_template_args['admin_page_content'] : '',
2983
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
2984
-            'isEEajax'  => true
2985
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2986
-        ];
2987
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
2988
-        if (null === error_get_last() || ! headers_sent()) {
2989
-            header('Content-Type: application/json; charset=UTF-8');
2990
-        }
2991
-        echo wp_json_encode($json);
2992
-        exit();
2993
-    }
2994
-
2995
-
2996
-    /**
2997
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2998
-     *
2999
-     * @return void
3000
-     * @throws EE_Error
3001
-     */
3002
-    public function return_json()
3003
-    {
3004
-        if ($this->request->isAjax()) {
3005
-            $this->_return_json();
3006
-        } else {
3007
-            throw new EE_Error(
3008
-                sprintf(
3009
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3010
-                    __FUNCTION__
3011
-                )
3012
-            );
3013
-        }
3014
-    }
3015
-
3016
-
3017
-    /**
3018
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3019
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3020
-     *
3021
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3022
-     */
3023
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3024
-    {
3025
-        $this->_hook_obj = $hook_obj;
3026
-    }
3027
-
3028
-
3029
-    /**
3030
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3031
-     *
3032
-     * @param boolean $about whether to use the special about page wrapper or default.
3033
-     * @return void
3034
-     * @throws DomainException
3035
-     * @throws EE_Error
3036
-     */
3037
-    public function admin_page_wrapper($about = false)
3038
-    {
3039
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3040
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3041
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3042
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3043
-
3044
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3045
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3046
-            isset($this->_template_args['before_admin_page_content'])
3047
-                ? $this->_template_args['before_admin_page_content']
3048
-                : ''
3049
-        );
3050
-
3051
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3052
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3053
-            isset($this->_template_args['after_admin_page_content'])
3054
-                ? $this->_template_args['after_admin_page_content']
3055
-                : ''
3056
-        );
3057
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3058
-
3059
-        if ($this->request->isAjax()) {
3060
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3061
-                // $template_path,
3062
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3063
-                $this->_template_args,
3064
-                true
3065
-            );
3066
-            $this->_return_json();
3067
-        }
3068
-        // load settings page wrapper template
3069
-        $template_path = $about
3070
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3071
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3072
-
3073
-        EEH_Template::display_template($template_path, $this->_template_args);
3074
-    }
3075
-
3076
-
3077
-    /**
3078
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3079
-     *
3080
-     * @return string html
3081
-     * @throws EE_Error
3082
-     */
3083
-    protected function _get_main_nav_tabs()
3084
-    {
3085
-        // let's generate the html using the EEH_Tabbed_Content helper.
3086
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3087
-        // (rather than setting in the page_routes array)
3088
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3089
-    }
3090
-
3091
-
3092
-    /**
3093
-     *        sort nav tabs
3094
-     *
3095
-     * @param $a
3096
-     * @param $b
3097
-     * @return int
3098
-     */
3099
-    private function _sort_nav_tabs($a, $b)
3100
-    {
3101
-        if ($a['order'] === $b['order']) {
3102
-            return 0;
3103
-        }
3104
-        return ($a['order'] < $b['order']) ? -1 : 1;
3105
-    }
3106
-
3107
-
3108
-    /**
3109
-     *    generates HTML for the forms used on admin pages
3110
-     *
3111
-     * @param array  $input_vars   - array of input field details
3112
-     * @param string $generator    (options are 'string' or 'array', basically use this to indicate which generator to
3113
-     *                             use)
3114
-     * @param bool   $id
3115
-     * @return array|string
3116
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3117
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3118
-     */
3119
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3120
-    {
3121
-        return $generator === 'string'
3122
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3123
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3124
-    }
3125
-
3126
-
3127
-    /**
3128
-     * generates the "Save" and "Save & Close" buttons for edit forms
3129
-     *
3130
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3131
-     *                                   Close" button.
3132
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3133
-     *                                   'Save', [1] => 'save & close')
3134
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3135
-     *                                   via the "name" value in the button).  We can also use this to just dump
3136
-     *                                   default actions by submitting some other value.
3137
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3138
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3139
-     *                                   close (normal form handling).
3140
-     */
3141
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3142
-    {
3143
-        // make sure $text and $actions are in an array
3144
-        $text          = (array) $text;
3145
-        $actions       = (array) $actions;
3146
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3147
-        $button_text   = ! empty($text)
3148
-            ? $text
3149
-            : [
3150
-                esc_html__('Save', 'event_espresso'),
3151
-                esc_html__('Save and Close', 'event_espresso'),
3152
-            ];
3153
-        $default_names = ['save', 'save_and_close'];
3154
-        $buttons = '';
3155
-        foreach ($button_text as $key => $button) {
3156
-            $ref     = $default_names[ $key ];
3157
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3158
-            $buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3159
-                        . 'value="' . $button . '" name="' . $name . '" '
3160
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3161
-            if (! $both) {
3162
-                break;
3163
-            }
3164
-        }
3165
-        // add in a hidden index for the current page (so save and close redirects properly)
3166
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3167
-                   . $referrer_url
3168
-                   . '" />';
3169
-        $this->_template_args['save_buttons'] = $buttons;
3170
-    }
3171
-
3172
-
3173
-    /**
3174
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3175
-     *
3176
-     * @param string $route
3177
-     * @param array  $additional_hidden_fields
3178
-     * @see   $this->_set_add_edit_form_tags() for details on params
3179
-     * @since 4.6.0
3180
-     */
3181
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3182
-    {
3183
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3184
-    }
3185
-
3186
-
3187
-    /**
3188
-     * set form open and close tags on add/edit pages.
3189
-     *
3190
-     * @param string $route                    the route you want the form to direct to
3191
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3192
-     * @return void
3193
-     */
3194
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3195
-    {
3196
-        if (empty($route)) {
3197
-            $user_msg = esc_html__(
3198
-                'An error occurred. No action was set for this page\'s form.',
3199
-                'event_espresso'
3200
-            );
3201
-            $dev_msg  = $user_msg . "\n"
3202
-                        . sprintf(
3203
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3204
-                            __FUNCTION__,
3205
-                            __CLASS__
3206
-                        );
3207
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3208
-        }
3209
-        // open form
3210
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3211
-                                                             . $this->_admin_base_url
3212
-                                                             . '" id="'
3213
-                                                             . $route
3214
-                                                             . '_event_form" >';
3215
-        // add nonce
3216
-        $nonce                                             =
3217
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3218
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3219
-        // add REQUIRED form action
3220
-        $hidden_fields = [
3221
-            'action' => ['type' => 'hidden', 'value' => $route],
3222
-        ];
3223
-        // merge arrays
3224
-        $hidden_fields = is_array($additional_hidden_fields)
3225
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3226
-            : $hidden_fields;
3227
-        // generate form fields
3228
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3229
-        // add fields to form
3230
-        foreach ((array) $form_fields as $form_field) {
3231
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3232
-        }
3233
-        // close form
3234
-        $this->_template_args['after_admin_page_content'] = '</form>';
3235
-    }
3236
-
3237
-
3238
-    /**
3239
-     * Public Wrapper for _redirect_after_action() method since its
3240
-     * discovered it would be useful for external code to have access.
3241
-     *
3242
-     * @param bool   $success
3243
-     * @param string $what
3244
-     * @param string $action_desc
3245
-     * @param array  $query_args
3246
-     * @param bool   $override_overwrite
3247
-     * @throws EE_Error
3248
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3249
-     * @since 4.5.0
3250
-     */
3251
-    public function redirect_after_action(
3252
-        $success = false,
3253
-        $what = 'item',
3254
-        $action_desc = 'processed',
3255
-        $query_args = [],
3256
-        $override_overwrite = false
3257
-    ) {
3258
-        $this->_redirect_after_action(
3259
-            $success,
3260
-            $what,
3261
-            $action_desc,
3262
-            $query_args,
3263
-            $override_overwrite
3264
-        );
3265
-    }
3266
-
3267
-
3268
-    /**
3269
-     * Helper method for merging existing request data with the returned redirect url.
3270
-     *
3271
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3272
-     * filters are still applied.
3273
-     *
3274
-     * @param array $new_route_data
3275
-     * @return array
3276
-     */
3277
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3278
-    {
3279
-        foreach ($this->request->requestParams() as $ref => $value) {
3280
-            // unset nonces
3281
-            if (strpos($ref, 'nonce') !== false) {
3282
-                $this->request->unSetRequestParam($ref);
3283
-                continue;
3284
-            }
3285
-            // urlencode values.
3286
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3287
-            $this->request->setRequestParam($ref, $value);
3288
-        }
3289
-        return array_merge($this->request->requestParams(), $new_route_data);
3290
-    }
3291
-
3292
-
3293
-    /**
3294
-     *    _redirect_after_action
3295
-     *
3296
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3297
-     * @param string $what               - what the action was performed on
3298
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3299
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3300
-     *                                   action is completed
3301
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3302
-     *                                   override this so that they show.
3303
-     * @return void
3304
-     * @throws EE_Error
3305
-     */
3306
-    protected function _redirect_after_action(
3307
-        $success = 0,
3308
-        $what = 'item',
3309
-        $action_desc = 'processed',
3310
-        $query_args = [],
3311
-        $override_overwrite = false
3312
-    ) {
3313
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3314
-        // class name for actions/filters.
3315
-        $classname = get_class($this);
3316
-        // set redirect url.
3317
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3318
-        // otherwise we go with whatever is set as the _admin_base_url
3319
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3320
-        $notices      = EE_Error::get_notices(false);
3321
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3322
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3323
-            EE_Error::overwrite_success();
3324
-        }
3325
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3326
-            // how many records affected ? more than one record ? or just one ?
3327
-            if ($success > 1) {
3328
-                // set plural msg
3329
-                EE_Error::add_success(
3330
-                    sprintf(
3331
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3332
-                        $what,
3333
-                        $action_desc
3334
-                    ),
3335
-                    __FILE__,
3336
-                    __FUNCTION__,
3337
-                    __LINE__
3338
-                );
3339
-            } elseif ($success === 1) {
3340
-                // set singular msg
3341
-                EE_Error::add_success(
3342
-                    sprintf(
3343
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3344
-                        $what,
3345
-                        $action_desc
3346
-                    ),
3347
-                    __FILE__,
3348
-                    __FUNCTION__,
3349
-                    __LINE__
3350
-                );
3351
-            }
3352
-        }
3353
-        // check that $query_args isn't something crazy
3354
-        if (! is_array($query_args)) {
3355
-            $query_args = [];
3356
-        }
3357
-        /**
3358
-         * Allow injecting actions before the query_args are modified for possible different
3359
-         * redirections on save and close actions
3360
-         *
3361
-         * @param array $query_args       The original query_args array coming into the
3362
-         *                                method.
3363
-         * @since 4.2.0
3364
-         */
3365
-        do_action(
3366
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3367
-            $query_args
3368
-        );
3369
-        // calculate where we're going (if we have a "save and close" button pushed)
3370
-
3371
-        if (
3372
-            $this->request->requestParamIsSet('save_and_close')
3373
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3374
-        ) {
3375
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3376
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3377
-            // regenerate query args array from referrer URL
3378
-            parse_str($parsed_url['query'], $query_args);
3379
-            // correct page and action will be in the query args now
3380
-            $redirect_url = admin_url('admin.php');
3381
-        }
3382
-        // merge any default query_args set in _default_route_query_args property
3383
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3384
-            $args_to_merge = [];
3385
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3386
-                // is there a wp_referer array in our _default_route_query_args property?
3387
-                if ($query_param === 'wp_referer') {
3388
-                    $query_value = (array) $query_value;
3389
-                    foreach ($query_value as $reference => $value) {
3390
-                        if (strpos($reference, 'nonce') !== false) {
3391
-                            continue;
3392
-                        }
3393
-                        // finally we will override any arguments in the referer with
3394
-                        // what might be set on the _default_route_query_args array.
3395
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3396
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3397
-                        } else {
3398
-                            $args_to_merge[ $reference ] = urlencode($value);
3399
-                        }
3400
-                    }
3401
-                    continue;
3402
-                }
3403
-                $args_to_merge[ $query_param ] = $query_value;
3404
-            }
3405
-            // now let's merge these arguments but override with what was specifically sent in to the
3406
-            // redirect.
3407
-            $query_args = array_merge($args_to_merge, $query_args);
3408
-        }
3409
-        $this->_process_notices($query_args);
3410
-        // generate redirect url
3411
-        // if redirecting to anything other than the main page, add a nonce
3412
-        if (isset($query_args['action'])) {
3413
-            // manually generate wp_nonce and merge that with the query vars
3414
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3415
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3416
-        }
3417
-        // we're adding some hooks and filters in here for processing any things just before redirects
3418
-        // (example: an admin page has done an insert or update and we want to run something after that).
3419
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3420
-        $redirect_url = apply_filters(
3421
-            'FHEE_redirect_' . $classname . $this->_req_action,
3422
-            self::add_query_args_and_nonce($query_args, $redirect_url),
3423
-            $query_args
3424
-        );
3425
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3426
-        if ($this->request->isAjax()) {
3427
-            $default_data                    = [
3428
-                'close'        => true,
3429
-                'redirect_url' => $redirect_url,
3430
-                'where'        => 'main',
3431
-                'what'         => 'append',
3432
-            ];
3433
-            $this->_template_args['success'] = $success;
3434
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3435
-                $default_data,
3436
-                $this->_template_args['data']
3437
-            ) : $default_data;
3438
-            $this->_return_json();
3439
-        }
3440
-        wp_safe_redirect($redirect_url);
3441
-        exit();
3442
-    }
3443
-
3444
-
3445
-    /**
3446
-     * process any notices before redirecting (or returning ajax request)
3447
-     * This method sets the $this->_template_args['notices'] attribute;
3448
-     *
3449
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3450
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3451
-     *                                  page_routes haven't been defined yet.
3452
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3453
-     *                                  still save a transient for the notice.
3454
-     * @return void
3455
-     * @throws EE_Error
3456
-     */
3457
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3458
-    {
3459
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3460
-        if ($this->request->isAjax()) {
3461
-            $notices = EE_Error::get_notices(false);
3462
-            if (empty($this->_template_args['success'])) {
3463
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3464
-            }
3465
-            if (empty($this->_template_args['errors'])) {
3466
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3467
-            }
3468
-            if (empty($this->_template_args['attention'])) {
3469
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3470
-            }
3471
-        }
3472
-        $this->_template_args['notices'] = EE_Error::get_notices();
3473
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3474
-        if (! $this->request->isAjax() || $sticky_notices) {
3475
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3476
-            $this->_add_transient(
3477
-                $route,
3478
-                $this->_template_args['notices'],
3479
-                true,
3480
-                $skip_route_verify
3481
-            );
3482
-        }
3483
-    }
3484
-
3485
-
3486
-    /**
3487
-     * get_action_link_or_button
3488
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3489
-     *
3490
-     * @param string $action        use this to indicate which action the url is generated with.
3491
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3492
-     *                              property.
3493
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3494
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3495
-     * @param string $base_url      If this is not provided
3496
-     *                              the _admin_base_url will be used as the default for the button base_url.
3497
-     *                              Otherwise this value will be used.
3498
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3499
-     * @return string
3500
-     * @throws InvalidArgumentException
3501
-     * @throws InvalidInterfaceException
3502
-     * @throws InvalidDataTypeException
3503
-     * @throws EE_Error
3504
-     */
3505
-    public function get_action_link_or_button(
3506
-        $action,
3507
-        $type = 'add',
3508
-        $extra_request = [],
3509
-        $class = 'button button--primary',
3510
-        $base_url = '',
3511
-        $exclude_nonce = false
3512
-    ) {
3513
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3514
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3515
-            throw new EE_Error(
3516
-                sprintf(
3517
-                    esc_html__(
3518
-                        'There is no page route for given action for the button.  This action was given: %s',
3519
-                        'event_espresso'
3520
-                    ),
3521
-                    $action
3522
-                )
3523
-            );
3524
-        }
3525
-        if (! isset($this->_labels['buttons'][ $type ])) {
3526
-            throw new EE_Error(
3527
-                sprintf(
3528
-                    esc_html__(
3529
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3530
-                        'event_espresso'
3531
-                    ),
3532
-                    $type
3533
-                )
3534
-            );
3535
-        }
3536
-        // finally check user access for this button.
3537
-        $has_access = $this->check_user_access($action, true);
3538
-        if (! $has_access) {
3539
-            return '';
3540
-        }
3541
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3542
-        $query_args = [
3543
-            'action' => $action,
3544
-        ];
3545
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3546
-        if (! empty($extra_request)) {
3547
-            $query_args = array_merge($extra_request, $query_args);
3548
-        }
3549
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3550
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3551
-    }
3552
-
3553
-
3554
-    /**
3555
-     * _per_page_screen_option
3556
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3557
-     *
3558
-     * @return void
3559
-     * @throws InvalidArgumentException
3560
-     * @throws InvalidInterfaceException
3561
-     * @throws InvalidDataTypeException
3562
-     */
3563
-    protected function _per_page_screen_option()
3564
-    {
3565
-        $option = 'per_page';
3566
-        $args   = [
3567
-            'label'   => apply_filters(
3568
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3569
-                $this->_admin_page_title,
3570
-                $this
3571
-            ),
3572
-            'default' => (int) apply_filters(
3573
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3574
-                20
3575
-            ),
3576
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3577
-        ];
3578
-        // ONLY add the screen option if the user has access to it.
3579
-        if ($this->check_user_access($this->_current_view, true)) {
3580
-            add_screen_option($option, $args);
3581
-        }
3582
-    }
3583
-
3584
-
3585
-    /**
3586
-     * set_per_page_screen_option
3587
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3588
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3589
-     * admin_menu.
3590
-     *
3591
-     * @return void
3592
-     */
3593
-    private function _set_per_page_screen_options()
3594
-    {
3595
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3596
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3597
-            if (! $user = wp_get_current_user()) {
3598
-                return;
3599
-            }
3600
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3601
-            if (! $option) {
3602
-                return;
3603
-            }
3604
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3605
-            $map_option = $option;
3606
-            $option     = str_replace('-', '_', $option);
3607
-            switch ($map_option) {
3608
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3609
-                    $max_value = apply_filters(
3610
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3611
-                        999,
3612
-                        $this->_current_page,
3613
-                        $this->_current_view
3614
-                    );
3615
-                    if ($value < 1) {
3616
-                        return;
3617
-                    }
3618
-                    $value = min($value, $max_value);
3619
-                    break;
3620
-                default:
3621
-                    $value = apply_filters(
3622
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3623
-                        false,
3624
-                        $option,
3625
-                        $value
3626
-                    );
3627
-                    if (false === $value) {
3628
-                        return;
3629
-                    }
3630
-                    break;
3631
-            }
3632
-            update_user_meta($user->ID, $option, $value);
3633
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3634
-            exit;
3635
-        }
3636
-    }
3637
-
3638
-
3639
-    /**
3640
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3641
-     *
3642
-     * @param array $data array that will be assigned to template args.
3643
-     */
3644
-    public function set_template_args($data)
3645
-    {
3646
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3647
-    }
3648
-
3649
-
3650
-    /**
3651
-     * This makes available the WP transient system for temporarily moving data between routes
3652
-     *
3653
-     * @param string $route             the route that should receive the transient
3654
-     * @param array  $data              the data that gets sent
3655
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3656
-     *                                  normal route transient.
3657
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3658
-     *                                  when we are adding a transient before page_routes have been defined.
3659
-     * @return void
3660
-     * @throws EE_Error
3661
-     */
3662
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3663
-    {
3664
-        $user_id = get_current_user_id();
3665
-        if (! $skip_route_verify) {
3666
-            $this->_verify_route($route);
3667
-        }
3668
-        // now let's set the string for what kind of transient we're setting
3669
-        $transient = $notices
3670
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3671
-            : 'rte_tx_' . $route . '_' . $user_id;
3672
-        $data      = $notices ? ['notices' => $data] : $data;
3673
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3674
-        $existing = is_multisite() && is_network_admin()
3675
-            ? get_site_transient($transient)
3676
-            : get_transient($transient);
3677
-        if ($existing) {
3678
-            $data = array_merge((array) $data, (array) $existing);
3679
-        }
3680
-        if (is_multisite() && is_network_admin()) {
3681
-            set_site_transient($transient, $data, 8);
3682
-        } else {
3683
-            set_transient($transient, $data, 8);
3684
-        }
3685
-    }
3686
-
3687
-
3688
-    /**
3689
-     * this retrieves the temporary transient that has been set for moving data between routes.
3690
-     *
3691
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3692
-     * @param string $route
3693
-     * @return mixed data
3694
-     */
3695
-    protected function _get_transient($notices = false, $route = '')
3696
-    {
3697
-        $user_id   = get_current_user_id();
3698
-        $route     = ! $route ? $this->_req_action : $route;
3699
-        $transient = $notices
3700
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3701
-            : 'rte_tx_' . $route . '_' . $user_id;
3702
-        $data      = is_multisite() && is_network_admin()
3703
-            ? get_site_transient($transient)
3704
-            : get_transient($transient);
3705
-        // delete transient after retrieval (just in case it hasn't expired);
3706
-        if (is_multisite() && is_network_admin()) {
3707
-            delete_site_transient($transient);
3708
-        } else {
3709
-            delete_transient($transient);
3710
-        }
3711
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3712
-    }
3713
-
3714
-
3715
-    /**
3716
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3717
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3718
-     * default route callback on the EE_Admin page you want it run.)
3719
-     *
3720
-     * @return void
3721
-     */
3722
-    protected function _transient_garbage_collection()
3723
-    {
3724
-        global $wpdb;
3725
-        // retrieve all existing transients
3726
-        $query =
3727
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3728
-        if ($results = $wpdb->get_results($query)) {
3729
-            foreach ($results as $result) {
3730
-                $transient = str_replace('_transient_', '', $result->option_name);
3731
-                get_transient($transient);
3732
-                if (is_multisite() && is_network_admin()) {
3733
-                    get_site_transient($transient);
3734
-                }
3735
-            }
3736
-        }
3737
-    }
3738
-
3739
-
3740
-    /**
3741
-     * get_view
3742
-     *
3743
-     * @return string content of _view property
3744
-     */
3745
-    public function get_view()
3746
-    {
3747
-        return $this->_view;
3748
-    }
3749
-
3750
-
3751
-    /**
3752
-     * getter for the protected $_views property
3753
-     *
3754
-     * @return array
3755
-     */
3756
-    public function get_views()
3757
-    {
3758
-        return $this->_views;
3759
-    }
3760
-
3761
-
3762
-    /**
3763
-     * get_current_page
3764
-     *
3765
-     * @return string _current_page property value
3766
-     */
3767
-    public function get_current_page()
3768
-    {
3769
-        return $this->_current_page;
3770
-    }
3771
-
3772
-
3773
-    /**
3774
-     * get_current_view
3775
-     *
3776
-     * @return string _current_view property value
3777
-     */
3778
-    public function get_current_view()
3779
-    {
3780
-        return $this->_current_view;
3781
-    }
3782
-
3783
-
3784
-    /**
3785
-     * get_current_screen
3786
-     *
3787
-     * @return object The current WP_Screen object
3788
-     */
3789
-    public function get_current_screen()
3790
-    {
3791
-        return $this->_current_screen;
3792
-    }
3793
-
3794
-
3795
-    /**
3796
-     * get_current_page_view_url
3797
-     *
3798
-     * @return string This returns the url for the current_page_view.
3799
-     */
3800
-    public function get_current_page_view_url()
3801
-    {
3802
-        return $this->_current_page_view_url;
3803
-    }
3804
-
3805
-
3806
-    /**
3807
-     * just returns the Request
3808
-     *
3809
-     * @return RequestInterface
3810
-     */
3811
-    public function get_request()
3812
-    {
3813
-        return $this->request;
3814
-    }
3815
-
3816
-
3817
-    /**
3818
-     * just returns the _req_data property
3819
-     *
3820
-     * @return array
3821
-     */
3822
-    public function get_request_data()
3823
-    {
3824
-        return $this->request->requestParams();
3825
-    }
3826
-
3827
-
3828
-    /**
3829
-     * returns the _req_data protected property
3830
-     *
3831
-     * @return string
3832
-     */
3833
-    public function get_req_action()
3834
-    {
3835
-        return $this->_req_action;
3836
-    }
3837
-
3838
-
3839
-    /**
3840
-     * @return bool  value of $_is_caf property
3841
-     */
3842
-    public function is_caf()
3843
-    {
3844
-        return $this->_is_caf;
3845
-    }
3846
-
3847
-
3848
-    /**
3849
-     * @return mixed
3850
-     */
3851
-    public function default_espresso_metaboxes()
3852
-    {
3853
-        return $this->_default_espresso_metaboxes;
3854
-    }
3855
-
3856
-
3857
-    /**
3858
-     * @return mixed
3859
-     */
3860
-    public function admin_base_url()
3861
-    {
3862
-        return $this->_admin_base_url;
3863
-    }
3864
-
3865
-
3866
-    /**
3867
-     * @return mixed
3868
-     */
3869
-    public function wp_page_slug()
3870
-    {
3871
-        return $this->_wp_page_slug;
3872
-    }
3873
-
3874
-
3875
-    /**
3876
-     * updates  espresso configuration settings
3877
-     *
3878
-     * @param string                   $tab
3879
-     * @param EE_Config_Base|EE_Config $config
3880
-     * @param string                   $file file where error occurred
3881
-     * @param string                   $func function  where error occurred
3882
-     * @param string                   $line line no where error occurred
3883
-     * @return boolean
3884
-     */
3885
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3886
-    {
3887
-        // remove any options that are NOT going to be saved with the config settings.
3888
-        if (isset($config->core->ee_ueip_optin)) {
3889
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3890
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3891
-            update_option('ee_ueip_has_notified', true);
3892
-        }
3893
-        // and save it (note we're also doing the network save here)
3894
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3895
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
3896
-        if ($config_saved && $net_saved) {
3897
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3898
-            return true;
3899
-        }
3900
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3901
-        return false;
3902
-    }
3903
-
3904
-
3905
-    /**
3906
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3907
-     *
3908
-     * @return array
3909
-     */
3910
-    public function get_yes_no_values()
3911
-    {
3912
-        return $this->_yes_no_values;
3913
-    }
3914
-
3915
-
3916
-    protected function _get_dir()
3917
-    {
3918
-        $reflector = new ReflectionClass(get_class($this));
3919
-        return dirname($reflector->getFileName());
3920
-    }
3921
-
3922
-
3923
-    /**
3924
-     * A helper for getting a "next link".
3925
-     *
3926
-     * @param string $url   The url to link to
3927
-     * @param string $class The class to use.
3928
-     * @return string
3929
-     */
3930
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3931
-    {
3932
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3933
-    }
3934
-
3935
-
3936
-    /**
3937
-     * A helper for getting a "previous link".
3938
-     *
3939
-     * @param string $url   The url to link to
3940
-     * @param string $class The class to use.
3941
-     * @return string
3942
-     */
3943
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3944
-    {
3945
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3946
-    }
3947
-
3948
-
3949
-
3950
-
3951
-
3952
-
3953
-
3954
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3955
-
3956
-
3957
-    /**
3958
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
3959
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
3960
-     * _req_data array.
3961
-     *
3962
-     * @return bool success/fail
3963
-     * @throws EE_Error
3964
-     * @throws InvalidArgumentException
3965
-     * @throws ReflectionException
3966
-     * @throws InvalidDataTypeException
3967
-     * @throws InvalidInterfaceException
3968
-     */
3969
-    protected function _process_resend_registration()
3970
-    {
3971
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3972
-        do_action(
3973
-            'AHEE__EE_Admin_Page___process_resend_registration',
3974
-            $this->_template_args['success'],
3975
-            $this->request->requestParams()
3976
-        );
3977
-        return $this->_template_args['success'];
3978
-    }
3979
-
3980
-
3981
-    /**
3982
-     * This automatically processes any payment message notifications when manual payment has been applied.
3983
-     *
3984
-     * @param EE_Payment $payment
3985
-     * @return bool success/fail
3986
-     */
3987
-    protected function _process_payment_notification(EE_Payment $payment)
3988
-    {
3989
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3990
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3991
-        $this->_template_args['success'] = apply_filters(
3992
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
3993
-            false,
3994
-            $payment
3995
-        );
3996
-        return $this->_template_args['success'];
3997
-    }
3998
-
3999
-
4000
-    /**
4001
-     * @param EEM_Base      $entity_model
4002
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4003
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4004
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4005
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4006
-     * @return int|float
4007
-     * @throws EE_Error
4008
-     */
4009
-    protected function trashRestoreDeleteEntities(
4010
-        EEM_Base $entity_model,
4011
-        $entity_PK_name,
4012
-        $action = EE_Admin_List_Table::ACTION_DELETE,
4013
-        $delete_column = '',
4014
-        callable $callback = null
4015
-    ) {
4016
-        $entity_PK      = $entity_model->get_primary_key_field();
4017
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4018
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4019
-        // grab ID if deleting a single entity
4020
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4021
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4022
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4023
-        }
4024
-        // or grab checkbox array if bulk deleting
4025
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4026
-        if (empty($checkboxes)) {
4027
-            return 0;
4028
-        }
4029
-        $success = 0;
4030
-        $IDs     = array_keys($checkboxes);
4031
-        // cycle thru bulk action checkboxes
4032
-        foreach ($IDs as $ID) {
4033
-            // increment $success
4034
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4035
-                $success++;
4036
-            }
4037
-        }
4038
-        $count = (int) count($checkboxes);
4039
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4040
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4041
-        return $success === $count ? $count : $success / $count;
4042
-    }
4043
-
4044
-
4045
-    /**
4046
-     * @param EE_Primary_Key_Field_Base $entity_PK
4047
-     * @return string
4048
-     * @throws EE_Error
4049
-     * @since   4.10.30.p
4050
-     */
4051
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK)
4052
-    {
4053
-        $entity_PK_type = $entity_PK->getSchemaType();
4054
-        switch ($entity_PK_type) {
4055
-            case 'boolean':
4056
-                return 'bool';
4057
-            case 'integer':
4058
-                return 'int';
4059
-            case 'number':
4060
-                return 'float';
4061
-            case 'string':
4062
-                return 'string';
4063
-        }
4064
-        throw new RuntimeException(
4065
-            sprintf(
4066
-                esc_html__(
4067
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4068
-                    'event_espresso'
4069
-                ),
4070
-                $entity_PK_type,
4071
-                $entity_PK->get_name()
4072
-            )
4073
-        );
4074
-    }
4075
-
4076
-
4077
-    /**
4078
-     * @param EEM_Base      $entity_model
4079
-     * @param int|string    $entity_ID
4080
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4081
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4082
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4083
-     * @return bool
4084
-     */
4085
-    protected function trashRestoreDeleteEntity(
4086
-        EEM_Base $entity_model,
4087
-        $entity_ID,
4088
-        $action,
4089
-        $delete_column,
4090
-        callable $callback = null
4091
-    ) {
4092
-        $entity_ID = absint($entity_ID);
4093
-        if (! $entity_ID) {
4094
-            $this->trashRestoreDeleteError($action, $entity_model);
4095
-        }
4096
-        $result = 0;
4097
-        try {
4098
-            $entity = $entity_model->get_one_by_ID($entity_ID);
4099
-            if (! $entity instanceof EE_Base_Class) {
4100
-                throw new DomainException(
4101
-                    sprintf(
4102
-                        esc_html__(
4103
-                            'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4104
-                            'event_espresso'
4105
-                        ),
4106
-                        str_replace('EEM_', '', $entity_model->get_this_model_name()),
4107
-                        $entity_ID
4108
-                    )
4109
-                );
4110
-            }
4111
-            switch ($action) {
4112
-                case EE_Admin_List_Table::ACTION_DELETE:
4113
-                    $result = (bool) $entity->delete_permanently();
4114
-                    break;
4115
-                case EE_Admin_List_Table::ACTION_RESTORE:
4116
-                    $result = $entity->delete_or_restore(false);
4117
-                    break;
4118
-                case EE_Admin_List_Table::ACTION_TRASH:
4119
-                    $result = $entity->delete_or_restore();
4120
-                    break;
4121
-            }
4122
-        } catch (Exception $exception) {
4123
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4124
-        }
4125
-        if (is_callable($callback)) {
4126
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4127
-        }
4128
-        return $result;
4129
-    }
4130
-
4131
-
4132
-    /**
4133
-     * @param EEM_Base $entity_model
4134
-     * @param string   $delete_column
4135
-     * @since 4.10.30.p
4136
-     */
4137
-    private function validateDeleteColumn(EEM_Base $entity_model, $delete_column)
4138
-    {
4139
-        if (empty($delete_column)) {
4140
-            throw new DomainException(
4141
-                sprintf(
4142
-                    esc_html__(
4143
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4144
-                        'event_espresso'
4145
-                    ),
4146
-                    $entity_model->get_this_model_name()
4147
-                )
4148
-            );
4149
-        }
4150
-        if (! $entity_model->has_field($delete_column)) {
4151
-            throw new DomainException(
4152
-                sprintf(
4153
-                    esc_html__(
4154
-                        'The %1$s field does not exist on the %2$s model.',
4155
-                        'event_espresso'
4156
-                    ),
4157
-                    $delete_column,
4158
-                    $entity_model->get_this_model_name()
4159
-                )
4160
-            );
4161
-        }
4162
-    }
4163
-
4164
-
4165
-    /**
4166
-     * @param EEM_Base       $entity_model
4167
-     * @param Exception|null $exception
4168
-     * @param string         $action
4169
-     * @since 4.10.30.p
4170
-     */
4171
-    private function trashRestoreDeleteError($action, EEM_Base $entity_model, Exception $exception = null)
4172
-    {
4173
-        if ($exception instanceof Exception) {
4174
-            throw new RuntimeException(
4175
-                sprintf(
4176
-                    esc_html__(
4177
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4178
-                        'event_espresso'
4179
-                    ),
4180
-                    $action,
4181
-                    $entity_model->get_this_model_name(),
4182
-                    $exception->getMessage()
4183
-                )
4184
-            );
4185
-        }
4186
-        throw new RuntimeException(
4187
-            sprintf(
4188
-                esc_html__(
4189
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4190
-                    'event_espresso'
4191
-                ),
4192
-                $action,
4193
-                $entity_model->get_this_model_name()
4194
-            )
4195
-        );
4196
-    }
2854
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2855
+		// display message about search results?
2856
+		$search = $this->request->getRequestParam('s');
2857
+		$this->_template_args['before_list_table'] .= ! empty($search)
2858
+			? '<p class="ee-search-results">' . sprintf(
2859
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2860
+				trim($search, '%')
2861
+			) . '</p>'
2862
+			: '';
2863
+		// filter before_list_table template arg
2864
+		$this->_template_args['before_list_table'] = apply_filters(
2865
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2866
+			$this->_template_args['before_list_table'],
2867
+			$this->page_slug,
2868
+			$this->request->requestParams(),
2869
+			$this->_req_action
2870
+		);
2871
+		// convert to array and filter again
2872
+		// arrays are easier to inject new items in a specific location,
2873
+		// but would not be backwards compatible, so we have to add a new filter
2874
+		$this->_template_args['before_list_table'] = implode(
2875
+			" \n",
2876
+			(array) apply_filters(
2877
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2878
+				(array) $this->_template_args['before_list_table'],
2879
+				$this->page_slug,
2880
+				$this->request->requestParams(),
2881
+				$this->_req_action
2882
+			)
2883
+		);
2884
+		// filter after_list_table template arg
2885
+		$this->_template_args['after_list_table'] = apply_filters(
2886
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2887
+			$this->_template_args['after_list_table'],
2888
+			$this->page_slug,
2889
+			$this->request->requestParams(),
2890
+			$this->_req_action
2891
+		);
2892
+		// convert to array and filter again
2893
+		// arrays are easier to inject new items in a specific location,
2894
+		// but would not be backwards compatible, so we have to add a new filter
2895
+		$this->_template_args['after_list_table']   = implode(
2896
+			" \n",
2897
+			(array) apply_filters(
2898
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2899
+				(array) $this->_template_args['after_list_table'],
2900
+				$this->page_slug,
2901
+				$this->request->requestParams(),
2902
+				$this->_req_action
2903
+			)
2904
+		);
2905
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2906
+			$template_path,
2907
+			$this->_template_args,
2908
+			true
2909
+		);
2910
+		// the final template wrapper
2911
+		if ($sidebar) {
2912
+			$this->display_admin_page_with_sidebar();
2913
+		} else {
2914
+			$this->display_admin_page_with_no_sidebar();
2915
+		}
2916
+	}
2917
+
2918
+
2919
+	/**
2920
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
2921
+	 * html string for the legend.
2922
+	 * $items are expected in an array in the following format:
2923
+	 * $legend_items = array(
2924
+	 *        'item_id' => array(
2925
+	 *            'icon' => 'http://url_to_icon_being_described.png',
2926
+	 *            'desc' => esc_html__('localized description of item');
2927
+	 *        )
2928
+	 * );
2929
+	 *
2930
+	 * @param array $items see above for format of array
2931
+	 * @return string html string of legend
2932
+	 * @throws DomainException
2933
+	 */
2934
+	protected function _display_legend($items)
2935
+	{
2936
+		$this->_template_args['items'] = apply_filters(
2937
+			'FHEE__EE_Admin_Page___display_legend__items',
2938
+			(array) $items,
2939
+			$this
2940
+		);
2941
+		return EEH_Template::display_template(
2942
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
2943
+			$this->_template_args,
2944
+			true
2945
+		);
2946
+	}
2947
+
2948
+
2949
+	/**
2950
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2951
+	 * The returned json object is created from an array in the following format:
2952
+	 * array(
2953
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2954
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
2955
+	 *  'notices' => '', // - contains any EE_Error formatted notices
2956
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
2957
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
2958
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
2959
+	 *  that might be included in here)
2960
+	 * )
2961
+	 * The json object is populated by whatever is set in the $_template_args property.
2962
+	 *
2963
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
2964
+	 *                                 instead of displayed.
2965
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
2966
+	 * @return void
2967
+	 * @throws EE_Error
2968
+	 */
2969
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
2970
+	{
2971
+		// make sure any EE_Error notices have been handled.
2972
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
2973
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
2974
+		unset($this->_template_args['data']);
2975
+		$json = [
2976
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2977
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2978
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2979
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2980
+			'notices'   => EE_Error::get_notices(),
2981
+			'content'   => isset($this->_template_args['admin_page_content'])
2982
+				? $this->_template_args['admin_page_content'] : '',
2983
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
2984
+			'isEEajax'  => true
2985
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2986
+		];
2987
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
2988
+		if (null === error_get_last() || ! headers_sent()) {
2989
+			header('Content-Type: application/json; charset=UTF-8');
2990
+		}
2991
+		echo wp_json_encode($json);
2992
+		exit();
2993
+	}
2994
+
2995
+
2996
+	/**
2997
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2998
+	 *
2999
+	 * @return void
3000
+	 * @throws EE_Error
3001
+	 */
3002
+	public function return_json()
3003
+	{
3004
+		if ($this->request->isAjax()) {
3005
+			$this->_return_json();
3006
+		} else {
3007
+			throw new EE_Error(
3008
+				sprintf(
3009
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3010
+					__FUNCTION__
3011
+				)
3012
+			);
3013
+		}
3014
+	}
3015
+
3016
+
3017
+	/**
3018
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3019
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3020
+	 *
3021
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3022
+	 */
3023
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3024
+	{
3025
+		$this->_hook_obj = $hook_obj;
3026
+	}
3027
+
3028
+
3029
+	/**
3030
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3031
+	 *
3032
+	 * @param boolean $about whether to use the special about page wrapper or default.
3033
+	 * @return void
3034
+	 * @throws DomainException
3035
+	 * @throws EE_Error
3036
+	 */
3037
+	public function admin_page_wrapper($about = false)
3038
+	{
3039
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3040
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3041
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3042
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3043
+
3044
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3045
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3046
+			isset($this->_template_args['before_admin_page_content'])
3047
+				? $this->_template_args['before_admin_page_content']
3048
+				: ''
3049
+		);
3050
+
3051
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3052
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3053
+			isset($this->_template_args['after_admin_page_content'])
3054
+				? $this->_template_args['after_admin_page_content']
3055
+				: ''
3056
+		);
3057
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3058
+
3059
+		if ($this->request->isAjax()) {
3060
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3061
+				// $template_path,
3062
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3063
+				$this->_template_args,
3064
+				true
3065
+			);
3066
+			$this->_return_json();
3067
+		}
3068
+		// load settings page wrapper template
3069
+		$template_path = $about
3070
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3071
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3072
+
3073
+		EEH_Template::display_template($template_path, $this->_template_args);
3074
+	}
3075
+
3076
+
3077
+	/**
3078
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3079
+	 *
3080
+	 * @return string html
3081
+	 * @throws EE_Error
3082
+	 */
3083
+	protected function _get_main_nav_tabs()
3084
+	{
3085
+		// let's generate the html using the EEH_Tabbed_Content helper.
3086
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3087
+		// (rather than setting in the page_routes array)
3088
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3089
+	}
3090
+
3091
+
3092
+	/**
3093
+	 *        sort nav tabs
3094
+	 *
3095
+	 * @param $a
3096
+	 * @param $b
3097
+	 * @return int
3098
+	 */
3099
+	private function _sort_nav_tabs($a, $b)
3100
+	{
3101
+		if ($a['order'] === $b['order']) {
3102
+			return 0;
3103
+		}
3104
+		return ($a['order'] < $b['order']) ? -1 : 1;
3105
+	}
3106
+
3107
+
3108
+	/**
3109
+	 *    generates HTML for the forms used on admin pages
3110
+	 *
3111
+	 * @param array  $input_vars   - array of input field details
3112
+	 * @param string $generator    (options are 'string' or 'array', basically use this to indicate which generator to
3113
+	 *                             use)
3114
+	 * @param bool   $id
3115
+	 * @return array|string
3116
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3117
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3118
+	 */
3119
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3120
+	{
3121
+		return $generator === 'string'
3122
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3123
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3124
+	}
3125
+
3126
+
3127
+	/**
3128
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3129
+	 *
3130
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3131
+	 *                                   Close" button.
3132
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3133
+	 *                                   'Save', [1] => 'save & close')
3134
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3135
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3136
+	 *                                   default actions by submitting some other value.
3137
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3138
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3139
+	 *                                   close (normal form handling).
3140
+	 */
3141
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3142
+	{
3143
+		// make sure $text and $actions are in an array
3144
+		$text          = (array) $text;
3145
+		$actions       = (array) $actions;
3146
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3147
+		$button_text   = ! empty($text)
3148
+			? $text
3149
+			: [
3150
+				esc_html__('Save', 'event_espresso'),
3151
+				esc_html__('Save and Close', 'event_espresso'),
3152
+			];
3153
+		$default_names = ['save', 'save_and_close'];
3154
+		$buttons = '';
3155
+		foreach ($button_text as $key => $button) {
3156
+			$ref     = $default_names[ $key ];
3157
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3158
+			$buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3159
+						. 'value="' . $button . '" name="' . $name . '" '
3160
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3161
+			if (! $both) {
3162
+				break;
3163
+			}
3164
+		}
3165
+		// add in a hidden index for the current page (so save and close redirects properly)
3166
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3167
+				   . $referrer_url
3168
+				   . '" />';
3169
+		$this->_template_args['save_buttons'] = $buttons;
3170
+	}
3171
+
3172
+
3173
+	/**
3174
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3175
+	 *
3176
+	 * @param string $route
3177
+	 * @param array  $additional_hidden_fields
3178
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3179
+	 * @since 4.6.0
3180
+	 */
3181
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3182
+	{
3183
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3184
+	}
3185
+
3186
+
3187
+	/**
3188
+	 * set form open and close tags on add/edit pages.
3189
+	 *
3190
+	 * @param string $route                    the route you want the form to direct to
3191
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3192
+	 * @return void
3193
+	 */
3194
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3195
+	{
3196
+		if (empty($route)) {
3197
+			$user_msg = esc_html__(
3198
+				'An error occurred. No action was set for this page\'s form.',
3199
+				'event_espresso'
3200
+			);
3201
+			$dev_msg  = $user_msg . "\n"
3202
+						. sprintf(
3203
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3204
+							__FUNCTION__,
3205
+							__CLASS__
3206
+						);
3207
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3208
+		}
3209
+		// open form
3210
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3211
+															 . $this->_admin_base_url
3212
+															 . '" id="'
3213
+															 . $route
3214
+															 . '_event_form" >';
3215
+		// add nonce
3216
+		$nonce                                             =
3217
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3218
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3219
+		// add REQUIRED form action
3220
+		$hidden_fields = [
3221
+			'action' => ['type' => 'hidden', 'value' => $route],
3222
+		];
3223
+		// merge arrays
3224
+		$hidden_fields = is_array($additional_hidden_fields)
3225
+			? array_merge($hidden_fields, $additional_hidden_fields)
3226
+			: $hidden_fields;
3227
+		// generate form fields
3228
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3229
+		// add fields to form
3230
+		foreach ((array) $form_fields as $form_field) {
3231
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3232
+		}
3233
+		// close form
3234
+		$this->_template_args['after_admin_page_content'] = '</form>';
3235
+	}
3236
+
3237
+
3238
+	/**
3239
+	 * Public Wrapper for _redirect_after_action() method since its
3240
+	 * discovered it would be useful for external code to have access.
3241
+	 *
3242
+	 * @param bool   $success
3243
+	 * @param string $what
3244
+	 * @param string $action_desc
3245
+	 * @param array  $query_args
3246
+	 * @param bool   $override_overwrite
3247
+	 * @throws EE_Error
3248
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3249
+	 * @since 4.5.0
3250
+	 */
3251
+	public function redirect_after_action(
3252
+		$success = false,
3253
+		$what = 'item',
3254
+		$action_desc = 'processed',
3255
+		$query_args = [],
3256
+		$override_overwrite = false
3257
+	) {
3258
+		$this->_redirect_after_action(
3259
+			$success,
3260
+			$what,
3261
+			$action_desc,
3262
+			$query_args,
3263
+			$override_overwrite
3264
+		);
3265
+	}
3266
+
3267
+
3268
+	/**
3269
+	 * Helper method for merging existing request data with the returned redirect url.
3270
+	 *
3271
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3272
+	 * filters are still applied.
3273
+	 *
3274
+	 * @param array $new_route_data
3275
+	 * @return array
3276
+	 */
3277
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3278
+	{
3279
+		foreach ($this->request->requestParams() as $ref => $value) {
3280
+			// unset nonces
3281
+			if (strpos($ref, 'nonce') !== false) {
3282
+				$this->request->unSetRequestParam($ref);
3283
+				continue;
3284
+			}
3285
+			// urlencode values.
3286
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3287
+			$this->request->setRequestParam($ref, $value);
3288
+		}
3289
+		return array_merge($this->request->requestParams(), $new_route_data);
3290
+	}
3291
+
3292
+
3293
+	/**
3294
+	 *    _redirect_after_action
3295
+	 *
3296
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3297
+	 * @param string $what               - what the action was performed on
3298
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3299
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3300
+	 *                                   action is completed
3301
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3302
+	 *                                   override this so that they show.
3303
+	 * @return void
3304
+	 * @throws EE_Error
3305
+	 */
3306
+	protected function _redirect_after_action(
3307
+		$success = 0,
3308
+		$what = 'item',
3309
+		$action_desc = 'processed',
3310
+		$query_args = [],
3311
+		$override_overwrite = false
3312
+	) {
3313
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3314
+		// class name for actions/filters.
3315
+		$classname = get_class($this);
3316
+		// set redirect url.
3317
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3318
+		// otherwise we go with whatever is set as the _admin_base_url
3319
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3320
+		$notices      = EE_Error::get_notices(false);
3321
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3322
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3323
+			EE_Error::overwrite_success();
3324
+		}
3325
+		if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3326
+			// how many records affected ? more than one record ? or just one ?
3327
+			if ($success > 1) {
3328
+				// set plural msg
3329
+				EE_Error::add_success(
3330
+					sprintf(
3331
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3332
+						$what,
3333
+						$action_desc
3334
+					),
3335
+					__FILE__,
3336
+					__FUNCTION__,
3337
+					__LINE__
3338
+				);
3339
+			} elseif ($success === 1) {
3340
+				// set singular msg
3341
+				EE_Error::add_success(
3342
+					sprintf(
3343
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3344
+						$what,
3345
+						$action_desc
3346
+					),
3347
+					__FILE__,
3348
+					__FUNCTION__,
3349
+					__LINE__
3350
+				);
3351
+			}
3352
+		}
3353
+		// check that $query_args isn't something crazy
3354
+		if (! is_array($query_args)) {
3355
+			$query_args = [];
3356
+		}
3357
+		/**
3358
+		 * Allow injecting actions before the query_args are modified for possible different
3359
+		 * redirections on save and close actions
3360
+		 *
3361
+		 * @param array $query_args       The original query_args array coming into the
3362
+		 *                                method.
3363
+		 * @since 4.2.0
3364
+		 */
3365
+		do_action(
3366
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3367
+			$query_args
3368
+		);
3369
+		// calculate where we're going (if we have a "save and close" button pushed)
3370
+
3371
+		if (
3372
+			$this->request->requestParamIsSet('save_and_close')
3373
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3374
+		) {
3375
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3376
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3377
+			// regenerate query args array from referrer URL
3378
+			parse_str($parsed_url['query'], $query_args);
3379
+			// correct page and action will be in the query args now
3380
+			$redirect_url = admin_url('admin.php');
3381
+		}
3382
+		// merge any default query_args set in _default_route_query_args property
3383
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3384
+			$args_to_merge = [];
3385
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3386
+				// is there a wp_referer array in our _default_route_query_args property?
3387
+				if ($query_param === 'wp_referer') {
3388
+					$query_value = (array) $query_value;
3389
+					foreach ($query_value as $reference => $value) {
3390
+						if (strpos($reference, 'nonce') !== false) {
3391
+							continue;
3392
+						}
3393
+						// finally we will override any arguments in the referer with
3394
+						// what might be set on the _default_route_query_args array.
3395
+						if (isset($this->_default_route_query_args[ $reference ])) {
3396
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3397
+						} else {
3398
+							$args_to_merge[ $reference ] = urlencode($value);
3399
+						}
3400
+					}
3401
+					continue;
3402
+				}
3403
+				$args_to_merge[ $query_param ] = $query_value;
3404
+			}
3405
+			// now let's merge these arguments but override with what was specifically sent in to the
3406
+			// redirect.
3407
+			$query_args = array_merge($args_to_merge, $query_args);
3408
+		}
3409
+		$this->_process_notices($query_args);
3410
+		// generate redirect url
3411
+		// if redirecting to anything other than the main page, add a nonce
3412
+		if (isset($query_args['action'])) {
3413
+			// manually generate wp_nonce and merge that with the query vars
3414
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3415
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3416
+		}
3417
+		// we're adding some hooks and filters in here for processing any things just before redirects
3418
+		// (example: an admin page has done an insert or update and we want to run something after that).
3419
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3420
+		$redirect_url = apply_filters(
3421
+			'FHEE_redirect_' . $classname . $this->_req_action,
3422
+			self::add_query_args_and_nonce($query_args, $redirect_url),
3423
+			$query_args
3424
+		);
3425
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3426
+		if ($this->request->isAjax()) {
3427
+			$default_data                    = [
3428
+				'close'        => true,
3429
+				'redirect_url' => $redirect_url,
3430
+				'where'        => 'main',
3431
+				'what'         => 'append',
3432
+			];
3433
+			$this->_template_args['success'] = $success;
3434
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3435
+				$default_data,
3436
+				$this->_template_args['data']
3437
+			) : $default_data;
3438
+			$this->_return_json();
3439
+		}
3440
+		wp_safe_redirect($redirect_url);
3441
+		exit();
3442
+	}
3443
+
3444
+
3445
+	/**
3446
+	 * process any notices before redirecting (or returning ajax request)
3447
+	 * This method sets the $this->_template_args['notices'] attribute;
3448
+	 *
3449
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3450
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3451
+	 *                                  page_routes haven't been defined yet.
3452
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3453
+	 *                                  still save a transient for the notice.
3454
+	 * @return void
3455
+	 * @throws EE_Error
3456
+	 */
3457
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3458
+	{
3459
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3460
+		if ($this->request->isAjax()) {
3461
+			$notices = EE_Error::get_notices(false);
3462
+			if (empty($this->_template_args['success'])) {
3463
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3464
+			}
3465
+			if (empty($this->_template_args['errors'])) {
3466
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3467
+			}
3468
+			if (empty($this->_template_args['attention'])) {
3469
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3470
+			}
3471
+		}
3472
+		$this->_template_args['notices'] = EE_Error::get_notices();
3473
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3474
+		if (! $this->request->isAjax() || $sticky_notices) {
3475
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3476
+			$this->_add_transient(
3477
+				$route,
3478
+				$this->_template_args['notices'],
3479
+				true,
3480
+				$skip_route_verify
3481
+			);
3482
+		}
3483
+	}
3484
+
3485
+
3486
+	/**
3487
+	 * get_action_link_or_button
3488
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3489
+	 *
3490
+	 * @param string $action        use this to indicate which action the url is generated with.
3491
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3492
+	 *                              property.
3493
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3494
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3495
+	 * @param string $base_url      If this is not provided
3496
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3497
+	 *                              Otherwise this value will be used.
3498
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3499
+	 * @return string
3500
+	 * @throws InvalidArgumentException
3501
+	 * @throws InvalidInterfaceException
3502
+	 * @throws InvalidDataTypeException
3503
+	 * @throws EE_Error
3504
+	 */
3505
+	public function get_action_link_or_button(
3506
+		$action,
3507
+		$type = 'add',
3508
+		$extra_request = [],
3509
+		$class = 'button button--primary',
3510
+		$base_url = '',
3511
+		$exclude_nonce = false
3512
+	) {
3513
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3514
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3515
+			throw new EE_Error(
3516
+				sprintf(
3517
+					esc_html__(
3518
+						'There is no page route for given action for the button.  This action was given: %s',
3519
+						'event_espresso'
3520
+					),
3521
+					$action
3522
+				)
3523
+			);
3524
+		}
3525
+		if (! isset($this->_labels['buttons'][ $type ])) {
3526
+			throw new EE_Error(
3527
+				sprintf(
3528
+					esc_html__(
3529
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3530
+						'event_espresso'
3531
+					),
3532
+					$type
3533
+				)
3534
+			);
3535
+		}
3536
+		// finally check user access for this button.
3537
+		$has_access = $this->check_user_access($action, true);
3538
+		if (! $has_access) {
3539
+			return '';
3540
+		}
3541
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3542
+		$query_args = [
3543
+			'action' => $action,
3544
+		];
3545
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3546
+		if (! empty($extra_request)) {
3547
+			$query_args = array_merge($extra_request, $query_args);
3548
+		}
3549
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3550
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3551
+	}
3552
+
3553
+
3554
+	/**
3555
+	 * _per_page_screen_option
3556
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3557
+	 *
3558
+	 * @return void
3559
+	 * @throws InvalidArgumentException
3560
+	 * @throws InvalidInterfaceException
3561
+	 * @throws InvalidDataTypeException
3562
+	 */
3563
+	protected function _per_page_screen_option()
3564
+	{
3565
+		$option = 'per_page';
3566
+		$args   = [
3567
+			'label'   => apply_filters(
3568
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3569
+				$this->_admin_page_title,
3570
+				$this
3571
+			),
3572
+			'default' => (int) apply_filters(
3573
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3574
+				20
3575
+			),
3576
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3577
+		];
3578
+		// ONLY add the screen option if the user has access to it.
3579
+		if ($this->check_user_access($this->_current_view, true)) {
3580
+			add_screen_option($option, $args);
3581
+		}
3582
+	}
3583
+
3584
+
3585
+	/**
3586
+	 * set_per_page_screen_option
3587
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3588
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3589
+	 * admin_menu.
3590
+	 *
3591
+	 * @return void
3592
+	 */
3593
+	private function _set_per_page_screen_options()
3594
+	{
3595
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3596
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3597
+			if (! $user = wp_get_current_user()) {
3598
+				return;
3599
+			}
3600
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3601
+			if (! $option) {
3602
+				return;
3603
+			}
3604
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3605
+			$map_option = $option;
3606
+			$option     = str_replace('-', '_', $option);
3607
+			switch ($map_option) {
3608
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3609
+					$max_value = apply_filters(
3610
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3611
+						999,
3612
+						$this->_current_page,
3613
+						$this->_current_view
3614
+					);
3615
+					if ($value < 1) {
3616
+						return;
3617
+					}
3618
+					$value = min($value, $max_value);
3619
+					break;
3620
+				default:
3621
+					$value = apply_filters(
3622
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3623
+						false,
3624
+						$option,
3625
+						$value
3626
+					);
3627
+					if (false === $value) {
3628
+						return;
3629
+					}
3630
+					break;
3631
+			}
3632
+			update_user_meta($user->ID, $option, $value);
3633
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3634
+			exit;
3635
+		}
3636
+	}
3637
+
3638
+
3639
+	/**
3640
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3641
+	 *
3642
+	 * @param array $data array that will be assigned to template args.
3643
+	 */
3644
+	public function set_template_args($data)
3645
+	{
3646
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3647
+	}
3648
+
3649
+
3650
+	/**
3651
+	 * This makes available the WP transient system for temporarily moving data between routes
3652
+	 *
3653
+	 * @param string $route             the route that should receive the transient
3654
+	 * @param array  $data              the data that gets sent
3655
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3656
+	 *                                  normal route transient.
3657
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3658
+	 *                                  when we are adding a transient before page_routes have been defined.
3659
+	 * @return void
3660
+	 * @throws EE_Error
3661
+	 */
3662
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3663
+	{
3664
+		$user_id = get_current_user_id();
3665
+		if (! $skip_route_verify) {
3666
+			$this->_verify_route($route);
3667
+		}
3668
+		// now let's set the string for what kind of transient we're setting
3669
+		$transient = $notices
3670
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3671
+			: 'rte_tx_' . $route . '_' . $user_id;
3672
+		$data      = $notices ? ['notices' => $data] : $data;
3673
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3674
+		$existing = is_multisite() && is_network_admin()
3675
+			? get_site_transient($transient)
3676
+			: get_transient($transient);
3677
+		if ($existing) {
3678
+			$data = array_merge((array) $data, (array) $existing);
3679
+		}
3680
+		if (is_multisite() && is_network_admin()) {
3681
+			set_site_transient($transient, $data, 8);
3682
+		} else {
3683
+			set_transient($transient, $data, 8);
3684
+		}
3685
+	}
3686
+
3687
+
3688
+	/**
3689
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3690
+	 *
3691
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3692
+	 * @param string $route
3693
+	 * @return mixed data
3694
+	 */
3695
+	protected function _get_transient($notices = false, $route = '')
3696
+	{
3697
+		$user_id   = get_current_user_id();
3698
+		$route     = ! $route ? $this->_req_action : $route;
3699
+		$transient = $notices
3700
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3701
+			: 'rte_tx_' . $route . '_' . $user_id;
3702
+		$data      = is_multisite() && is_network_admin()
3703
+			? get_site_transient($transient)
3704
+			: get_transient($transient);
3705
+		// delete transient after retrieval (just in case it hasn't expired);
3706
+		if (is_multisite() && is_network_admin()) {
3707
+			delete_site_transient($transient);
3708
+		} else {
3709
+			delete_transient($transient);
3710
+		}
3711
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3712
+	}
3713
+
3714
+
3715
+	/**
3716
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3717
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3718
+	 * default route callback on the EE_Admin page you want it run.)
3719
+	 *
3720
+	 * @return void
3721
+	 */
3722
+	protected function _transient_garbage_collection()
3723
+	{
3724
+		global $wpdb;
3725
+		// retrieve all existing transients
3726
+		$query =
3727
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3728
+		if ($results = $wpdb->get_results($query)) {
3729
+			foreach ($results as $result) {
3730
+				$transient = str_replace('_transient_', '', $result->option_name);
3731
+				get_transient($transient);
3732
+				if (is_multisite() && is_network_admin()) {
3733
+					get_site_transient($transient);
3734
+				}
3735
+			}
3736
+		}
3737
+	}
3738
+
3739
+
3740
+	/**
3741
+	 * get_view
3742
+	 *
3743
+	 * @return string content of _view property
3744
+	 */
3745
+	public function get_view()
3746
+	{
3747
+		return $this->_view;
3748
+	}
3749
+
3750
+
3751
+	/**
3752
+	 * getter for the protected $_views property
3753
+	 *
3754
+	 * @return array
3755
+	 */
3756
+	public function get_views()
3757
+	{
3758
+		return $this->_views;
3759
+	}
3760
+
3761
+
3762
+	/**
3763
+	 * get_current_page
3764
+	 *
3765
+	 * @return string _current_page property value
3766
+	 */
3767
+	public function get_current_page()
3768
+	{
3769
+		return $this->_current_page;
3770
+	}
3771
+
3772
+
3773
+	/**
3774
+	 * get_current_view
3775
+	 *
3776
+	 * @return string _current_view property value
3777
+	 */
3778
+	public function get_current_view()
3779
+	{
3780
+		return $this->_current_view;
3781
+	}
3782
+
3783
+
3784
+	/**
3785
+	 * get_current_screen
3786
+	 *
3787
+	 * @return object The current WP_Screen object
3788
+	 */
3789
+	public function get_current_screen()
3790
+	{
3791
+		return $this->_current_screen;
3792
+	}
3793
+
3794
+
3795
+	/**
3796
+	 * get_current_page_view_url
3797
+	 *
3798
+	 * @return string This returns the url for the current_page_view.
3799
+	 */
3800
+	public function get_current_page_view_url()
3801
+	{
3802
+		return $this->_current_page_view_url;
3803
+	}
3804
+
3805
+
3806
+	/**
3807
+	 * just returns the Request
3808
+	 *
3809
+	 * @return RequestInterface
3810
+	 */
3811
+	public function get_request()
3812
+	{
3813
+		return $this->request;
3814
+	}
3815
+
3816
+
3817
+	/**
3818
+	 * just returns the _req_data property
3819
+	 *
3820
+	 * @return array
3821
+	 */
3822
+	public function get_request_data()
3823
+	{
3824
+		return $this->request->requestParams();
3825
+	}
3826
+
3827
+
3828
+	/**
3829
+	 * returns the _req_data protected property
3830
+	 *
3831
+	 * @return string
3832
+	 */
3833
+	public function get_req_action()
3834
+	{
3835
+		return $this->_req_action;
3836
+	}
3837
+
3838
+
3839
+	/**
3840
+	 * @return bool  value of $_is_caf property
3841
+	 */
3842
+	public function is_caf()
3843
+	{
3844
+		return $this->_is_caf;
3845
+	}
3846
+
3847
+
3848
+	/**
3849
+	 * @return mixed
3850
+	 */
3851
+	public function default_espresso_metaboxes()
3852
+	{
3853
+		return $this->_default_espresso_metaboxes;
3854
+	}
3855
+
3856
+
3857
+	/**
3858
+	 * @return mixed
3859
+	 */
3860
+	public function admin_base_url()
3861
+	{
3862
+		return $this->_admin_base_url;
3863
+	}
3864
+
3865
+
3866
+	/**
3867
+	 * @return mixed
3868
+	 */
3869
+	public function wp_page_slug()
3870
+	{
3871
+		return $this->_wp_page_slug;
3872
+	}
3873
+
3874
+
3875
+	/**
3876
+	 * updates  espresso configuration settings
3877
+	 *
3878
+	 * @param string                   $tab
3879
+	 * @param EE_Config_Base|EE_Config $config
3880
+	 * @param string                   $file file where error occurred
3881
+	 * @param string                   $func function  where error occurred
3882
+	 * @param string                   $line line no where error occurred
3883
+	 * @return boolean
3884
+	 */
3885
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3886
+	{
3887
+		// remove any options that are NOT going to be saved with the config settings.
3888
+		if (isset($config->core->ee_ueip_optin)) {
3889
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3890
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3891
+			update_option('ee_ueip_has_notified', true);
3892
+		}
3893
+		// and save it (note we're also doing the network save here)
3894
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3895
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
3896
+		if ($config_saved && $net_saved) {
3897
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3898
+			return true;
3899
+		}
3900
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3901
+		return false;
3902
+	}
3903
+
3904
+
3905
+	/**
3906
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3907
+	 *
3908
+	 * @return array
3909
+	 */
3910
+	public function get_yes_no_values()
3911
+	{
3912
+		return $this->_yes_no_values;
3913
+	}
3914
+
3915
+
3916
+	protected function _get_dir()
3917
+	{
3918
+		$reflector = new ReflectionClass(get_class($this));
3919
+		return dirname($reflector->getFileName());
3920
+	}
3921
+
3922
+
3923
+	/**
3924
+	 * A helper for getting a "next link".
3925
+	 *
3926
+	 * @param string $url   The url to link to
3927
+	 * @param string $class The class to use.
3928
+	 * @return string
3929
+	 */
3930
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3931
+	{
3932
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3933
+	}
3934
+
3935
+
3936
+	/**
3937
+	 * A helper for getting a "previous link".
3938
+	 *
3939
+	 * @param string $url   The url to link to
3940
+	 * @param string $class The class to use.
3941
+	 * @return string
3942
+	 */
3943
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3944
+	{
3945
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3946
+	}
3947
+
3948
+
3949
+
3950
+
3951
+
3952
+
3953
+
3954
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3955
+
3956
+
3957
+	/**
3958
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
3959
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
3960
+	 * _req_data array.
3961
+	 *
3962
+	 * @return bool success/fail
3963
+	 * @throws EE_Error
3964
+	 * @throws InvalidArgumentException
3965
+	 * @throws ReflectionException
3966
+	 * @throws InvalidDataTypeException
3967
+	 * @throws InvalidInterfaceException
3968
+	 */
3969
+	protected function _process_resend_registration()
3970
+	{
3971
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3972
+		do_action(
3973
+			'AHEE__EE_Admin_Page___process_resend_registration',
3974
+			$this->_template_args['success'],
3975
+			$this->request->requestParams()
3976
+		);
3977
+		return $this->_template_args['success'];
3978
+	}
3979
+
3980
+
3981
+	/**
3982
+	 * This automatically processes any payment message notifications when manual payment has been applied.
3983
+	 *
3984
+	 * @param EE_Payment $payment
3985
+	 * @return bool success/fail
3986
+	 */
3987
+	protected function _process_payment_notification(EE_Payment $payment)
3988
+	{
3989
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3990
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3991
+		$this->_template_args['success'] = apply_filters(
3992
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
3993
+			false,
3994
+			$payment
3995
+		);
3996
+		return $this->_template_args['success'];
3997
+	}
3998
+
3999
+
4000
+	/**
4001
+	 * @param EEM_Base      $entity_model
4002
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4003
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4004
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4005
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4006
+	 * @return int|float
4007
+	 * @throws EE_Error
4008
+	 */
4009
+	protected function trashRestoreDeleteEntities(
4010
+		EEM_Base $entity_model,
4011
+		$entity_PK_name,
4012
+		$action = EE_Admin_List_Table::ACTION_DELETE,
4013
+		$delete_column = '',
4014
+		callable $callback = null
4015
+	) {
4016
+		$entity_PK      = $entity_model->get_primary_key_field();
4017
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4018
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4019
+		// grab ID if deleting a single entity
4020
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4021
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4022
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4023
+		}
4024
+		// or grab checkbox array if bulk deleting
4025
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4026
+		if (empty($checkboxes)) {
4027
+			return 0;
4028
+		}
4029
+		$success = 0;
4030
+		$IDs     = array_keys($checkboxes);
4031
+		// cycle thru bulk action checkboxes
4032
+		foreach ($IDs as $ID) {
4033
+			// increment $success
4034
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4035
+				$success++;
4036
+			}
4037
+		}
4038
+		$count = (int) count($checkboxes);
4039
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4040
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4041
+		return $success === $count ? $count : $success / $count;
4042
+	}
4043
+
4044
+
4045
+	/**
4046
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4047
+	 * @return string
4048
+	 * @throws EE_Error
4049
+	 * @since   4.10.30.p
4050
+	 */
4051
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK)
4052
+	{
4053
+		$entity_PK_type = $entity_PK->getSchemaType();
4054
+		switch ($entity_PK_type) {
4055
+			case 'boolean':
4056
+				return 'bool';
4057
+			case 'integer':
4058
+				return 'int';
4059
+			case 'number':
4060
+				return 'float';
4061
+			case 'string':
4062
+				return 'string';
4063
+		}
4064
+		throw new RuntimeException(
4065
+			sprintf(
4066
+				esc_html__(
4067
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4068
+					'event_espresso'
4069
+				),
4070
+				$entity_PK_type,
4071
+				$entity_PK->get_name()
4072
+			)
4073
+		);
4074
+	}
4075
+
4076
+
4077
+	/**
4078
+	 * @param EEM_Base      $entity_model
4079
+	 * @param int|string    $entity_ID
4080
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4081
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4082
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4083
+	 * @return bool
4084
+	 */
4085
+	protected function trashRestoreDeleteEntity(
4086
+		EEM_Base $entity_model,
4087
+		$entity_ID,
4088
+		$action,
4089
+		$delete_column,
4090
+		callable $callback = null
4091
+	) {
4092
+		$entity_ID = absint($entity_ID);
4093
+		if (! $entity_ID) {
4094
+			$this->trashRestoreDeleteError($action, $entity_model);
4095
+		}
4096
+		$result = 0;
4097
+		try {
4098
+			$entity = $entity_model->get_one_by_ID($entity_ID);
4099
+			if (! $entity instanceof EE_Base_Class) {
4100
+				throw new DomainException(
4101
+					sprintf(
4102
+						esc_html__(
4103
+							'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4104
+							'event_espresso'
4105
+						),
4106
+						str_replace('EEM_', '', $entity_model->get_this_model_name()),
4107
+						$entity_ID
4108
+					)
4109
+				);
4110
+			}
4111
+			switch ($action) {
4112
+				case EE_Admin_List_Table::ACTION_DELETE:
4113
+					$result = (bool) $entity->delete_permanently();
4114
+					break;
4115
+				case EE_Admin_List_Table::ACTION_RESTORE:
4116
+					$result = $entity->delete_or_restore(false);
4117
+					break;
4118
+				case EE_Admin_List_Table::ACTION_TRASH:
4119
+					$result = $entity->delete_or_restore();
4120
+					break;
4121
+			}
4122
+		} catch (Exception $exception) {
4123
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4124
+		}
4125
+		if (is_callable($callback)) {
4126
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4127
+		}
4128
+		return $result;
4129
+	}
4130
+
4131
+
4132
+	/**
4133
+	 * @param EEM_Base $entity_model
4134
+	 * @param string   $delete_column
4135
+	 * @since 4.10.30.p
4136
+	 */
4137
+	private function validateDeleteColumn(EEM_Base $entity_model, $delete_column)
4138
+	{
4139
+		if (empty($delete_column)) {
4140
+			throw new DomainException(
4141
+				sprintf(
4142
+					esc_html__(
4143
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4144
+						'event_espresso'
4145
+					),
4146
+					$entity_model->get_this_model_name()
4147
+				)
4148
+			);
4149
+		}
4150
+		if (! $entity_model->has_field($delete_column)) {
4151
+			throw new DomainException(
4152
+				sprintf(
4153
+					esc_html__(
4154
+						'The %1$s field does not exist on the %2$s model.',
4155
+						'event_espresso'
4156
+					),
4157
+					$delete_column,
4158
+					$entity_model->get_this_model_name()
4159
+				)
4160
+			);
4161
+		}
4162
+	}
4163
+
4164
+
4165
+	/**
4166
+	 * @param EEM_Base       $entity_model
4167
+	 * @param Exception|null $exception
4168
+	 * @param string         $action
4169
+	 * @since 4.10.30.p
4170
+	 */
4171
+	private function trashRestoreDeleteError($action, EEM_Base $entity_model, Exception $exception = null)
4172
+	{
4173
+		if ($exception instanceof Exception) {
4174
+			throw new RuntimeException(
4175
+				sprintf(
4176
+					esc_html__(
4177
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4178
+						'event_espresso'
4179
+					),
4180
+					$action,
4181
+					$entity_model->get_this_model_name(),
4182
+					$exception->getMessage()
4183
+				)
4184
+			);
4185
+		}
4186
+		throw new RuntimeException(
4187
+			sprintf(
4188
+				esc_html__(
4189
+					'Could not %1$s the %2$s because an invalid ID was received.',
4190
+					'event_espresso'
4191
+				),
4192
+				$action,
4193
+				$entity_model->get_this_model_name()
4194
+			)
4195
+		);
4196
+	}
4197 4197
 }
Please login to merge, or discard this patch.
Spacing   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
         $ee_menu_slugs = (array) $ee_menu_slugs;
516 516
         if (
517 517
             ! $this->request->isAjax()
518
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
518
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
519 519
         ) {
520 520
             return;
521 521
         }
@@ -535,7 +535,7 @@  discard block
 block discarded – undo
535 535
             : $req_action;
536 536
 
537 537
         $this->_current_view = $this->_req_action;
538
-        $this->_req_nonce    = $this->_req_action . '_nonce';
538
+        $this->_req_nonce    = $this->_req_action.'_nonce';
539 539
         $this->_define_page_props();
540 540
         $this->_current_page_view_url = add_query_arg(
541 541
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -572,21 +572,21 @@  discard block
 block discarded – undo
572 572
         }
573 573
         // filter routes and page_config so addons can add their stuff. Filtering done per class
574 574
         $this->_page_routes = apply_filters(
575
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
575
+            'FHEE__'.get_class($this).'__page_setup__page_routes',
576 576
             $this->_page_routes,
577 577
             $this
578 578
         );
579 579
         $this->_page_config = apply_filters(
580
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
580
+            'FHEE__'.get_class($this).'__page_setup__page_config',
581 581
             $this->_page_config,
582 582
             $this
583 583
         );
584 584
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585 585
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
586
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
587 587
             add_action(
588 588
                 'AHEE__EE_Admin_Page__route_admin_request',
589
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
589
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
590 590
                 10,
591 591
                 2
592 592
             );
@@ -599,8 +599,8 @@  discard block
 block discarded – undo
599 599
             if ($this->_is_UI_request) {
600 600
                 // admin_init stuff - global, all views for this page class, specific view
601 601
                 add_action('admin_init', [$this, 'admin_init'], 10);
602
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
603
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
602
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
603
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
604 604
                 }
605 605
             } else {
606 606
                 // hijack regular WP loading and route admin request immediately
@@ -619,12 +619,12 @@  discard block
 block discarded – undo
619 619
      */
620 620
     private function _do_other_page_hooks()
621 621
     {
622
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
622
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
623 623
         foreach ($registered_pages as $page) {
624 624
             // now let's setup the file name and class that should be present
625 625
             $classname = str_replace('.class.php', '', $page);
626 626
             // autoloaders should take care of loading file
627
-            if (! class_exists($classname)) {
627
+            if ( ! class_exists($classname)) {
628 628
                 $error_msg[] = sprintf(
629 629
                     esc_html__(
630 630
                         'Something went wrong with loading the %s admin hooks page.',
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
                                    ),
642 642
                                    $page,
643 643
                                    '<br />',
644
-                                   '<strong>' . $classname . '</strong>'
644
+                                   '<strong>'.$classname.'</strong>'
645 645
                                );
646 646
                 throw new EE_Error(implode('||', $error_msg));
647 647
             }
@@ -683,13 +683,13 @@  discard block
 block discarded – undo
683 683
         // load admin_notices - global, page class, and view specific
684 684
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
685 685
         add_action('admin_notices', [$this, 'admin_notices'], 10);
686
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
687
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
686
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
687
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
688 688
         }
689 689
         // load network admin_notices - global, page class, and view specific
690 690
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
691
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
692
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
691
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
692
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
693 693
         }
694 694
         // this will save any per_page screen options if they are present
695 695
         $this->_set_per_page_screen_options();
@@ -810,7 +810,7 @@  discard block
 block discarded – undo
810 810
     protected function _verify_routes()
811 811
     {
812 812
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
813
-        if (! $this->_current_page && ! $this->request->isAjax()) {
813
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
814 814
             return false;
815 815
         }
816 816
         $this->_route = false;
@@ -822,7 +822,7 @@  discard block
 block discarded – undo
822 822
                 $this->_admin_page_title
823 823
             );
824 824
             // developer error msg
825
-            $error_msg .= '||' . $error_msg
825
+            $error_msg .= '||'.$error_msg
826 826
                           . esc_html__(
827 827
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
828 828
                               'event_espresso'
@@ -831,9 +831,9 @@  discard block
 block discarded – undo
831 831
         }
832 832
         // and that the requested page route exists
833 833
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
834
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
835
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
836
-                ? $this->_page_config[ $this->_req_action ]
834
+            $this->_route        = $this->_page_routes[$this->_req_action];
835
+            $this->_route_config = isset($this->_page_config[$this->_req_action])
836
+                ? $this->_page_config[$this->_req_action]
837 837
                 : [];
838 838
         } else {
839 839
             // user error msg
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
                 $this->_admin_page_title
846 846
             );
847 847
             // developer error msg
848
-            $error_msg .= '||' . $error_msg
848
+            $error_msg .= '||'.$error_msg
849 849
                           . sprintf(
850 850
                               esc_html__(
851 851
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -856,7 +856,7 @@  discard block
 block discarded – undo
856 856
             throw new EE_Error($error_msg);
857 857
         }
858 858
         // and that a default route exists
859
-        if (! array_key_exists('default', $this->_page_routes)) {
859
+        if ( ! array_key_exists('default', $this->_page_routes)) {
860 860
             // user error msg
861 861
             $error_msg = sprintf(
862 862
                 esc_html__(
@@ -866,7 +866,7 @@  discard block
 block discarded – undo
866 866
                 $this->_admin_page_title
867 867
             );
868 868
             // developer error msg
869
-            $error_msg .= '||' . $error_msg
869
+            $error_msg .= '||'.$error_msg
870 870
                           . esc_html__(
871 871
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
872 872
                               'event_espresso'
@@ -907,7 +907,7 @@  discard block
 block discarded – undo
907 907
             $this->_admin_page_title
908 908
         );
909 909
         // developer error msg
910
-        $error_msg .= '||' . $error_msg
910
+        $error_msg .= '||'.$error_msg
911 911
                       . sprintf(
912 912
                           esc_html__(
913 913
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
     protected function _verify_nonce($nonce, $nonce_ref)
933 933
     {
934 934
         // verify nonce against expected value
935
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
935
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
936 936
             // these are not the droids you are looking for !!!
937 937
             $msg = sprintf(
938 938
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -949,7 +949,7 @@  discard block
 block discarded – undo
949 949
                     __CLASS__
950 950
                 );
951 951
             }
952
-            if (! $this->request->isAjax()) {
952
+            if ( ! $this->request->isAjax()) {
953 953
                 wp_die($msg);
954 954
             }
955 955
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
      */
974 974
     protected function _route_admin_request()
975 975
     {
976
-        if (! $this->_is_UI_request) {
976
+        if ( ! $this->_is_UI_request) {
977 977
             $this->_verify_routes();
978 978
         }
979 979
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
         $error_msg = '';
994 994
         // action right before calling route
995 995
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
996
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
996
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
997 997
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
998 998
         }
999 999
         // right before calling the route, let's clean the _wp_http_referer
@@ -1005,7 +1005,7 @@  discard block
 block discarded – undo
1005 1005
         );
1006 1006
         $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri);
1007 1007
         $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri);
1008
-        if (! empty($func)) {
1008
+        if ( ! empty($func)) {
1009 1009
             if (is_array($func)) {
1010 1010
                 [$class, $method] = $func;
1011 1011
             } elseif (strpos($func, '::') !== false) {
@@ -1014,7 +1014,7 @@  discard block
 block discarded – undo
1014 1014
                 $class  = $this;
1015 1015
                 $method = $func;
1016 1016
             }
1017
-            if (! (is_object($class) && $class === $this) && ! in_array($this, $args)) {
1017
+            if ( ! (is_object($class) && $class === $this) && ! in_array($this, $args)) {
1018 1018
                 // send along this admin page object for access by addons.
1019 1019
                 $args['admin_page'] = $this;
1020 1020
             }
@@ -1055,7 +1055,7 @@  discard block
 block discarded – undo
1055 1055
                     $method
1056 1056
                 );
1057 1057
             }
1058
-            if (! empty($error_msg)) {
1058
+            if ( ! empty($error_msg)) {
1059 1059
                 throw new EE_Error($error_msg);
1060 1060
             }
1061 1061
         }
@@ -1140,7 +1140,7 @@  discard block
 block discarded – undo
1140 1140
                 if (strpos($key, 'nonce') !== false) {
1141 1141
                     continue;
1142 1142
                 }
1143
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1143
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1144 1144
             }
1145 1145
         }
1146 1146
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1179,12 +1179,12 @@  discard block
 block discarded – undo
1179 1179
      */
1180 1180
     protected function _add_help_tabs()
1181 1181
     {
1182
-        if (isset($this->_page_config[ $this->_req_action ])) {
1183
-            $config = $this->_page_config[ $this->_req_action ];
1182
+        if (isset($this->_page_config[$this->_req_action])) {
1183
+            $config = $this->_page_config[$this->_req_action];
1184 1184
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1185 1185
             if (is_array($config) && isset($config['help_sidebar'])) {
1186 1186
                 // check that the callback given is valid
1187
-                if (! method_exists($this, $config['help_sidebar'])) {
1187
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1188 1188
                     throw new EE_Error(
1189 1189
                         sprintf(
1190 1190
                             esc_html__(
@@ -1197,18 +1197,18 @@  discard block
 block discarded – undo
1197 1197
                     );
1198 1198
                 }
1199 1199
                 $content = apply_filters(
1200
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1200
+                    'FHEE__'.get_class($this).'__add_help_tabs__help_sidebar',
1201 1201
                     $this->{$config['help_sidebar']}()
1202 1202
                 );
1203 1203
                 $this->_current_screen->set_help_sidebar($content);
1204 1204
             }
1205
-            if (! isset($config['help_tabs'])) {
1205
+            if ( ! isset($config['help_tabs'])) {
1206 1206
                 return;
1207 1207
             } //no help tabs for this route
1208 1208
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1209 1209
                 // we're here so there ARE help tabs!
1210 1210
                 // make sure we've got what we need
1211
-                if (! isset($cfg['title'])) {
1211
+                if ( ! isset($cfg['title'])) {
1212 1212
                     throw new EE_Error(
1213 1213
                         esc_html__(
1214 1214
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1216,7 +1216,7 @@  discard block
 block discarded – undo
1216 1216
                         )
1217 1217
                     );
1218 1218
                 }
1219
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1219
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1220 1220
                     throw new EE_Error(
1221 1221
                         esc_html__(
1222 1222
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1225,11 +1225,11 @@  discard block
 block discarded – undo
1225 1225
                     );
1226 1226
                 }
1227 1227
                 // first priority goes to content.
1228
-                if (! empty($cfg['content'])) {
1228
+                if ( ! empty($cfg['content'])) {
1229 1229
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1230 1230
                     // second priority goes to filename
1231
-                } elseif (! empty($cfg['filename'])) {
1232
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1231
+                } elseif ( ! empty($cfg['filename'])) {
1232
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1233 1233
                     // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1234 1234
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1235 1235
                                                              . basename($this->_get_dir())
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
                                                              . $cfg['filename']
1238 1238
                                                              . '.help_tab.php' : $file_path;
1239 1239
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1240
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1240
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1241 1241
                         EE_Error::add_error(
1242 1242
                             sprintf(
1243 1243
                                 esc_html__(
@@ -1285,7 +1285,7 @@  discard block
 block discarded – undo
1285 1285
                     return;
1286 1286
                 }
1287 1287
                 // setup config array for help tab method
1288
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1288
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1289 1289
                 $_ht = [
1290 1290
                     'id'       => $id,
1291 1291
                     'title'    => $cfg['title'],
@@ -1309,8 +1309,8 @@  discard block
 block discarded – undo
1309 1309
             $qtips = (array) $this->_route_config['qtips'];
1310 1310
             // load qtip loader
1311 1311
             $path = [
1312
-                $this->_get_dir() . '/qtips/',
1313
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1312
+                $this->_get_dir().'/qtips/',
1313
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1314 1314
             ];
1315 1315
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1316 1316
         }
@@ -1332,7 +1332,7 @@  discard block
 block discarded – undo
1332 1332
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1333 1333
         $i = 0;
1334 1334
         foreach ($this->_page_config as $slug => $config) {
1335
-            if (! is_array($config) || empty($config['nav'])) {
1335
+            if ( ! is_array($config) || empty($config['nav'])) {
1336 1336
                 continue;
1337 1337
             }
1338 1338
             // no nav tab for this config
@@ -1341,12 +1341,12 @@  discard block
 block discarded – undo
1341 1341
                 // nav tab is only to appear when route requested.
1342 1342
                 continue;
1343 1343
             }
1344
-            if (! $this->check_user_access($slug, true)) {
1344
+            if ( ! $this->check_user_access($slug, true)) {
1345 1345
                 // no nav tab because current user does not have access.
1346 1346
                 continue;
1347 1347
             }
1348
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1349
-            $this->_nav_tabs[ $slug ] = [
1348
+            $css_class                = isset($config['css_class']) ? $config['css_class'].' ' : '';
1349
+            $this->_nav_tabs[$slug] = [
1350 1350
                 'url'       => isset($config['nav']['url'])
1351 1351
                     ? $config['nav']['url']
1352 1352
                     : self::add_query_args_and_nonce(
@@ -1358,14 +1358,14 @@  discard block
 block discarded – undo
1358 1358
                     : ucwords(
1359 1359
                         str_replace('_', ' ', $slug)
1360 1360
                     ),
1361
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1361
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1362 1362
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1363 1363
             ];
1364 1364
             $i++;
1365 1365
         }
1366 1366
         // if $this->_nav_tabs is empty then lets set the default
1367 1367
         if (empty($this->_nav_tabs)) {
1368
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1368
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1369 1369
                 'url'       => $this->_admin_base_url,
1370 1370
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1371 1371
                 'css_class' => 'nav-tab-active',
@@ -1390,10 +1390,10 @@  discard block
 block discarded – undo
1390 1390
             foreach ($this->_route_config['labels'] as $label => $text) {
1391 1391
                 if (is_array($text)) {
1392 1392
                     foreach ($text as $sublabel => $subtext) {
1393
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1393
+                        $this->_labels[$label][$sublabel] = $subtext;
1394 1394
                     }
1395 1395
                 } else {
1396
-                    $this->_labels[ $label ] = $text;
1396
+                    $this->_labels[$label] = $text;
1397 1397
                 }
1398 1398
             }
1399 1399
         }
@@ -1415,12 +1415,12 @@  discard block
 block discarded – undo
1415 1415
     {
1416 1416
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1417 1417
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1418
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1418
+        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1419 1419
                           && is_array(
1420
-                              $this->_page_routes[ $route_to_check ]
1420
+                              $this->_page_routes[$route_to_check]
1421 1421
                           )
1422
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1423
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1422
+                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1423
+            ? $this->_page_routes[$route_to_check]['capability'] : null;
1424 1424
         if (empty($capability) && empty($route_to_check)) {
1425 1425
             $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1426 1426
                 : $this->_route['capability'];
@@ -1540,7 +1540,7 @@  discard block
 block discarded – undo
1540 1540
         ';
1541 1541
 
1542 1542
         // current set timezone for timezone js
1543
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1543
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1544 1544
     }
1545 1545
 
1546 1546
 
@@ -1574,7 +1574,7 @@  discard block
 block discarded – undo
1574 1574
         // loop through the array and setup content
1575 1575
         foreach ($help_array as $trigger => $help) {
1576 1576
             // make sure the array is setup properly
1577
-            if (! isset($help['title']) || ! isset($help['content'])) {
1577
+            if ( ! isset($help['title']) || ! isset($help['content'])) {
1578 1578
                 throw new EE_Error(
1579 1579
                     esc_html__(
1580 1580
                         'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
@@ -1588,8 +1588,8 @@  discard block
 block discarded – undo
1588 1588
                 'help_popup_title'   => $help['title'],
1589 1589
                 'help_popup_content' => $help['content'],
1590 1590
             ];
1591
-            $content       .= EEH_Template::display_template(
1592
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1591
+            $content .= EEH_Template::display_template(
1592
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1593 1593
                 $template_args,
1594 1594
                 true
1595 1595
             );
@@ -1611,15 +1611,15 @@  discard block
 block discarded – undo
1611 1611
     private function _get_help_content()
1612 1612
     {
1613 1613
         // what is the method we're looking for?
1614
-        $method_name = '_help_popup_content_' . $this->_req_action;
1614
+        $method_name = '_help_popup_content_'.$this->_req_action;
1615 1615
         // if method doesn't exist let's get out.
1616
-        if (! method_exists($this, $method_name)) {
1616
+        if ( ! method_exists($this, $method_name)) {
1617 1617
             return [];
1618 1618
         }
1619 1619
         // k we're good to go let's retrieve the help array
1620 1620
         $help_array = call_user_func([$this, $method_name]);
1621 1621
         // make sure we've got an array!
1622
-        if (! is_array($help_array)) {
1622
+        if ( ! is_array($help_array)) {
1623 1623
             throw new EE_Error(
1624 1624
                 esc_html__(
1625 1625
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1651,15 +1651,15 @@  discard block
 block discarded – undo
1651 1651
         // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1652 1652
         $help_array   = $this->_get_help_content();
1653 1653
         $help_content = '';
1654
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1655
-            $help_array[ $trigger_id ] = [
1654
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1655
+            $help_array[$trigger_id] = [
1656 1656
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1657 1657
                 'content' => esc_html__(
1658 1658
                     'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1659 1659
                     'event_espresso'
1660 1660
                 ),
1661 1661
             ];
1662
-            $help_content              = $this->_set_help_popup_content($help_array);
1662
+            $help_content = $this->_set_help_popup_content($help_array);
1663 1663
         }
1664 1664
         // let's setup the trigger
1665 1665
         $content = '<a class="ee-dialog" href="?height='
@@ -1727,15 +1727,15 @@  discard block
 block discarded – undo
1727 1727
         // register all styles
1728 1728
         wp_register_style(
1729 1729
             'espresso-ui-theme',
1730
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1730
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1731 1731
             [],
1732 1732
             EVENT_ESPRESSO_VERSION
1733 1733
         );
1734
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1734
+        wp_register_style('ee-admin-css', EE_ADMIN_URL.'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1735 1735
         // helpers styles
1736 1736
         wp_register_style(
1737 1737
             'ee-text-links',
1738
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1738
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.css',
1739 1739
             [],
1740 1740
             EVENT_ESPRESSO_VERSION
1741 1741
         );
@@ -1743,21 +1743,21 @@  discard block
 block discarded – undo
1743 1743
         // register all scripts
1744 1744
         wp_register_script(
1745 1745
             'ee-dialog',
1746
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1746
+            EE_ADMIN_URL.'assets/ee-dialog-helper.js',
1747 1747
             ['jquery', 'jquery-ui-draggable'],
1748 1748
             EVENT_ESPRESSO_VERSION,
1749 1749
             true
1750 1750
         );
1751 1751
         wp_register_script(
1752 1752
             'ee_admin_js',
1753
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1753
+            EE_ADMIN_URL.'assets/ee-admin-page.js',
1754 1754
             ['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1755 1755
             EVENT_ESPRESSO_VERSION,
1756 1756
             true
1757 1757
         );
1758 1758
         wp_register_script(
1759 1759
             'jquery-ui-timepicker-addon',
1760
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1760
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery-ui-timepicker-addon.js',
1761 1761
             ['jquery-ui-datepicker', 'jquery-ui-slider'],
1762 1762
             EVENT_ESPRESSO_VERSION,
1763 1763
             true
@@ -1765,7 +1765,7 @@  discard block
 block discarded – undo
1765 1765
         // script for sorting tables
1766 1766
         wp_register_script(
1767 1767
             'espresso_ajax_table_sorting',
1768
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1768
+            EE_ADMIN_URL.'assets/espresso_ajax_table_sorting.js',
1769 1769
             ['ee_admin_js', 'jquery-ui-sortable'],
1770 1770
             EVENT_ESPRESSO_VERSION,
1771 1771
             true
@@ -1773,7 +1773,7 @@  discard block
 block discarded – undo
1773 1773
         // script for parsing uri's
1774 1774
         wp_register_script(
1775 1775
             'ee-parse-uri',
1776
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1776
+            EE_GLOBAL_ASSETS_URL.'scripts/parseuri.js',
1777 1777
             [],
1778 1778
             EVENT_ESPRESSO_VERSION,
1779 1779
             true
@@ -1781,7 +1781,7 @@  discard block
 block discarded – undo
1781 1781
         // and parsing associative serialized form elements
1782 1782
         wp_register_script(
1783 1783
             'ee-serialize-full-array',
1784
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1784
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.serializefullarray.js',
1785 1785
             ['jquery'],
1786 1786
             EVENT_ESPRESSO_VERSION,
1787 1787
             true
@@ -1789,28 +1789,28 @@  discard block
 block discarded – undo
1789 1789
         // helpers scripts
1790 1790
         wp_register_script(
1791 1791
             'ee-text-links',
1792
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1792
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.js',
1793 1793
             ['jquery'],
1794 1794
             EVENT_ESPRESSO_VERSION,
1795 1795
             true
1796 1796
         );
1797 1797
         wp_register_script(
1798 1798
             'ee-moment-core',
1799
-            EE_GLOBAL_ASSETS_URL . 'moment/moment-with-locales.min.js',
1799
+            EE_GLOBAL_ASSETS_URL.'moment/moment-with-locales.min.js',
1800 1800
             [],
1801 1801
             EVENT_ESPRESSO_VERSION,
1802 1802
             true
1803 1803
         );
1804 1804
         wp_register_script(
1805 1805
             'ee-moment',
1806
-            EE_GLOBAL_ASSETS_URL . 'moment/moment-timezone-with-data.min.js',
1806
+            EE_GLOBAL_ASSETS_URL.'moment/moment-timezone-with-data.min.js',
1807 1807
             ['ee-moment-core'],
1808 1808
             EVENT_ESPRESSO_VERSION,
1809 1809
             true
1810 1810
         );
1811 1811
         wp_register_script(
1812 1812
             'ee-datepicker',
1813
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1813
+            EE_ADMIN_URL.'assets/ee-datepicker.js',
1814 1814
             ['jquery-ui-timepicker-addon', 'ee-moment'],
1815 1815
             EVENT_ESPRESSO_VERSION,
1816 1816
             true
@@ -1843,7 +1843,7 @@  discard block
 block discarded – undo
1843 1843
         wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1844 1844
         add_filter(
1845 1845
             'admin_body_class',
1846
-            function ($classes) {
1846
+            function($classes) {
1847 1847
                 if (strpos($classes, 'espresso-admin') === false) {
1848 1848
                     $classes .= ' espresso-admin';
1849 1849
                 }
@@ -1931,12 +1931,12 @@  discard block
 block discarded – undo
1931 1931
     protected function _set_list_table()
1932 1932
     {
1933 1933
         // first is this a list_table view?
1934
-        if (! isset($this->_route_config['list_table'])) {
1934
+        if ( ! isset($this->_route_config['list_table'])) {
1935 1935
             return;
1936 1936
         } //not a list_table view so get out.
1937 1937
         // list table functions are per view specific (because some admin pages might have more than one list table!)
1938
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1939
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1938
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
1939
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1940 1940
             // user error msg
1941 1941
             $error_msg = esc_html__(
1942 1942
                 'An error occurred. The requested list table views could not be found.',
@@ -1956,10 +1956,10 @@  discard block
 block discarded – undo
1956 1956
         }
1957 1957
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1958 1958
         $this->_views = apply_filters(
1959
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
1959
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
1960 1960
             $this->_views
1961 1961
         );
1962
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1962
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
1963 1963
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1964 1964
         $this->_set_list_table_view();
1965 1965
         $this->_set_list_table_object();
@@ -1994,7 +1994,7 @@  discard block
 block discarded – undo
1994 1994
     protected function _set_list_table_object()
1995 1995
     {
1996 1996
         if (isset($this->_route_config['list_table'])) {
1997
-            if (! class_exists($this->_route_config['list_table'])) {
1997
+            if ( ! class_exists($this->_route_config['list_table'])) {
1998 1998
                 throw new EE_Error(
1999 1999
                     sprintf(
2000 2000
                         esc_html__(
@@ -2032,15 +2032,15 @@  discard block
 block discarded – undo
2032 2032
         foreach ($this->_views as $key => $view) {
2033 2033
             $query_args = [];
2034 2034
             // check for current view
2035
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2035
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2036 2036
             $query_args['action']                        = $this->_req_action;
2037
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2037
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2038 2038
             $query_args['status']                        = $view['slug'];
2039 2039
             // merge any other arguments sent in.
2040
-            if (isset($extra_query_args[ $view['slug'] ])) {
2041
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2040
+            if (isset($extra_query_args[$view['slug']])) {
2041
+                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2042 2042
             }
2043
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2043
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2044 2044
         }
2045 2045
         return $this->_views;
2046 2046
     }
@@ -2071,14 +2071,14 @@  discard block
 block discarded – undo
2071 2071
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2072 2072
         foreach ($values as $value) {
2073 2073
             if ($value < $max_entries) {
2074
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2074
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2075 2075
                 $entries_per_page_dropdown .= '
2076
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2076
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2077 2077
             }
2078 2078
         }
2079
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2079
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2080 2080
         $entries_per_page_dropdown .= '
2081
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2081
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2082 2082
         $entries_per_page_dropdown .= '
2083 2083
 					</select>
2084 2084
 					entries
@@ -2102,7 +2102,7 @@  discard block
 block discarded – undo
2102 2102
             empty($this->_search_btn_label) ? $this->page_label
2103 2103
                 : $this->_search_btn_label
2104 2104
         );
2105
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2105
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2106 2106
     }
2107 2107
 
2108 2108
 
@@ -2190,7 +2190,7 @@  discard block
 block discarded – undo
2190 2190
             $total_columns                                       = ! empty($screen_columns)
2191 2191
                 ? $screen_columns
2192 2192
                 : $this->_route_config['columns'][1];
2193
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2193
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2194 2194
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2195 2195
             $this->_template_args['screen']                      = $this->_current_screen;
2196 2196
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2235,7 +2235,7 @@  discard block
 block discarded – undo
2235 2235
      */
2236 2236
     protected function _espresso_ratings_request()
2237 2237
     {
2238
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2238
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2239 2239
             return;
2240 2240
         }
2241 2241
         $ratings_box_title = apply_filters(
@@ -2263,7 +2263,7 @@  discard block
 block discarded – undo
2263 2263
     public function espresso_ratings_request()
2264 2264
     {
2265 2265
         EEH_Template::display_template(
2266
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2266
+            EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php',
2267 2267
             []
2268 2268
         );
2269 2269
     }
@@ -2271,22 +2271,22 @@  discard block
 block discarded – undo
2271 2271
 
2272 2272
     public static function cached_rss_display($rss_id, $url)
2273 2273
     {
2274
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2274
+        $loading = '<p class="widget-loading hide-if-no-js">'
2275 2275
                      . esc_html__('Loading&#8230;', 'event_espresso')
2276 2276
                      . '</p><p class="hide-if-js">'
2277 2277
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2278 2278
                      . '</p>';
2279
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2280
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2281
-        $post      = '</div>' . "\n";
2282
-        $cache_key = 'ee_rss_' . md5($rss_id);
2279
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2280
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2281
+        $post      = '</div>'."\n";
2282
+        $cache_key = 'ee_rss_'.md5($rss_id);
2283 2283
         $output    = get_transient($cache_key);
2284 2284
         if ($output !== false) {
2285
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2285
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2286 2286
             return true;
2287 2287
         }
2288
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2289
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2288
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2289
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2290 2290
             return false;
2291 2291
         }
2292 2292
         ob_start();
@@ -2353,19 +2353,19 @@  discard block
 block discarded – undo
2353 2353
     public function espresso_sponsors_post_box()
2354 2354
     {
2355 2355
         EEH_Template::display_template(
2356
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2356
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2357 2357
         );
2358 2358
     }
2359 2359
 
2360 2360
 
2361 2361
     private function _publish_post_box()
2362 2362
     {
2363
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2363
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2364 2364
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2365 2365
         // then we'll use that for the metabox label.
2366 2366
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2367
-        if (! empty($this->_labels['publishbox'])) {
2368
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2367
+        if ( ! empty($this->_labels['publishbox'])) {
2368
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2369 2369
                 : $this->_labels['publishbox'];
2370 2370
         } else {
2371 2371
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2394,7 +2394,7 @@  discard block
 block discarded – undo
2394 2394
             ? $this->_template_args['publish_box_extra_content']
2395 2395
             : '';
2396 2396
         echo EEH_Template::display_template(
2397
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2397
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2398 2398
             $this->_template_args,
2399 2399
             true
2400 2400
         );
@@ -2486,18 +2486,18 @@  discard block
 block discarded – undo
2486 2486
             );
2487 2487
         }
2488 2488
         $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2489
-        if (! empty($name) && ! empty($id)) {
2490
-            $hidden_field_arr[ $name ] = [
2489
+        if ( ! empty($name) && ! empty($id)) {
2490
+            $hidden_field_arr[$name] = [
2491 2491
                 'type'  => 'hidden',
2492 2492
                 'value' => $id,
2493 2493
             ];
2494
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2494
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2495 2495
         } else {
2496 2496
             $hf = '';
2497 2497
         }
2498 2498
         // add hidden field
2499 2499
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2500
-            ? $hf[ $name ]['field']
2500
+            ? $hf[$name]['field']
2501 2501
             : $hf;
2502 2502
     }
2503 2503
 
@@ -2599,7 +2599,7 @@  discard block
 block discarded – undo
2599 2599
         }
2600 2600
         // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2601 2601
         $call_back_func = $create_func
2602
-            ? function ($post, $metabox) {
2602
+            ? function($post, $metabox) {
2603 2603
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2604 2604
                 echo EEH_Template::display_template(
2605 2605
                     $metabox['args']['template_path'],
@@ -2609,7 +2609,7 @@  discard block
 block discarded – undo
2609 2609
             }
2610 2610
             : $callback;
2611 2611
         add_meta_box(
2612
-            str_replace('_', '-', $action) . '-mbox',
2612
+            str_replace('_', '-', $action).'-mbox',
2613 2613
             $title,
2614 2614
             $call_back_func,
2615 2615
             $this->_wp_page_slug,
@@ -2701,9 +2701,9 @@  discard block
 block discarded – undo
2701 2701
             : 'espresso-default-admin';
2702 2702
         $template_path                                     = $sidebar
2703 2703
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2704
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2704
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2705 2705
         if ($this->request->isAjax()) {
2706
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2706
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2707 2707
         }
2708 2708
         $template_path                                     = ! empty($this->_column_template_path)
2709 2709
             ? $this->_column_template_path : $template_path;
@@ -2743,11 +2743,11 @@  discard block
 block discarded – undo
2743 2743
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2744 2744
     {
2745 2745
         // let's generate a default preview action button if there isn't one already present.
2746
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2746
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2747 2747
             'Upgrade to Event Espresso 4 Right Now',
2748 2748
             'event_espresso'
2749 2749
         );
2750
-        $buy_now_url                                   = add_query_arg(
2750
+        $buy_now_url = add_query_arg(
2751 2751
             [
2752 2752
                 'ee_ver'       => 'ee4',
2753 2753
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2767,8 +2767,8 @@  discard block
 block discarded – undo
2767 2767
                 true
2768 2768
             )
2769 2769
             : $this->_template_args['preview_action_button'];
2770
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2771
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2770
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2771
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2772 2772
             $this->_template_args,
2773 2773
             true
2774 2774
         );
@@ -2817,7 +2817,7 @@  discard block
 block discarded – undo
2817 2817
         // setup search attributes
2818 2818
         $this->_set_search_attributes();
2819 2819
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2820
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2820
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2821 2821
         $this->_template_args['table_url']        = $this->request->isAjax()
2822 2822
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2823 2823
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2825,10 +2825,10 @@  discard block
 block discarded – undo
2825 2825
         $this->_template_args['current_route']    = $this->_req_action;
2826 2826
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2827 2827
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2828
-        if (! empty($ajax_sorting_callback)) {
2828
+        if ( ! empty($ajax_sorting_callback)) {
2829 2829
             $sortable_list_table_form_fields = wp_nonce_field(
2830
-                $ajax_sorting_callback . '_nonce',
2831
-                $ajax_sorting_callback . '_nonce',
2830
+                $ajax_sorting_callback.'_nonce',
2831
+                $ajax_sorting_callback.'_nonce',
2832 2832
                 false,
2833 2833
                 false
2834 2834
             );
@@ -2847,18 +2847,18 @@  discard block
 block discarded – undo
2847 2847
                 ? $this->_template_args['list_table_hidden_fields']
2848 2848
                 : '';
2849 2849
 
2850
-        $nonce_ref          = $this->_req_action . '_nonce';
2850
+        $nonce_ref = $this->_req_action.'_nonce';
2851 2851
         $hidden_form_fields .= '
2852
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2852
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2853 2853
 
2854
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2854
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2855 2855
         // display message about search results?
2856 2856
         $search = $this->request->getRequestParam('s');
2857 2857
         $this->_template_args['before_list_table'] .= ! empty($search)
2858
-            ? '<p class="ee-search-results">' . sprintf(
2858
+            ? '<p class="ee-search-results">'.sprintf(
2859 2859
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2860 2860
                 trim($search, '%')
2861
-            ) . '</p>'
2861
+            ).'</p>'
2862 2862
             : '';
2863 2863
         // filter before_list_table template arg
2864 2864
         $this->_template_args['before_list_table'] = apply_filters(
@@ -2892,7 +2892,7 @@  discard block
 block discarded – undo
2892 2892
         // convert to array and filter again
2893 2893
         // arrays are easier to inject new items in a specific location,
2894 2894
         // but would not be backwards compatible, so we have to add a new filter
2895
-        $this->_template_args['after_list_table']   = implode(
2895
+        $this->_template_args['after_list_table'] = implode(
2896 2896
             " \n",
2897 2897
             (array) apply_filters(
2898 2898
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -2939,7 +2939,7 @@  discard block
 block discarded – undo
2939 2939
             $this
2940 2940
         );
2941 2941
         return EEH_Template::display_template(
2942
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
2942
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
2943 2943
             $this->_template_args,
2944 2944
             true
2945 2945
         );
@@ -3048,18 +3048,18 @@  discard block
 block discarded – undo
3048 3048
                 : ''
3049 3049
         );
3050 3050
 
3051
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3051
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3052 3052
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3053 3053
             isset($this->_template_args['after_admin_page_content'])
3054 3054
                 ? $this->_template_args['after_admin_page_content']
3055 3055
                 : ''
3056 3056
         );
3057
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3057
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3058 3058
 
3059 3059
         if ($this->request->isAjax()) {
3060 3060
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3061 3061
                 // $template_path,
3062
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3062
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3063 3063
                 $this->_template_args,
3064 3064
                 true
3065 3065
             );
@@ -3068,7 +3068,7 @@  discard block
 block discarded – undo
3068 3068
         // load settings page wrapper template
3069 3069
         $template_path = $about
3070 3070
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3071
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3071
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3072 3072
 
3073 3073
         EEH_Template::display_template($template_path, $this->_template_args);
3074 3074
     }
@@ -3153,12 +3153,12 @@  discard block
 block discarded – undo
3153 3153
         $default_names = ['save', 'save_and_close'];
3154 3154
         $buttons = '';
3155 3155
         foreach ($button_text as $key => $button) {
3156
-            $ref     = $default_names[ $key ];
3157
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3158
-            $buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3159
-                        . 'value="' . $button . '" name="' . $name . '" '
3160
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3161
-            if (! $both) {
3156
+            $ref     = $default_names[$key];
3157
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3158
+            $buttons .= '<input type="submit" class="button-primary '.$ref.'" '
3159
+                        . 'value="'.$button.'" name="'.$name.'" '
3160
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3161
+            if ( ! $both) {
3162 3162
                 break;
3163 3163
             }
3164 3164
         }
@@ -3198,13 +3198,13 @@  discard block
 block discarded – undo
3198 3198
                 'An error occurred. No action was set for this page\'s form.',
3199 3199
                 'event_espresso'
3200 3200
             );
3201
-            $dev_msg  = $user_msg . "\n"
3201
+            $dev_msg = $user_msg."\n"
3202 3202
                         . sprintf(
3203 3203
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3204 3204
                             __FUNCTION__,
3205 3205
                             __CLASS__
3206 3206
                         );
3207
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3207
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3208 3208
         }
3209 3209
         // open form
3210 3210
         $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
@@ -3213,9 +3213,9 @@  discard block
 block discarded – undo
3213 3213
                                                              . $route
3214 3214
                                                              . '_event_form" >';
3215 3215
         // add nonce
3216
-        $nonce                                             =
3217
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3218
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3216
+        $nonce =
3217
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3218
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3219 3219
         // add REQUIRED form action
3220 3220
         $hidden_fields = [
3221 3221
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3228,7 +3228,7 @@  discard block
 block discarded – undo
3228 3228
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3229 3229
         // add fields to form
3230 3230
         foreach ((array) $form_fields as $form_field) {
3231
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3231
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3232 3232
         }
3233 3233
         // close form
3234 3234
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3319,10 +3319,10 @@  discard block
 block discarded – undo
3319 3319
         $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3320 3320
         $notices      = EE_Error::get_notices(false);
3321 3321
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3322
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3322
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3323 3323
             EE_Error::overwrite_success();
3324 3324
         }
3325
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3325
+        if ( ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3326 3326
             // how many records affected ? more than one record ? or just one ?
3327 3327
             if ($success > 1) {
3328 3328
                 // set plural msg
@@ -3351,7 +3351,7 @@  discard block
 block discarded – undo
3351 3351
             }
3352 3352
         }
3353 3353
         // check that $query_args isn't something crazy
3354
-        if (! is_array($query_args)) {
3354
+        if ( ! is_array($query_args)) {
3355 3355
             $query_args = [];
3356 3356
         }
3357 3357
         /**
@@ -3380,7 +3380,7 @@  discard block
 block discarded – undo
3380 3380
             $redirect_url = admin_url('admin.php');
3381 3381
         }
3382 3382
         // merge any default query_args set in _default_route_query_args property
3383
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3383
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3384 3384
             $args_to_merge = [];
3385 3385
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3386 3386
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3392,15 +3392,15 @@  discard block
 block discarded – undo
3392 3392
                         }
3393 3393
                         // finally we will override any arguments in the referer with
3394 3394
                         // what might be set on the _default_route_query_args array.
3395
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3396
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3395
+                        if (isset($this->_default_route_query_args[$reference])) {
3396
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3397 3397
                         } else {
3398
-                            $args_to_merge[ $reference ] = urlencode($value);
3398
+                            $args_to_merge[$reference] = urlencode($value);
3399 3399
                         }
3400 3400
                     }
3401 3401
                     continue;
3402 3402
                 }
3403
-                $args_to_merge[ $query_param ] = $query_value;
3403
+                $args_to_merge[$query_param] = $query_value;
3404 3404
             }
3405 3405
             // now let's merge these arguments but override with what was specifically sent in to the
3406 3406
             // redirect.
@@ -3412,19 +3412,19 @@  discard block
 block discarded – undo
3412 3412
         if (isset($query_args['action'])) {
3413 3413
             // manually generate wp_nonce and merge that with the query vars
3414 3414
             // becuz the wp_nonce_url function wrecks havoc on some vars
3415
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3415
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3416 3416
         }
3417 3417
         // we're adding some hooks and filters in here for processing any things just before redirects
3418 3418
         // (example: an admin page has done an insert or update and we want to run something after that).
3419
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3419
+        do_action('AHEE_redirect_'.$classname.$this->_req_action, $query_args);
3420 3420
         $redirect_url = apply_filters(
3421
-            'FHEE_redirect_' . $classname . $this->_req_action,
3421
+            'FHEE_redirect_'.$classname.$this->_req_action,
3422 3422
             self::add_query_args_and_nonce($query_args, $redirect_url),
3423 3423
             $query_args
3424 3424
         );
3425 3425
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3426 3426
         if ($this->request->isAjax()) {
3427
-            $default_data                    = [
3427
+            $default_data = [
3428 3428
                 'close'        => true,
3429 3429
                 'redirect_url' => $redirect_url,
3430 3430
                 'where'        => 'main',
@@ -3471,7 +3471,7 @@  discard block
 block discarded – undo
3471 3471
         }
3472 3472
         $this->_template_args['notices'] = EE_Error::get_notices();
3473 3473
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3474
-        if (! $this->request->isAjax() || $sticky_notices) {
3474
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3475 3475
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3476 3476
             $this->_add_transient(
3477 3477
                 $route,
@@ -3511,7 +3511,7 @@  discard block
 block discarded – undo
3511 3511
         $exclude_nonce = false
3512 3512
     ) {
3513 3513
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3514
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3514
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3515 3515
             throw new EE_Error(
3516 3516
                 sprintf(
3517 3517
                     esc_html__(
@@ -3522,7 +3522,7 @@  discard block
 block discarded – undo
3522 3522
                 )
3523 3523
             );
3524 3524
         }
3525
-        if (! isset($this->_labels['buttons'][ $type ])) {
3525
+        if ( ! isset($this->_labels['buttons'][$type])) {
3526 3526
             throw new EE_Error(
3527 3527
                 sprintf(
3528 3528
                     esc_html__(
@@ -3535,7 +3535,7 @@  discard block
 block discarded – undo
3535 3535
         }
3536 3536
         // finally check user access for this button.
3537 3537
         $has_access = $this->check_user_access($action, true);
3538
-        if (! $has_access) {
3538
+        if ( ! $has_access) {
3539 3539
             return '';
3540 3540
         }
3541 3541
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3543,11 +3543,11 @@  discard block
 block discarded – undo
3543 3543
             'action' => $action,
3544 3544
         ];
3545 3545
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3546
-        if (! empty($extra_request)) {
3546
+        if ( ! empty($extra_request)) {
3547 3547
             $query_args = array_merge($extra_request, $query_args);
3548 3548
         }
3549 3549
         $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3550
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3550
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3551 3551
     }
3552 3552
 
3553 3553
 
@@ -3573,7 +3573,7 @@  discard block
 block discarded – undo
3573 3573
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3574 3574
                 20
3575 3575
             ),
3576
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3576
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3577 3577
         ];
3578 3578
         // ONLY add the screen option if the user has access to it.
3579 3579
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3594,18 +3594,18 @@  discard block
 block discarded – undo
3594 3594
     {
3595 3595
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3596 3596
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3597
-            if (! $user = wp_get_current_user()) {
3597
+            if ( ! $user = wp_get_current_user()) {
3598 3598
                 return;
3599 3599
             }
3600 3600
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3601
-            if (! $option) {
3601
+            if ( ! $option) {
3602 3602
                 return;
3603 3603
             }
3604
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3604
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3605 3605
             $map_option = $option;
3606 3606
             $option     = str_replace('-', '_', $option);
3607 3607
             switch ($map_option) {
3608
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3608
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3609 3609
                     $max_value = apply_filters(
3610 3610
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3611 3611
                         999,
@@ -3662,13 +3662,13 @@  discard block
 block discarded – undo
3662 3662
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3663 3663
     {
3664 3664
         $user_id = get_current_user_id();
3665
-        if (! $skip_route_verify) {
3665
+        if ( ! $skip_route_verify) {
3666 3666
             $this->_verify_route($route);
3667 3667
         }
3668 3668
         // now let's set the string for what kind of transient we're setting
3669 3669
         $transient = $notices
3670
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3671
-            : 'rte_tx_' . $route . '_' . $user_id;
3670
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3671
+            : 'rte_tx_'.$route.'_'.$user_id;
3672 3672
         $data      = $notices ? ['notices' => $data] : $data;
3673 3673
         // is there already a transient for this route?  If there is then let's ADD to that transient
3674 3674
         $existing = is_multisite() && is_network_admin()
@@ -3697,8 +3697,8 @@  discard block
 block discarded – undo
3697 3697
         $user_id   = get_current_user_id();
3698 3698
         $route     = ! $route ? $this->_req_action : $route;
3699 3699
         $transient = $notices
3700
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3701
-            : 'rte_tx_' . $route . '_' . $user_id;
3700
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3701
+            : 'rte_tx_'.$route.'_'.$user_id;
3702 3702
         $data      = is_multisite() && is_network_admin()
3703 3703
             ? get_site_transient($transient)
3704 3704
             : get_transient($transient);
@@ -3929,7 +3929,7 @@  discard block
 block discarded – undo
3929 3929
      */
3930 3930
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3931 3931
     {
3932
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3932
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
3933 3933
     }
3934 3934
 
3935 3935
 
@@ -3942,7 +3942,7 @@  discard block
 block discarded – undo
3942 3942
      */
3943 3943
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3944 3944
     {
3945
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3945
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
3946 3946
     }
3947 3947
 
3948 3948
 
@@ -4090,13 +4090,13 @@  discard block
 block discarded – undo
4090 4090
         callable $callback = null
4091 4091
     ) {
4092 4092
         $entity_ID = absint($entity_ID);
4093
-        if (! $entity_ID) {
4093
+        if ( ! $entity_ID) {
4094 4094
             $this->trashRestoreDeleteError($action, $entity_model);
4095 4095
         }
4096 4096
         $result = 0;
4097 4097
         try {
4098 4098
             $entity = $entity_model->get_one_by_ID($entity_ID);
4099
-            if (! $entity instanceof EE_Base_Class) {
4099
+            if ( ! $entity instanceof EE_Base_Class) {
4100 4100
                 throw new DomainException(
4101 4101
                     sprintf(
4102 4102
                         esc_html__(
@@ -4147,7 +4147,7 @@  discard block
 block discarded – undo
4147 4147
                 )
4148 4148
             );
4149 4149
         }
4150
-        if (! $entity_model->has_field($delete_column)) {
4150
+        if ( ! $entity_model->has_field($delete_column)) {
4151 4151
             throw new DomainException(
4152 4152
                 sprintf(
4153 4153
                     esc_html__(
Please login to merge, or discard this patch.
core/EE_Deprecated.core.php 2 patches
Indentation   +1222 added lines, -1222 removed lines patch added patch discarded remove patch
@@ -39,31 +39,31 @@  discard block
 block discarded – undo
39 39
  * @param string $action_or_filter
40 40
  */
41 41
 function deprecated_espresso_action_or_filter_doing_it_wrong(
42
-    $deprecated_filter,
43
-    $replacement,
44
-    $replacement_location,
45
-    $version_deprecated,
46
-    $version_applies,
47
-    $action_or_filter = 'action'
42
+	$deprecated_filter,
43
+	$replacement,
44
+	$replacement_location,
45
+	$version_deprecated,
46
+	$version_applies,
47
+	$action_or_filter = 'action'
48 48
 ) {
49
-    $action_or_filter = $action_or_filter === 'action'
50
-        ? esc_html__('action', 'event_espresso')
51
-        : esc_html__('filter', 'event_espresso');
52
-    EE_Error::doing_it_wrong(
53
-        $deprecated_filter,
54
-        sprintf(
55
-            esc_html__(
56
-                'This %1$s is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new %1$s: %4$s"%2$s" found in "%3$s"',
57
-                'event_espresso'
58
-            ),
59
-            $action_or_filter,
60
-            $replacement,
61
-            $replacement_location,
62
-            '<br />'
63
-        ),
64
-        $version_deprecated,
65
-        $version_applies
66
-    );
49
+	$action_or_filter = $action_or_filter === 'action'
50
+		? esc_html__('action', 'event_espresso')
51
+		: esc_html__('filter', 'event_espresso');
52
+	EE_Error::doing_it_wrong(
53
+		$deprecated_filter,
54
+		sprintf(
55
+			esc_html__(
56
+				'This %1$s is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new %1$s: %4$s"%2$s" found in "%3$s"',
57
+				'event_espresso'
58
+			),
59
+			$action_or_filter,
60
+			$replacement,
61
+			$replacement_location,
62
+			'<br />'
63
+		),
64
+		$version_deprecated,
65
+		$version_applies
66
+	);
67 67
 }
68 68
 
69 69
 /**
@@ -75,90 +75,90 @@  discard block
 block discarded – undo
75 75
  */
76 76
 function ee_deprecated__registration_checkout__button_text($submit_button_text, EE_Checkout $checkout)
77 77
 {
78
-    // list of old filters
79
-    $deprecated_filters = array(
80
-        'update_registration_details' => true,
81
-        'process_payment'             => true,
82
-        'finalize_registration'       => true,
83
-        'and_proceed_to_payment'      => true,
84
-        'proceed_to'                  => true,
85
-    );
86
-    // loop thru and call doing_it_wrong() or remove any that aren't being used
87
-    foreach ($deprecated_filters as $deprecated_filter => $on) {
88
-        // was this filter called ?
89
-        if (has_action('FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter)) {
90
-            // only display doing_it_wrong() notice to Event Admins during non-AJAX requests
91
-            if (EE_Registry::instance()->CAP->current_user_can(
92
-                    'ee_read_ee',
93
-                    'hide_doing_it_wrong_for_deprecated_SPCO_filter'
94
-                ) && ! defined('DOING_AJAX')) {
95
-                EE_Error::doing_it_wrong(
96
-                    'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
97
-                    sprintf(
98
-                        esc_html__(
99
-                            'The %1$s filter is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new filter: %2$s"%3$s" found in "%4$s"',
100
-                            'event_espresso'
101
-                        ),
102
-                        'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
103
-                        '<br />',
104
-                        'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
105
-                        '/modules/single_page_checkout/inc/EE_SPCO_Reg_Step.class.php'
106
-                    ),
107
-                    '4.6.10'
108
-                );
109
-            }
110
-        } else {
111
-            unset($deprecated_filters[ $deprecated_filter ]);
112
-        }
113
-    }
114
-    if (! empty($deprecated_filters)) {
115
-
116
-        if ($checkout->current_step->slug(
117
-            ) == 'attendee_information' && $checkout->revisit && isset($deprecated_filters['update_registration_details'])) {
118
-            $submit_button_text = apply_filters(
119
-                'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__update_registration_details',
120
-                $submit_button_text
121
-            );
122
-        } elseif ($checkout->current_step->slug(
123
-            ) == 'payment_options' && $checkout->revisit && isset($deprecated_filters['process_payment'])) {
124
-            $submit_button_text = apply_filters(
125
-                'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__process_payment',
126
-                $submit_button_text
127
-            );
128
-        } elseif ($checkout->next_step instanceof EE_SPCO_Reg_Step && $checkout->next_step->slug(
129
-            ) == 'finalize_registration' && isset($deprecated_filters['finalize_registration'])) {
130
-            $submit_button_text = apply_filters(
131
-                'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__finalize_registration',
132
-                $submit_button_text
133
-            );
134
-        }
135
-        if ($checkout->next_step instanceof EE_SPCO_Reg_Step) {
136
-            if ($checkout->payment_required() && $checkout->next_step->slug(
137
-                ) == 'payment_options' && isset($deprecated_filters['and_proceed_to_payment'])) {
138
-                $submit_button_text .= apply_filters(
139
-                    'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__and_proceed_to_payment',
140
-                    $submit_button_text
141
-                );
142
-            }
143
-            if ($checkout->next_step->slug(
144
-                ) != 'finalize_registration' && ! $checkout->revisit && isset($deprecated_filters['proceed_to'])) {
145
-                $submit_button_text = apply_filters(
146
-                                          'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__proceed_to',
147
-                                          $submit_button_text
148
-                                      ) . $checkout->next_step->name();
149
-            }
150
-        }
151
-
152
-    }
153
-    return $submit_button_text;
78
+	// list of old filters
79
+	$deprecated_filters = array(
80
+		'update_registration_details' => true,
81
+		'process_payment'             => true,
82
+		'finalize_registration'       => true,
83
+		'and_proceed_to_payment'      => true,
84
+		'proceed_to'                  => true,
85
+	);
86
+	// loop thru and call doing_it_wrong() or remove any that aren't being used
87
+	foreach ($deprecated_filters as $deprecated_filter => $on) {
88
+		// was this filter called ?
89
+		if (has_action('FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter)) {
90
+			// only display doing_it_wrong() notice to Event Admins during non-AJAX requests
91
+			if (EE_Registry::instance()->CAP->current_user_can(
92
+					'ee_read_ee',
93
+					'hide_doing_it_wrong_for_deprecated_SPCO_filter'
94
+				) && ! defined('DOING_AJAX')) {
95
+				EE_Error::doing_it_wrong(
96
+					'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
97
+					sprintf(
98
+						esc_html__(
99
+							'The %1$s filter is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new filter: %2$s"%3$s" found in "%4$s"',
100
+							'event_espresso'
101
+						),
102
+						'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
103
+						'<br />',
104
+						'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
105
+						'/modules/single_page_checkout/inc/EE_SPCO_Reg_Step.class.php'
106
+					),
107
+					'4.6.10'
108
+				);
109
+			}
110
+		} else {
111
+			unset($deprecated_filters[ $deprecated_filter ]);
112
+		}
113
+	}
114
+	if (! empty($deprecated_filters)) {
115
+
116
+		if ($checkout->current_step->slug(
117
+			) == 'attendee_information' && $checkout->revisit && isset($deprecated_filters['update_registration_details'])) {
118
+			$submit_button_text = apply_filters(
119
+				'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__update_registration_details',
120
+				$submit_button_text
121
+			);
122
+		} elseif ($checkout->current_step->slug(
123
+			) == 'payment_options' && $checkout->revisit && isset($deprecated_filters['process_payment'])) {
124
+			$submit_button_text = apply_filters(
125
+				'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__process_payment',
126
+				$submit_button_text
127
+			);
128
+		} elseif ($checkout->next_step instanceof EE_SPCO_Reg_Step && $checkout->next_step->slug(
129
+			) == 'finalize_registration' && isset($deprecated_filters['finalize_registration'])) {
130
+			$submit_button_text = apply_filters(
131
+				'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__finalize_registration',
132
+				$submit_button_text
133
+			);
134
+		}
135
+		if ($checkout->next_step instanceof EE_SPCO_Reg_Step) {
136
+			if ($checkout->payment_required() && $checkout->next_step->slug(
137
+				) == 'payment_options' && isset($deprecated_filters['and_proceed_to_payment'])) {
138
+				$submit_button_text .= apply_filters(
139
+					'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__and_proceed_to_payment',
140
+					$submit_button_text
141
+				);
142
+			}
143
+			if ($checkout->next_step->slug(
144
+				) != 'finalize_registration' && ! $checkout->revisit && isset($deprecated_filters['proceed_to'])) {
145
+				$submit_button_text = apply_filters(
146
+										  'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__proceed_to',
147
+										  $submit_button_text
148
+									  ) . $checkout->next_step->name();
149
+			}
150
+		}
151
+
152
+	}
153
+	return $submit_button_text;
154 154
 
155 155
 }
156 156
 
157 157
 add_filter(
158
-    'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
159
-    'ee_deprecated__registration_checkout__button_text',
160
-    10,
161
-    2
158
+	'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
159
+	'ee_deprecated__registration_checkout__button_text',
160
+	10,
161
+	2
162 162
 );
163 163
 
164 164
 
@@ -170,54 +170,54 @@  discard block
 block discarded – undo
170 170
  */
171 171
 function ee_deprecated_finalize_transaction(EE_Checkout $checkout, $status_updates)
172 172
 {
173
-    $action_ref = null;
174
-    $action_ref = has_action('AHEE__EE_Transaction__finalize__new_transaction')
175
-        ? 'AHEE__EE_Transaction__finalize__new_transaction' : $action_ref;
176
-    $action_ref = has_action('AHEE__EE_Transaction__finalize__all_transaction')
177
-        ? 'AHEE__EE_Transaction__finalize__all_transaction' : $action_ref;
178
-    if ($action_ref) {
179
-
180
-        EE_Error::doing_it_wrong(
181
-            $action_ref,
182
-            sprintf(
183
-                esc_html__(
184
-                    'This action is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use one of the following new actions: %1$s"%3$s" found in "%2$s" %1$s"%4$s" found in "%2$s" %1$s"%5$s" found in "%2$s" %1$s"%6$s" found in "%2$s"',
185
-                    'event_espresso'
186
-                ),
187
-                '<br />',
188
-                '/core/business/EE_Transaction_Processor.class.php',
189
-                'AHEE__EE_Transaction_Processor__finalize',
190
-                'AHEE__EE_Transaction_Processor__manually_update_registration_statuses',
191
-                'AHEE__EE_Transaction_Processor__toggle_registration_statuses_for_default_approved_events',
192
-                'AHEE__EE_Transaction_Processor__toggle_registration_statuses_if_no_monies_owing'
193
-            ),
194
-            '4.6.0'
195
-        );
196
-        switch ($action_ref) {
197
-            case 'AHEE__EE_Transaction__finalize__new_transaction' :
198
-                do_action(
199
-                    'AHEE__EE_Transaction__finalize__new_transaction',
200
-                    $checkout->transaction,
201
-                    $checkout->admin_request
202
-                );
203
-                break;
204
-            case 'AHEE__EE_Transaction__finalize__all_transaction' :
205
-                do_action(
206
-                    'AHEE__EE_Transaction__finalize__new_transaction',
207
-                    $checkout->transaction,
208
-                    array('new_reg' => ! $checkout->revisit, 'to_approved' => $status_updates),
209
-                    $checkout->admin_request
210
-                );
211
-                break;
212
-        }
213
-    }
173
+	$action_ref = null;
174
+	$action_ref = has_action('AHEE__EE_Transaction__finalize__new_transaction')
175
+		? 'AHEE__EE_Transaction__finalize__new_transaction' : $action_ref;
176
+	$action_ref = has_action('AHEE__EE_Transaction__finalize__all_transaction')
177
+		? 'AHEE__EE_Transaction__finalize__all_transaction' : $action_ref;
178
+	if ($action_ref) {
179
+
180
+		EE_Error::doing_it_wrong(
181
+			$action_ref,
182
+			sprintf(
183
+				esc_html__(
184
+					'This action is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use one of the following new actions: %1$s"%3$s" found in "%2$s" %1$s"%4$s" found in "%2$s" %1$s"%5$s" found in "%2$s" %1$s"%6$s" found in "%2$s"',
185
+					'event_espresso'
186
+				),
187
+				'<br />',
188
+				'/core/business/EE_Transaction_Processor.class.php',
189
+				'AHEE__EE_Transaction_Processor__finalize',
190
+				'AHEE__EE_Transaction_Processor__manually_update_registration_statuses',
191
+				'AHEE__EE_Transaction_Processor__toggle_registration_statuses_for_default_approved_events',
192
+				'AHEE__EE_Transaction_Processor__toggle_registration_statuses_if_no_monies_owing'
193
+			),
194
+			'4.6.0'
195
+		);
196
+		switch ($action_ref) {
197
+			case 'AHEE__EE_Transaction__finalize__new_transaction' :
198
+				do_action(
199
+					'AHEE__EE_Transaction__finalize__new_transaction',
200
+					$checkout->transaction,
201
+					$checkout->admin_request
202
+				);
203
+				break;
204
+			case 'AHEE__EE_Transaction__finalize__all_transaction' :
205
+				do_action(
206
+					'AHEE__EE_Transaction__finalize__new_transaction',
207
+					$checkout->transaction,
208
+					array('new_reg' => ! $checkout->revisit, 'to_approved' => $status_updates),
209
+					$checkout->admin_request
210
+				);
211
+				break;
212
+		}
213
+	}
214 214
 }
215 215
 
216 216
 add_action(
217
-    'AHEE__EE_SPCO_Reg_Step_Finalize_Registration__process_reg_step__completed',
218
-    'ee_deprecated_finalize_transaction',
219
-    10,
220
-    2
217
+	'AHEE__EE_SPCO_Reg_Step_Finalize_Registration__process_reg_step__completed',
218
+	'ee_deprecated_finalize_transaction',
219
+	10,
220
+	2
221 221
 );
222 222
 /**
223 223
  * ee_deprecated_finalize_registration
@@ -226,35 +226,35 @@  discard block
 block discarded – undo
226 226
  */
227 227
 function ee_deprecated_finalize_registration(EE_Registration $registration)
228 228
 {
229
-    $action_ref = has_action('AHEE__EE_Registration__finalize__update_and_new_reg')
230
-        ? 'AHEE__EE_Registration__finalize__update_and_new_reg' : null;
231
-    if ($action_ref) {
232
-        EE_Error::doing_it_wrong(
233
-            $action_ref,
234
-            sprintf(
235
-                esc_html__(
236
-                    'This action is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new action: %1$s"%3$s" found in "%2$s"',
237
-                    'event_espresso'
238
-                ),
239
-                '<br />',
240
-                '/core/business/EE_Registration_Processor.class.php',
241
-                'AHEE__EE_Registration_Processor__trigger_registration_update_notifications'
242
-            ),
243
-            '4.6.0'
244
-        );
245
-        do_action(
246
-            'AHEE__EE_Registration__finalize__update_and_new_reg',
247
-            $registration,
248
-            (is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX))
249
-        );
250
-    }
229
+	$action_ref = has_action('AHEE__EE_Registration__finalize__update_and_new_reg')
230
+		? 'AHEE__EE_Registration__finalize__update_and_new_reg' : null;
231
+	if ($action_ref) {
232
+		EE_Error::doing_it_wrong(
233
+			$action_ref,
234
+			sprintf(
235
+				esc_html__(
236
+					'This action is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new action: %1$s"%3$s" found in "%2$s"',
237
+					'event_espresso'
238
+				),
239
+				'<br />',
240
+				'/core/business/EE_Registration_Processor.class.php',
241
+				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications'
242
+			),
243
+			'4.6.0'
244
+		);
245
+		do_action(
246
+			'AHEE__EE_Registration__finalize__update_and_new_reg',
247
+			$registration,
248
+			(is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX))
249
+		);
250
+	}
251 251
 }
252 252
 
253 253
 add_action(
254
-    'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
255
-    'ee_deprecated_finalize_registration',
256
-    10,
257
-    1
254
+	'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
255
+	'ee_deprecated_finalize_registration',
256
+	10,
257
+	1
258 258
 );
259 259
 
260 260
 
@@ -264,44 +264,44 @@  discard block
 block discarded – undo
264 264
  */
265 265
 function ee_deprecated_hooks()
266 266
 {
267
-    /**
268
-     * @var          $hooks       array where keys are hook names, and their values are array{
269
-     * @type string  $version     when deprecated
270
-     * @type string  $alternative saying what to use instead
271
-     * @type boolean $still_works whether or not the hook still works
272
-     *        }
273
-     */
274
-    $hooks = array(
275
-        'AHEE__EE_System___do_setup_validations' => array(
276
-            'version'     => '4.6.0',
277
-            'alternative' => esc_html__(
278
-                'Instead use "AHEE__EEH_Activation__validate_messages_system" which is called after validating messages (done on every new install, upgrade, reactivation, and downgrade)',
279
-                'event_espresso'
280
-            ),
281
-            'still_works' => false,
282
-        ),
283
-    );
284
-    foreach ($hooks as $name => $deprecation_info) {
285
-        if (has_action($name)) {
286
-            EE_Error::doing_it_wrong(
287
-                $name,
288
-                sprintf(
289
-                    esc_html__('This filter is deprecated. %1$s%2$s', 'event_espresso'),
290
-                    $deprecation_info['still_works'] ? esc_html__(
291
-                        'It *may* work as an attempt to build in backwards compatibility.',
292
-                        'event_espresso'
293
-                    ) : esc_html__('It has been completely removed.', 'event_espresso'),
294
-                    isset($deprecation_info['alternative'])
295
-                        ? $deprecation_info['alternative']
296
-                        : esc_html__(
297
-                        'Please read the current EE4 documentation further or contact Support.',
298
-                        'event_espresso'
299
-                    )
300
-                ),
301
-                isset($deprecation_info['version']) ? $deprecation_info['version'] : esc_html__('recently', 'event_espresso')
302
-            );
303
-        }
304
-    }
267
+	/**
268
+	 * @var          $hooks       array where keys are hook names, and their values are array{
269
+	 * @type string  $version     when deprecated
270
+	 * @type string  $alternative saying what to use instead
271
+	 * @type boolean $still_works whether or not the hook still works
272
+	 *        }
273
+	 */
274
+	$hooks = array(
275
+		'AHEE__EE_System___do_setup_validations' => array(
276
+			'version'     => '4.6.0',
277
+			'alternative' => esc_html__(
278
+				'Instead use "AHEE__EEH_Activation__validate_messages_system" which is called after validating messages (done on every new install, upgrade, reactivation, and downgrade)',
279
+				'event_espresso'
280
+			),
281
+			'still_works' => false,
282
+		),
283
+	);
284
+	foreach ($hooks as $name => $deprecation_info) {
285
+		if (has_action($name)) {
286
+			EE_Error::doing_it_wrong(
287
+				$name,
288
+				sprintf(
289
+					esc_html__('This filter is deprecated. %1$s%2$s', 'event_espresso'),
290
+					$deprecation_info['still_works'] ? esc_html__(
291
+						'It *may* work as an attempt to build in backwards compatibility.',
292
+						'event_espresso'
293
+					) : esc_html__('It has been completely removed.', 'event_espresso'),
294
+					isset($deprecation_info['alternative'])
295
+						? $deprecation_info['alternative']
296
+						: esc_html__(
297
+						'Please read the current EE4 documentation further or contact Support.',
298
+						'event_espresso'
299
+					)
300
+				),
301
+				isset($deprecation_info['version']) ? $deprecation_info['version'] : esc_html__('recently', 'event_espresso')
302
+			);
303
+		}
304
+	}
305 305
 }
306 306
 
307 307
 add_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons', 'ee_deprecated_hooks');
@@ -316,34 +316,34 @@  discard block
 block discarded – undo
316 316
  */
317 317
 function ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
318 318
 {
319
-    $in_use = has_filter('FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns')
320
-              || has_action(
321
-                  'AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save'
322
-              );
323
-    if ($in_use) {
324
-        $msg = esc_html__(
325
-            'We detected you are using the filter FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns or AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save.'
326
-            . 'Both of these have been deprecated and should not be used anymore. You should instead use FHEE__EE_Form_Section_Proper___construct__options_array to customize the contents of the form,'
327
-            . 'use FHEE__EE_Form_Section_Proper__receive_form_submission__req_data to customize the submission data, or AHEE__EE_Form_Section_Proper__receive_form_submission__end '
328
-            . 'to add other actions after a form submission has been received.',
329
-            'event_espresso'
330
-        );
331
-        EE_Error::doing_it_wrong(
332
-            __CLASS__ . '::' . __FUNCTION__,
333
-            $msg,
334
-            '4.8.32.rc.000'
335
-        );
336
-        // it seems the doing_it_wrong messages get output during some hidden html tags, so add an error to make sure this gets noticed
337
-        if (is_admin() && ! defined('DOING_AJAX')) {
338
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
339
-        }
340
-    }
341
-    return $in_use;
319
+	$in_use = has_filter('FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns')
320
+			  || has_action(
321
+				  'AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save'
322
+			  );
323
+	if ($in_use) {
324
+		$msg = esc_html__(
325
+			'We detected you are using the filter FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns or AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save.'
326
+			. 'Both of these have been deprecated and should not be used anymore. You should instead use FHEE__EE_Form_Section_Proper___construct__options_array to customize the contents of the form,'
327
+			. 'use FHEE__EE_Form_Section_Proper__receive_form_submission__req_data to customize the submission data, or AHEE__EE_Form_Section_Proper__receive_form_submission__end '
328
+			. 'to add other actions after a form submission has been received.',
329
+			'event_espresso'
330
+		);
331
+		EE_Error::doing_it_wrong(
332
+			__CLASS__ . '::' . __FUNCTION__,
333
+			$msg,
334
+			'4.8.32.rc.000'
335
+		);
336
+		// it seems the doing_it_wrong messages get output during some hidden html tags, so add an error to make sure this gets noticed
337
+		if (is_admin() && ! defined('DOING_AJAX')) {
338
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
339
+		}
340
+	}
341
+	return $in_use;
342 342
 }
343 343
 
344 344
 add_action(
345
-    'AHEE__Registrations_Admin_Page___registration_details_metabox__start',
346
-    'ee_deprecated_using_old_registration_admin_custom_questions_form_hooks'
345
+	'AHEE__Registrations_Admin_Page___registration_details_metabox__start',
346
+	'ee_deprecated_using_old_registration_admin_custom_questions_form_hooks'
347 347
 );
348 348
 
349 349
 /**
@@ -355,82 +355,82 @@  discard block
 block discarded – undo
355 355
  */
356 356
 function ee_deprecated_update_attendee_registration_form_old($admin_page)
357 357
 {
358
-    // check if the old hooks are in use. If not, do the default
359
-    if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
360
-        || ! $admin_page instanceof EE_Admin_Page) {
361
-        return;
362
-    }
363
-    $req_data = $admin_page->get_request_data();
364
-    $qstns = isset($req_data['qstn']) ? $req_data['qstn'] : false;
365
-    $REG_ID = isset($req_data['_REG_ID']) ? absint($req_data['_REG_ID']) : false;
366
-    $qstns = apply_filters('FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns', $qstns);
367
-    if (! $REG_ID || ! $qstns) {
368
-        EE_Error::add_error(
369
-            esc_html__('An error occurred. No registration ID and/or registration questions were received.', 'event_espresso'),
370
-            __FILE__,
371
-            __FUNCTION__,
372
-            __LINE__
373
-        );
374
-    }
375
-    $success = true;
376
-
377
-    // allow others to get in on this awesome fun   :D
378
-    do_action(
379
-        'AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save',
380
-        $REG_ID,
381
-        $qstns
382
-    );
383
-    // loop thru questions... FINALLY!!!
384
-
385
-    foreach ($qstns as $QST_ID => $qstn) {
386
-        // if $qstn isn't an array then it doesn't already have an answer, so let's create the answer
387
-        if (! is_array($qstn)) {
388
-            $set_values = [
389
-                'QST_ID'    => $QST_ID,
390
-                'REG_ID'    => $REG_ID,
391
-                'ANS_value' => $qstn,
392
-            ];
393
-            $success    = EEM_Answer::instance()->insert($set_values);
394
-            continue;
395
-        }
396
-
397
-
398
-        foreach ($qstn as $ANS_ID => $ANS_value) {
399
-            // get answer
400
-            $query_params = array(
401
-                0 => array(
402
-                    'ANS_ID' => $ANS_ID,
403
-                    'REG_ID' => $REG_ID,
404
-                    'QST_ID' => $QST_ID,
405
-                ),
406
-            );
407
-            $answer = EEM_Answer::instance()->get_one($query_params);
408
-            // this MAY be an array but NOT have an answer because its multi select.  If so then we need to create the answer
409
-            if (! $answer instanceof EE_Answer) {
410
-                $set_values = array(
411
-                    'QST_ID'    => $QST_ID,
412
-                    'REG_ID'    => $REG_ID,
413
-                    'ANS_value' => $qstn,
414
-                );
415
-                $success = EEM_Answer::instance()->insert($set_values);
416
-                continue 2;
417
-            }
418
-
419
-            $answer->set('ANS_value', $ANS_value);
420
-            $success = $answer->save();
421
-        }
422
-    }
423
-    $what = esc_html__('Registration Form', 'event_espresso');
424
-    $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID) : array('action' => 'default');
425
-    $admin_page->redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
426
-    exit;
358
+	// check if the old hooks are in use. If not, do the default
359
+	if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
360
+		|| ! $admin_page instanceof EE_Admin_Page) {
361
+		return;
362
+	}
363
+	$req_data = $admin_page->get_request_data();
364
+	$qstns = isset($req_data['qstn']) ? $req_data['qstn'] : false;
365
+	$REG_ID = isset($req_data['_REG_ID']) ? absint($req_data['_REG_ID']) : false;
366
+	$qstns = apply_filters('FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns', $qstns);
367
+	if (! $REG_ID || ! $qstns) {
368
+		EE_Error::add_error(
369
+			esc_html__('An error occurred. No registration ID and/or registration questions were received.', 'event_espresso'),
370
+			__FILE__,
371
+			__FUNCTION__,
372
+			__LINE__
373
+		);
374
+	}
375
+	$success = true;
376
+
377
+	// allow others to get in on this awesome fun   :D
378
+	do_action(
379
+		'AHEE__Registrations_Admin_Page___save_attendee_registration_form__after_reg_and_attendee_save',
380
+		$REG_ID,
381
+		$qstns
382
+	);
383
+	// loop thru questions... FINALLY!!!
384
+
385
+	foreach ($qstns as $QST_ID => $qstn) {
386
+		// if $qstn isn't an array then it doesn't already have an answer, so let's create the answer
387
+		if (! is_array($qstn)) {
388
+			$set_values = [
389
+				'QST_ID'    => $QST_ID,
390
+				'REG_ID'    => $REG_ID,
391
+				'ANS_value' => $qstn,
392
+			];
393
+			$success    = EEM_Answer::instance()->insert($set_values);
394
+			continue;
395
+		}
396
+
397
+
398
+		foreach ($qstn as $ANS_ID => $ANS_value) {
399
+			// get answer
400
+			$query_params = array(
401
+				0 => array(
402
+					'ANS_ID' => $ANS_ID,
403
+					'REG_ID' => $REG_ID,
404
+					'QST_ID' => $QST_ID,
405
+				),
406
+			);
407
+			$answer = EEM_Answer::instance()->get_one($query_params);
408
+			// this MAY be an array but NOT have an answer because its multi select.  If so then we need to create the answer
409
+			if (! $answer instanceof EE_Answer) {
410
+				$set_values = array(
411
+					'QST_ID'    => $QST_ID,
412
+					'REG_ID'    => $REG_ID,
413
+					'ANS_value' => $qstn,
414
+				);
415
+				$success = EEM_Answer::instance()->insert($set_values);
416
+				continue 2;
417
+			}
418
+
419
+			$answer->set('ANS_value', $ANS_value);
420
+			$success = $answer->save();
421
+		}
422
+	}
423
+	$what = esc_html__('Registration Form', 'event_espresso');
424
+	$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID) : array('action' => 'default');
425
+	$admin_page->redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
426
+	exit;
427 427
 }
428 428
 
429 429
 add_action(
430
-    'AHEE__Registrations_Admin_Page___update_attendee_registration_form__start',
431
-    'ee_deprecated_update_attendee_registration_form_old',
432
-    10,
433
-    1
430
+	'AHEE__Registrations_Admin_Page___update_attendee_registration_form__start',
431
+	'ee_deprecated_update_attendee_registration_form_old',
432
+	10,
433
+	1
434 434
 );
435 435
 /**
436 436
  * Render the registration admin page's custom questions area in the old fashion
@@ -446,50 +446,50 @@  discard block
 block discarded – undo
446 446
  */
447 447
 function ee_deprecated_reg_questions_meta_box_old($do_default_action, $admin_page, $registration)
448 448
 {
449
-    // check if the old hooks are in use. If not, do the default
450
-    if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
451
-        || ! $admin_page instanceof EE_Admin_Page) {
452
-        return $do_default_action;
453
-    }
454
-    add_filter(
455
-        'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
456
-        array($admin_page, 'form_before_question_group'),
457
-        10,
458
-        1
459
-    );
460
-    add_filter(
461
-        'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
462
-        array($admin_page, 'form_after_question_group'),
463
-        10,
464
-        1
465
-    );
466
-    add_filter('FHEE__EEH_Form_Fields__label_html', array($admin_page, 'form_form_field_label_wrap'), 10, 1);
467
-    add_filter('FHEE__EEH_Form_Fields__input_html', array($admin_page, 'form_form_field_input__wrap'), 10, 1);
468
-
469
-    $question_groups = EEM_Event::instance()->assemble_array_of_groups_questions_and_options(
470
-        $registration,
471
-        $registration->get(
472
-            'EVT_ID'
473
-        )
474
-    );
475
-
476
-    EE_Registry::instance()->load_helper('Form_Fields');
477
-    $template_args = array(
478
-        'att_questions'             => EEH_Form_Fields::generate_question_groups_html($question_groups),
479
-        'reg_questions_form_action' => 'edit_registration',
480
-        'REG_ID'                    => $registration->ID(),
481
-    );
482
-    $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
483
-    echo EEH_Template::display_template($template_path, $template_args, true);
484
-    // indicate that we should not do the default admin page code
485
-    return false;
449
+	// check if the old hooks are in use. If not, do the default
450
+	if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
451
+		|| ! $admin_page instanceof EE_Admin_Page) {
452
+		return $do_default_action;
453
+	}
454
+	add_filter(
455
+		'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
456
+		array($admin_page, 'form_before_question_group'),
457
+		10,
458
+		1
459
+	);
460
+	add_filter(
461
+		'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
462
+		array($admin_page, 'form_after_question_group'),
463
+		10,
464
+		1
465
+	);
466
+	add_filter('FHEE__EEH_Form_Fields__label_html', array($admin_page, 'form_form_field_label_wrap'), 10, 1);
467
+	add_filter('FHEE__EEH_Form_Fields__input_html', array($admin_page, 'form_form_field_input__wrap'), 10, 1);
468
+
469
+	$question_groups = EEM_Event::instance()->assemble_array_of_groups_questions_and_options(
470
+		$registration,
471
+		$registration->get(
472
+			'EVT_ID'
473
+		)
474
+	);
475
+
476
+	EE_Registry::instance()->load_helper('Form_Fields');
477
+	$template_args = array(
478
+		'att_questions'             => EEH_Form_Fields::generate_question_groups_html($question_groups),
479
+		'reg_questions_form_action' => 'edit_registration',
480
+		'REG_ID'                    => $registration->ID(),
481
+	);
482
+	$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
483
+	echo EEH_Template::display_template($template_path, $template_args, true);
484
+	// indicate that we should not do the default admin page code
485
+	return false;
486 486
 }
487 487
 
488 488
 add_action(
489
-    'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
490
-    'ee_deprecated_reg_questions_meta_box_old',
491
-    10,
492
-    3
489
+	'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
490
+	'ee_deprecated_reg_questions_meta_box_old',
491
+	10,
492
+	3
493 493
 );
494 494
 
495 495
 
@@ -506,42 +506,42 @@  discard block
 block discarded – undo
506 506
 class EE_Message_Template_Defaults extends EE_Base
507 507
 {
508 508
 
509
-    /**
510
-     * EE_Message_Template_Defaults constructor.
511
-     *
512
-     * @param EE_messages $messages
513
-     * @param             $messenger_name
514
-     * @param             $message_type_name
515
-     * @param int         $GRP_ID
516
-     * @return EE_Messages_Template_Defaults
517
-     */
518
-    public function __construct(
519
-        EE_messages $messages,
520
-        $messenger_name,
521
-        $message_type_name,
522
-        $GRP_ID = 0
523
-    ) {
524
-        EE_Error::doing_it_wrong(
525
-            __FUNCTION__,
526
-            esc_html__(
527
-                'The class EE_Message_Template_Defaults has been deprecated and replaced by EE_Messages_Template_Defaults.',
528
-                'event_espresso'
529
-            ),
530
-            '4.9.0'
531
-        );
532
-        /** @var EE_Message_Resource_Manager $message_resource_manager */
533
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
534
-        $messenger = $message_resource_manager->get_messenger($messenger_name);
535
-        $message_type = $message_resource_manager->get_message_type($message_type_name);
536
-        return EE_Registry::instance()->load_lib(
537
-            'Messages_Template_Defaults',
538
-            array(
539
-                $messenger,
540
-                $message_type,
541
-                $GRP_ID,
542
-            )
543
-        );
544
-    }
509
+	/**
510
+	 * EE_Message_Template_Defaults constructor.
511
+	 *
512
+	 * @param EE_messages $messages
513
+	 * @param             $messenger_name
514
+	 * @param             $message_type_name
515
+	 * @param int         $GRP_ID
516
+	 * @return EE_Messages_Template_Defaults
517
+	 */
518
+	public function __construct(
519
+		EE_messages $messages,
520
+		$messenger_name,
521
+		$message_type_name,
522
+		$GRP_ID = 0
523
+	) {
524
+		EE_Error::doing_it_wrong(
525
+			__FUNCTION__,
526
+			esc_html__(
527
+				'The class EE_Message_Template_Defaults has been deprecated and replaced by EE_Messages_Template_Defaults.',
528
+				'event_espresso'
529
+			),
530
+			'4.9.0'
531
+		);
532
+		/** @var EE_Message_Resource_Manager $message_resource_manager */
533
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
534
+		$messenger = $message_resource_manager->get_messenger($messenger_name);
535
+		$message_type = $message_resource_manager->get_message_type($message_type_name);
536
+		return EE_Registry::instance()->load_lib(
537
+			'Messages_Template_Defaults',
538
+			array(
539
+				$messenger,
540
+				$message_type,
541
+				$GRP_ID,
542
+			)
543
+		);
544
+	}
545 545
 }
546 546
 
547 547
 
@@ -559,525 +559,525 @@  discard block
 block discarded – undo
559 559
 class EE_messages
560 560
 {
561 561
 
562
-    /** @type EE_messenger[] */
563
-    protected $_active_messengers = array();
564
-
565
-    /** @type array */
566
-    protected $_active_message_types = array();
567
-
568
-    /** @type EE_message_type[] */
569
-    protected $_installed_message_types = array();
570
-
571
-    /** @type EE_messenger */
572
-    protected $_messenger;
573
-
574
-    /** @type EE_message_type */
575
-    protected $_message_type;
576
-
577
-    /** @type array */
578
-    protected $_contexts = array();
579
-
580
-    /** @type EE_Message_Resource_Manager $_message_resource_manager */
581
-    protected $_message_resource_manager;
582
-
583
-
584
-    /**
585
-     * EE_messages constructor.
586
-     *
587
-     * @deprecated 4.9.0
588
-     */
589
-    public function __construct()
590
-    {
591
-    }
592
-
593
-
594
-    /**
595
-     * @param string $method
596
-     */
597
-    public function _class_is_deprecated($method)
598
-    {
599
-        EE_Error::doing_it_wrong(
600
-            'EE_messages::' . $method,
601
-            esc_html__('EE_messages has been deprecated.  Please use EE_Message_Resource_Manager instead.'),
602
-            '4.9.0',
603
-            '4.10.0.p'
604
-        );
605
-        // Please use EE_Message_Resource_Manager instead
606
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
607
-    }
608
-
609
-
610
-    /**
611
-     * @deprecated 4.9.0
612
-     * @param string $messenger_name
613
-     * @return boolean TRUE if it was PREVIOUSLY active, and FALSE if it was previously inactive
614
-     */
615
-    public function ensure_messenger_is_active($messenger_name)
616
-    {
617
-        // EE_messages has been deprecated
618
-        $this->_class_is_deprecated(__FUNCTION__);
619
-        return $this->_message_resource_manager->ensure_messenger_is_active($messenger_name);
620
-    }
621
-
622
-
623
-    /**
624
-     * @deprecated 4.9.0
625
-     * @param string $message_type message type name
626
-     * @param        $messenger
627
-     * @return bool true if it got activated (or was active) and false if not.
628
-     * @throws \EE_Error
629
-     */
630
-    public function ensure_message_type_is_active($message_type, $messenger)
631
-    {
632
-        // EE_messages has been deprecated
633
-        $this->_class_is_deprecated(__FUNCTION__);
634
-        return $this->_message_resource_manager->ensure_message_type_is_active($message_type, $messenger);
635
-    }
636
-
637
-
638
-    /**
639
-     * @deprecated 4.9.0
640
-     * @param string $messenger_name
641
-     * @param array  $mts_to_activate             (optional) An array of message types to activate with this messenger.
642
-     *                                             If included we do NOT setup the default message types (assuming they
643
-     *                                             are already setup.)
644
-     * @return boolean an array of generated templates or false if nothing generated/activated.
645
-     */
646
-    public function activate_messenger($messenger_name, $mts_to_activate = array())
647
-    {
648
-        // EE_messages has been deprecated
649
-        $this->_class_is_deprecated(__FUNCTION__);
650
-        return $this->_message_resource_manager->activate_messenger($messenger_name, $mts_to_activate);
651
-    }
652
-
653
-
654
-    /**
655
-     * @deprecated 4.9.0
656
-     * @param EE_messenger    $messenger    messenger used in trigger
657
-     * @param EE_message_type $message_type message type used in trigger
658
-     *
659
-     * @return bool true is a generating messenger and can be sent OR FALSE meaning cannot send.
660
-     */
661
-    public function is_generating_messenger_and_active(EE_messenger $messenger, EE_message_type $message_type)
662
-    {
663
-        // EE_messages has been deprecated
664
-        $this->_class_is_deprecated(__FUNCTION__);
665
-        return $this->_message_resource_manager->is_generating_messenger_and_active($messenger, $message_type);
666
-    }
667
-
668
-
669
-    /**
670
-     * @deprecated 4.9.0
671
-     * @param string $messenger
672
-     * @return EE_messenger | null
673
-     */
674
-    public function get_messenger_if_active($messenger)
675
-    {
676
-        // EE_messages has been deprecated
677
-        $this->_class_is_deprecated(__FUNCTION__);
678
-        return $this->_message_resource_manager->get_active_messenger($messenger);
679
-    }
680
-
681
-
682
-    /**
683
-     * @deprecated 4.9.0
684
-     * @param EE_Message $message
685
-     * @return array  An array with 'messenger' and 'message_type' as the index and the corresponding valid object if
686
-     *                  available.
687
-     *                  Eg. Valid Messenger and Message Type:
688
-     *                  array(
689
-     *                  'messenger' => new EE_Email_messenger(),
690
-     *                  'message_type' => new EE_Registration_Approved_message_type()
691
-     *                  )
692
-     *                  Valid Messenger and Invalid Message Type:
693
-     *                  array(
694
-     *                  'messenger' => new EE_Email_messenger(),
695
-     *                  'message_type' => null
696
-     *                  )
697
-     */
698
-    public function validate_for_use(EE_Message $message)
699
-    {
700
-        // EE_messages has been deprecated
701
-        $this->_class_is_deprecated(__FUNCTION__);
702
-        return array(
703
-            'messenger'    => $message->messenger_object(),
704
-            'message_type' => $message->message_type_object(),
705
-        );
706
-    }
707
-
708
-
709
-    /**
710
-     * @deprecated 4.9.0
711
-     * @param  string $type                 What type of message are we sending (corresponds to message types)
712
-     * @param  mixed  $vars                 Data being sent for parsing in the message
713
-     * @param  string $sending_messenger    if included then we ONLY use the specified messenger for delivery.
714
-     *                                      Otherwise we cycle through all active messengers.
715
-     * @param string  $generating_messenger if included then this messenger is used for generating the message
716
-     *                                      templates (but not for sending).
717
-     * @param string  $context              If included then only a message type for a specific context will be
718
-     *                                      generated.
719
-     * @param bool    $send                 Default TRUE.  If false, then this will just return the generated
720
-     *                                      EE_messages objects which might be used by the trigger to setup a batch
721
-     *                                      message (typically html messenger uses it).
722
-     * @return bool
723
-     */
724
-    public function send_message(
725
-        $type,
726
-        $vars,
727
-        $sending_messenger = '',
728
-        $generating_messenger = '',
729
-        $context = '',
730
-        $send = true
731
-    ) {
732
-        // EE_messages has been deprecated
733
-        $this->_class_is_deprecated(__FUNCTION__);
734
-        /** @type EE_Messages_Processor $processor */
735
-        $processor = EE_Registry::instance()->load_lib('Messages_Processor');
736
-        $error = false;
737
-        // try to intelligently determine what method we'll call based on the incoming data.
738
-        // if generating and sending are different then generate and send immediately.
739
-        if (! empty($sending_messenger) && $sending_messenger != $generating_messenger && $send) {
740
-            // in the legacy system, when generating and sending were different, that means all the
741
-            // vars are already in the request object.  So let's just use that.
742
-            try {
743
-                /** @type EE_Message_To_Generate_From_Request $mtg */
744
-                $mtg = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
745
-                $processor->generate_and_send_now($mtg);
746
-            } catch (EE_Error $e) {
747
-                $error_msg = esc_html__(
748
-                    'Please note that a system message failed to send due to a technical issue.',
749
-                    'event_espresso'
750
-                );
751
-                // add specific message for developers if WP_DEBUG in on
752
-                $error_msg .= '||' . $e->getMessage();
753
-                EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
754
-                $error = true;
755
-            }
756
-        } else {
757
-            $processor->generate_for_all_active_messengers($type, $vars, $send);
758
-            // let's find out if there were any errors and how many successfully were queued.
759
-            $count_errors = $processor->get_queue()->count_STS_in_queue(
760
-                array(EEM_Message::status_failed, EEM_Message::status_debug_only)
761
-            );
762
-            $count_queued = $processor->get_queue()->count_STS_in_queue(EEM_Message::status_incomplete);
763
-            $count_retry = $processor->get_queue()->count_STS_in_queue(EEM_Message::status_retry);
764
-            $count_errors = $count_errors + $count_retry;
765
-            if ($count_errors > 0) {
766
-                $error = true;
767
-                if ($count_errors > 1 && $count_retry > 1 && $count_queued > 1) {
768
-                    $message = sprintf(
769
-                        esc_html__(
770
-                            'There were %d errors and %d messages successfully queued for generation and sending',
771
-                            'event_espresso'
772
-                        ),
773
-                        $count_errors,
774
-                        $count_queued
775
-                    );
776
-                } elseif ($count_errors > 1 && $count_queued === 1) {
777
-                    $message = sprintf(
778
-                        esc_html__(
779
-                            'There were %d errors and %d message successfully queued for generation.',
780
-                            'event_espresso'
781
-                        ),
782
-                        $count_errors,
783
-                        $count_queued
784
-                    );
785
-                } elseif ($count_errors === 1 && $count_queued > 1) {
786
-                    $message = sprintf(
787
-                        esc_html__(
788
-                            'There was %d error and %d messages successfully queued for generation.',
789
-                            'event_espresso'
790
-                        ),
791
-                        $count_errors,
792
-                        $count_queued
793
-                    );
794
-                } else {
795
-                    $message = sprintf(
796
-                        esc_html__(
797
-                            'There was %d message that failed to be queued for generation.',
798
-                            'event_espresso'
799
-                        ),
800
-                        $count_errors
801
-                    );
802
-                }
803
-                EE_Error::add_error($message, __FILE__, __FUNCTION__, __LINE__);
804
-            } else {
805
-                if ($count_queued === 1) {
806
-                    $message = sprintf(
807
-                        esc_html__(
808
-                            '%d message successfully queued for generation.',
809
-                            'event_espresso'
810
-                        ),
811
-                        $count_queued
812
-                    );
813
-                } else {
814
-                    $message = sprintf(
815
-                        esc_html__(
816
-                            '%d messages were successfully queued for generation.',
817
-                            'event_espresso'
818
-                        ),
819
-                        $count_queued
820
-                    );
821
-                }
822
-                EE_Error::add_success($message);
823
-            }
824
-        }
825
-        // if no error then return the generated message(s).
826
-        if (! $error && ! $send) {
827
-            $generated_queue = $processor->generate_queue(false);
828
-            // get message and return.
829
-            $generated_queue->get_message_repository()->rewind();
830
-            $messages = array();
831
-            while ($generated_queue->get_message_repository()->valid()) {
832
-                $message = $generated_queue->get_message_repository()->current();
833
-                if ($message instanceof EE_Message) {
834
-                    // set properties that might be expected by add-ons (backward compat)
835
-                    $message->content = $message->content();
836
-                    $message->template_pack = $message->get_template_pack();
837
-                    $message->template_variation = $message->get_template_pack_variation();
838
-                    $messages[] = $message;
839
-                }
840
-                $generated_queue->get_message_repository()->next();
841
-            }
842
-            return $messages;
843
-        }
844
-        return $error ? false
845
-            : true; // yeah backwards eh?  Really what we're returning is if there is a total success for all the messages or not.  We'll modify this once we get message recording in place.
846
-    }
847
-
848
-
849
-    /**
850
-     * @deprecated 4.9.0
851
-     * @param  string $type      This should correspond with a valid message type
852
-     * @param  string $context   This should correspond with a valid context for the message type
853
-     * @param  string $messenger This should correspond with a valid messenger.
854
-     * @param bool    $send      true we will do a test send using the messenger delivery, false we just do a regular
855
-     *                           preview
856
-     * @return string          The body of the message.
857
-     */
858
-    public function preview_message($type, $context, $messenger, $send = false)
859
-    {
860
-        // EE_messages has been deprecated
861
-        $this->_class_is_deprecated(__FUNCTION__);
862
-        return EED_Messages::preview_message($type, $context, $messenger, $send);
863
-    }
864
-
865
-
866
-    /**
867
-     * @since      4.5.0
868
-     * @deprecated 4.9.0   Moved to EED_Messages Module
869
-     * @param string   $messenger    a string matching a valid active messenger in the system
870
-     * @param string   $message_type Although it seems contrary to the name of the method, a message type name is still
871
-     *                               required to send along the message type to the messenger because this is used for
872
-     *                               determining what specific variations might be loaded for the generated message.
873
-     * @param stdClass $message      a stdClass object in the format expected by the messenger.
874
-     *
875
-     * @return bool          success or fail.
876
-     */
877
-    public function send_message_with_messenger_only($messenger, $message_type, $message)
878
-    {
879
-        // EE_messages has been deprecated
880
-        $this->_class_is_deprecated(__FUNCTION__);
881
-        // setup for sending to new method.
882
-        /** @type EE_Messages_Queue $queue */
883
-        $queue = EE_Registry::instance()->load_lib('Messages_Queue');
884
-        // make sure we have a proper message object
885
-        if (! $message instanceof EE_Message && is_object($message) && isset($message->content)) {
886
-            $msg = EE_Message_Factory::create(
887
-                array(
888
-                    'MSG_messenger'    => $messenger,
889
-                    'MSG_message_type' => $message_type,
890
-                    'MSG_content'      => $message->content,
891
-                    'MSG_subject'      => $message->subject,
892
-                )
893
-            );
894
-        } else {
895
-            $msg = $message;
896
-        }
897
-        if (! $msg instanceof EE_Message) {
898
-            return false;
899
-        }
900
-        // make sure any content in a content property (if not empty) is set on the MSG_content.
901
-        if (! empty($msg->content)) {
902
-            $msg->set('MSG_content', $msg->content);
903
-        }
904
-        $queue->add($msg);
905
-        return EED_Messages::send_message_with_messenger_only($messenger, $message_type, $queue);
906
-    }
907
-
908
-
909
-    /**
910
-     * @deprecated 4.9.0
911
-     * @param         $messenger
912
-     * @param  string $message_type message type that the templates are being created for
913
-     * @param int     $GRP_ID
914
-     * @param bool    $is_global
915
-     * @return array|object if creation is successful then we return an array of info, otherwise an error_object is
916
-     *                      returned.
917
-     * @throws \EE_Error
918
-     */
919
-    public function create_new_templates($messenger, $message_type, $GRP_ID = 0, $is_global = false)
920
-    {
921
-        // EE_messages has been deprecated
922
-        $this->_class_is_deprecated(__FUNCTION__);
923
-        EE_Registry::instance()->load_helper('MSG_Template');
924
-        return EEH_MSG_Template::create_new_templates($messenger, $message_type, $GRP_ID, $is_global);
925
-    }
926
-
927
-
928
-    /**
929
-     * @deprecated 4.9.0
930
-     * @param  string $messenger_name    name of EE_messenger
931
-     * @param  string $message_type_name name of EE_message_type
932
-     * @return array
933
-     */
934
-    public function get_fields($messenger_name, $message_type_name)
935
-    {
936
-        // EE_messages has been deprecated
937
-        $this->_class_is_deprecated(__FUNCTION__);
938
-        EE_Registry::instance()->load_helper('MSG_Template');
939
-        return EEH_MSG_Template::get_fields($messenger_name, $message_type_name);
940
-    }
941
-
942
-
943
-    /**
944
-     * @deprecated 4.9.0
945
-     * @access     public
946
-     * @param string $type                we can indicate just returning installed message types
947
-     *                                    or messengers (or both) via this parameter.
948
-     * @param bool   $skip_cache          if true then we skip the cache and retrieve via files.
949
-     * @return array                    multidimensional array of messenger and message_type objects
950
-     *                                    (messengers index, and message_type index);
951
-     */
952
-    public function get_installed($type = 'all', $skip_cache = false)
953
-    {
954
-        // EE_messages has been deprecated
955
-        $this->_class_is_deprecated(__FUNCTION__);
956
-        if ($skip_cache) {
957
-            $this->_message_resource_manager->reset_active_messengers_and_message_types();
958
-        }
959
-        switch ($type) {
960
-            case 'messengers' :
961
-                return array(
962
-                    'messenger' => $this->_message_resource_manager->installed_messengers(),
963
-                );
964
-                break;
965
-            case 'message_types' :
966
-                return array(
967
-                    'message_type' => $this->_message_resource_manager->installed_message_types(),
968
-                );
969
-                break;
970
-            case 'all' :
971
-            default :
972
-                return array(
973
-                    'messenger'    => $this->_message_resource_manager->installed_messengers(),
974
-                    'message_type' => $this->_message_resource_manager->installed_message_types(),
975
-                );
976
-                break;
977
-        }
978
-    }
979
-
980
-
981
-    /**
982
-     * @deprecated 4.9.0
983
-     * @return \EE_messenger[]
984
-     */
985
-    public function get_active_messengers()
986
-    {
987
-        // EE_messages has been deprecated
988
-        $this->_class_is_deprecated(__FUNCTION__);
989
-        return $this->_message_resource_manager->active_messengers();
990
-    }
991
-
992
-
993
-    /**
994
-     * @deprecated 4.9.0
995
-     * @return array array of message_type references (string)
996
-     */
997
-    public function get_active_message_types()
998
-    {
999
-        // EE_messages has been deprecated
1000
-        $this->_class_is_deprecated(__FUNCTION__);
1001
-        return $this->_message_resource_manager->list_of_active_message_types();
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * @deprecated 4.9.0
1007
-     * @return EE_message_type[]
1008
-     */
1009
-    public function get_active_message_type_objects()
1010
-    {
1011
-        // EE_messages has been deprecated
1012
-        $this->_class_is_deprecated(__FUNCTION__);
1013
-        return $this->_message_resource_manager->get_active_message_type_objects();
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * @deprecated 4.9.0
1019
-     * @since      4.5.0
1020
-     * @param string $messenger The messenger being checked
1021
-     * @return EE_message_type[]    (or empty array if none present)
1022
-     */
1023
-    public function get_active_message_types_per_messenger($messenger)
1024
-    {
1025
-        // EE_messages has been deprecated
1026
-        $this->_class_is_deprecated(__FUNCTION__);
1027
-        return $this->_message_resource_manager->get_active_message_types_for_messenger($messenger);
1028
-    }
1029
-
1030
-
1031
-    /**
1032
-     * @deprecated 4.9.0
1033
-     * @param string $messenger    The string should correspond to the messenger (message types are
1034
-     * @param string $message_type The string should correspond to a message type.
1035
-     * @return EE_message_type|null
1036
-     */
1037
-    public function get_active_message_type($messenger, $message_type)
1038
-    {
1039
-        // EE_messages has been deprecated
1040
-        $this->_class_is_deprecated(__FUNCTION__);
1041
-        return $this->_message_resource_manager->get_active_message_type_for_messenger($messenger, $message_type);
1042
-    }
1043
-
1044
-
1045
-    /**
1046
-     * @deprecated 4.9.0
1047
-     * @return array|\EE_message_type[]
1048
-     */
1049
-    public function get_installed_message_types()
1050
-    {
1051
-        // EE_messages has been deprecated
1052
-        $this->_class_is_deprecated(__FUNCTION__);
1053
-        return $this->_message_resource_manager->installed_message_types();
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     * @deprecated 4.9.0
1059
-     * @return array
1060
-     */
1061
-    public function get_installed_messengers()
1062
-    {
1063
-        // EE_messages has been deprecated
1064
-        $this->_class_is_deprecated(__FUNCTION__);
1065
-        return $this->_message_resource_manager->installed_messengers();
1066
-    }
1067
-
1068
-
1069
-    /**
1070
-     * @deprecated 4.9.0
1071
-     * @param   bool $slugs_only Whether to return an array of just slugs and labels (true) or all contexts indexed by
1072
-     *                           message type.
1073
-     * @return array
1074
-     */
1075
-    public function get_all_contexts($slugs_only = true)
1076
-    {
1077
-        // EE_messages has been deprecated
1078
-        $this->_class_is_deprecated(__FUNCTION__);
1079
-        return $this->_message_resource_manager->get_all_contexts($slugs_only);
1080
-    }
562
+	/** @type EE_messenger[] */
563
+	protected $_active_messengers = array();
564
+
565
+	/** @type array */
566
+	protected $_active_message_types = array();
567
+
568
+	/** @type EE_message_type[] */
569
+	protected $_installed_message_types = array();
570
+
571
+	/** @type EE_messenger */
572
+	protected $_messenger;
573
+
574
+	/** @type EE_message_type */
575
+	protected $_message_type;
576
+
577
+	/** @type array */
578
+	protected $_contexts = array();
579
+
580
+	/** @type EE_Message_Resource_Manager $_message_resource_manager */
581
+	protected $_message_resource_manager;
582
+
583
+
584
+	/**
585
+	 * EE_messages constructor.
586
+	 *
587
+	 * @deprecated 4.9.0
588
+	 */
589
+	public function __construct()
590
+	{
591
+	}
592
+
593
+
594
+	/**
595
+	 * @param string $method
596
+	 */
597
+	public function _class_is_deprecated($method)
598
+	{
599
+		EE_Error::doing_it_wrong(
600
+			'EE_messages::' . $method,
601
+			esc_html__('EE_messages has been deprecated.  Please use EE_Message_Resource_Manager instead.'),
602
+			'4.9.0',
603
+			'4.10.0.p'
604
+		);
605
+		// Please use EE_Message_Resource_Manager instead
606
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
607
+	}
608
+
609
+
610
+	/**
611
+	 * @deprecated 4.9.0
612
+	 * @param string $messenger_name
613
+	 * @return boolean TRUE if it was PREVIOUSLY active, and FALSE if it was previously inactive
614
+	 */
615
+	public function ensure_messenger_is_active($messenger_name)
616
+	{
617
+		// EE_messages has been deprecated
618
+		$this->_class_is_deprecated(__FUNCTION__);
619
+		return $this->_message_resource_manager->ensure_messenger_is_active($messenger_name);
620
+	}
621
+
622
+
623
+	/**
624
+	 * @deprecated 4.9.0
625
+	 * @param string $message_type message type name
626
+	 * @param        $messenger
627
+	 * @return bool true if it got activated (or was active) and false if not.
628
+	 * @throws \EE_Error
629
+	 */
630
+	public function ensure_message_type_is_active($message_type, $messenger)
631
+	{
632
+		// EE_messages has been deprecated
633
+		$this->_class_is_deprecated(__FUNCTION__);
634
+		return $this->_message_resource_manager->ensure_message_type_is_active($message_type, $messenger);
635
+	}
636
+
637
+
638
+	/**
639
+	 * @deprecated 4.9.0
640
+	 * @param string $messenger_name
641
+	 * @param array  $mts_to_activate             (optional) An array of message types to activate with this messenger.
642
+	 *                                             If included we do NOT setup the default message types (assuming they
643
+	 *                                             are already setup.)
644
+	 * @return boolean an array of generated templates or false if nothing generated/activated.
645
+	 */
646
+	public function activate_messenger($messenger_name, $mts_to_activate = array())
647
+	{
648
+		// EE_messages has been deprecated
649
+		$this->_class_is_deprecated(__FUNCTION__);
650
+		return $this->_message_resource_manager->activate_messenger($messenger_name, $mts_to_activate);
651
+	}
652
+
653
+
654
+	/**
655
+	 * @deprecated 4.9.0
656
+	 * @param EE_messenger    $messenger    messenger used in trigger
657
+	 * @param EE_message_type $message_type message type used in trigger
658
+	 *
659
+	 * @return bool true is a generating messenger and can be sent OR FALSE meaning cannot send.
660
+	 */
661
+	public function is_generating_messenger_and_active(EE_messenger $messenger, EE_message_type $message_type)
662
+	{
663
+		// EE_messages has been deprecated
664
+		$this->_class_is_deprecated(__FUNCTION__);
665
+		return $this->_message_resource_manager->is_generating_messenger_and_active($messenger, $message_type);
666
+	}
667
+
668
+
669
+	/**
670
+	 * @deprecated 4.9.0
671
+	 * @param string $messenger
672
+	 * @return EE_messenger | null
673
+	 */
674
+	public function get_messenger_if_active($messenger)
675
+	{
676
+		// EE_messages has been deprecated
677
+		$this->_class_is_deprecated(__FUNCTION__);
678
+		return $this->_message_resource_manager->get_active_messenger($messenger);
679
+	}
680
+
681
+
682
+	/**
683
+	 * @deprecated 4.9.0
684
+	 * @param EE_Message $message
685
+	 * @return array  An array with 'messenger' and 'message_type' as the index and the corresponding valid object if
686
+	 *                  available.
687
+	 *                  Eg. Valid Messenger and Message Type:
688
+	 *                  array(
689
+	 *                  'messenger' => new EE_Email_messenger(),
690
+	 *                  'message_type' => new EE_Registration_Approved_message_type()
691
+	 *                  )
692
+	 *                  Valid Messenger and Invalid Message Type:
693
+	 *                  array(
694
+	 *                  'messenger' => new EE_Email_messenger(),
695
+	 *                  'message_type' => null
696
+	 *                  )
697
+	 */
698
+	public function validate_for_use(EE_Message $message)
699
+	{
700
+		// EE_messages has been deprecated
701
+		$this->_class_is_deprecated(__FUNCTION__);
702
+		return array(
703
+			'messenger'    => $message->messenger_object(),
704
+			'message_type' => $message->message_type_object(),
705
+		);
706
+	}
707
+
708
+
709
+	/**
710
+	 * @deprecated 4.9.0
711
+	 * @param  string $type                 What type of message are we sending (corresponds to message types)
712
+	 * @param  mixed  $vars                 Data being sent for parsing in the message
713
+	 * @param  string $sending_messenger    if included then we ONLY use the specified messenger for delivery.
714
+	 *                                      Otherwise we cycle through all active messengers.
715
+	 * @param string  $generating_messenger if included then this messenger is used for generating the message
716
+	 *                                      templates (but not for sending).
717
+	 * @param string  $context              If included then only a message type for a specific context will be
718
+	 *                                      generated.
719
+	 * @param bool    $send                 Default TRUE.  If false, then this will just return the generated
720
+	 *                                      EE_messages objects which might be used by the trigger to setup a batch
721
+	 *                                      message (typically html messenger uses it).
722
+	 * @return bool
723
+	 */
724
+	public function send_message(
725
+		$type,
726
+		$vars,
727
+		$sending_messenger = '',
728
+		$generating_messenger = '',
729
+		$context = '',
730
+		$send = true
731
+	) {
732
+		// EE_messages has been deprecated
733
+		$this->_class_is_deprecated(__FUNCTION__);
734
+		/** @type EE_Messages_Processor $processor */
735
+		$processor = EE_Registry::instance()->load_lib('Messages_Processor');
736
+		$error = false;
737
+		// try to intelligently determine what method we'll call based on the incoming data.
738
+		// if generating and sending are different then generate and send immediately.
739
+		if (! empty($sending_messenger) && $sending_messenger != $generating_messenger && $send) {
740
+			// in the legacy system, when generating and sending were different, that means all the
741
+			// vars are already in the request object.  So let's just use that.
742
+			try {
743
+				/** @type EE_Message_To_Generate_From_Request $mtg */
744
+				$mtg = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
745
+				$processor->generate_and_send_now($mtg);
746
+			} catch (EE_Error $e) {
747
+				$error_msg = esc_html__(
748
+					'Please note that a system message failed to send due to a technical issue.',
749
+					'event_espresso'
750
+				);
751
+				// add specific message for developers if WP_DEBUG in on
752
+				$error_msg .= '||' . $e->getMessage();
753
+				EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
754
+				$error = true;
755
+			}
756
+		} else {
757
+			$processor->generate_for_all_active_messengers($type, $vars, $send);
758
+			// let's find out if there were any errors and how many successfully were queued.
759
+			$count_errors = $processor->get_queue()->count_STS_in_queue(
760
+				array(EEM_Message::status_failed, EEM_Message::status_debug_only)
761
+			);
762
+			$count_queued = $processor->get_queue()->count_STS_in_queue(EEM_Message::status_incomplete);
763
+			$count_retry = $processor->get_queue()->count_STS_in_queue(EEM_Message::status_retry);
764
+			$count_errors = $count_errors + $count_retry;
765
+			if ($count_errors > 0) {
766
+				$error = true;
767
+				if ($count_errors > 1 && $count_retry > 1 && $count_queued > 1) {
768
+					$message = sprintf(
769
+						esc_html__(
770
+							'There were %d errors and %d messages successfully queued for generation and sending',
771
+							'event_espresso'
772
+						),
773
+						$count_errors,
774
+						$count_queued
775
+					);
776
+				} elseif ($count_errors > 1 && $count_queued === 1) {
777
+					$message = sprintf(
778
+						esc_html__(
779
+							'There were %d errors and %d message successfully queued for generation.',
780
+							'event_espresso'
781
+						),
782
+						$count_errors,
783
+						$count_queued
784
+					);
785
+				} elseif ($count_errors === 1 && $count_queued > 1) {
786
+					$message = sprintf(
787
+						esc_html__(
788
+							'There was %d error and %d messages successfully queued for generation.',
789
+							'event_espresso'
790
+						),
791
+						$count_errors,
792
+						$count_queued
793
+					);
794
+				} else {
795
+					$message = sprintf(
796
+						esc_html__(
797
+							'There was %d message that failed to be queued for generation.',
798
+							'event_espresso'
799
+						),
800
+						$count_errors
801
+					);
802
+				}
803
+				EE_Error::add_error($message, __FILE__, __FUNCTION__, __LINE__);
804
+			} else {
805
+				if ($count_queued === 1) {
806
+					$message = sprintf(
807
+						esc_html__(
808
+							'%d message successfully queued for generation.',
809
+							'event_espresso'
810
+						),
811
+						$count_queued
812
+					);
813
+				} else {
814
+					$message = sprintf(
815
+						esc_html__(
816
+							'%d messages were successfully queued for generation.',
817
+							'event_espresso'
818
+						),
819
+						$count_queued
820
+					);
821
+				}
822
+				EE_Error::add_success($message);
823
+			}
824
+		}
825
+		// if no error then return the generated message(s).
826
+		if (! $error && ! $send) {
827
+			$generated_queue = $processor->generate_queue(false);
828
+			// get message and return.
829
+			$generated_queue->get_message_repository()->rewind();
830
+			$messages = array();
831
+			while ($generated_queue->get_message_repository()->valid()) {
832
+				$message = $generated_queue->get_message_repository()->current();
833
+				if ($message instanceof EE_Message) {
834
+					// set properties that might be expected by add-ons (backward compat)
835
+					$message->content = $message->content();
836
+					$message->template_pack = $message->get_template_pack();
837
+					$message->template_variation = $message->get_template_pack_variation();
838
+					$messages[] = $message;
839
+				}
840
+				$generated_queue->get_message_repository()->next();
841
+			}
842
+			return $messages;
843
+		}
844
+		return $error ? false
845
+			: true; // yeah backwards eh?  Really what we're returning is if there is a total success for all the messages or not.  We'll modify this once we get message recording in place.
846
+	}
847
+
848
+
849
+	/**
850
+	 * @deprecated 4.9.0
851
+	 * @param  string $type      This should correspond with a valid message type
852
+	 * @param  string $context   This should correspond with a valid context for the message type
853
+	 * @param  string $messenger This should correspond with a valid messenger.
854
+	 * @param bool    $send      true we will do a test send using the messenger delivery, false we just do a regular
855
+	 *                           preview
856
+	 * @return string          The body of the message.
857
+	 */
858
+	public function preview_message($type, $context, $messenger, $send = false)
859
+	{
860
+		// EE_messages has been deprecated
861
+		$this->_class_is_deprecated(__FUNCTION__);
862
+		return EED_Messages::preview_message($type, $context, $messenger, $send);
863
+	}
864
+
865
+
866
+	/**
867
+	 * @since      4.5.0
868
+	 * @deprecated 4.9.0   Moved to EED_Messages Module
869
+	 * @param string   $messenger    a string matching a valid active messenger in the system
870
+	 * @param string   $message_type Although it seems contrary to the name of the method, a message type name is still
871
+	 *                               required to send along the message type to the messenger because this is used for
872
+	 *                               determining what specific variations might be loaded for the generated message.
873
+	 * @param stdClass $message      a stdClass object in the format expected by the messenger.
874
+	 *
875
+	 * @return bool          success or fail.
876
+	 */
877
+	public function send_message_with_messenger_only($messenger, $message_type, $message)
878
+	{
879
+		// EE_messages has been deprecated
880
+		$this->_class_is_deprecated(__FUNCTION__);
881
+		// setup for sending to new method.
882
+		/** @type EE_Messages_Queue $queue */
883
+		$queue = EE_Registry::instance()->load_lib('Messages_Queue');
884
+		// make sure we have a proper message object
885
+		if (! $message instanceof EE_Message && is_object($message) && isset($message->content)) {
886
+			$msg = EE_Message_Factory::create(
887
+				array(
888
+					'MSG_messenger'    => $messenger,
889
+					'MSG_message_type' => $message_type,
890
+					'MSG_content'      => $message->content,
891
+					'MSG_subject'      => $message->subject,
892
+				)
893
+			);
894
+		} else {
895
+			$msg = $message;
896
+		}
897
+		if (! $msg instanceof EE_Message) {
898
+			return false;
899
+		}
900
+		// make sure any content in a content property (if not empty) is set on the MSG_content.
901
+		if (! empty($msg->content)) {
902
+			$msg->set('MSG_content', $msg->content);
903
+		}
904
+		$queue->add($msg);
905
+		return EED_Messages::send_message_with_messenger_only($messenger, $message_type, $queue);
906
+	}
907
+
908
+
909
+	/**
910
+	 * @deprecated 4.9.0
911
+	 * @param         $messenger
912
+	 * @param  string $message_type message type that the templates are being created for
913
+	 * @param int     $GRP_ID
914
+	 * @param bool    $is_global
915
+	 * @return array|object if creation is successful then we return an array of info, otherwise an error_object is
916
+	 *                      returned.
917
+	 * @throws \EE_Error
918
+	 */
919
+	public function create_new_templates($messenger, $message_type, $GRP_ID = 0, $is_global = false)
920
+	{
921
+		// EE_messages has been deprecated
922
+		$this->_class_is_deprecated(__FUNCTION__);
923
+		EE_Registry::instance()->load_helper('MSG_Template');
924
+		return EEH_MSG_Template::create_new_templates($messenger, $message_type, $GRP_ID, $is_global);
925
+	}
926
+
927
+
928
+	/**
929
+	 * @deprecated 4.9.0
930
+	 * @param  string $messenger_name    name of EE_messenger
931
+	 * @param  string $message_type_name name of EE_message_type
932
+	 * @return array
933
+	 */
934
+	public function get_fields($messenger_name, $message_type_name)
935
+	{
936
+		// EE_messages has been deprecated
937
+		$this->_class_is_deprecated(__FUNCTION__);
938
+		EE_Registry::instance()->load_helper('MSG_Template');
939
+		return EEH_MSG_Template::get_fields($messenger_name, $message_type_name);
940
+	}
941
+
942
+
943
+	/**
944
+	 * @deprecated 4.9.0
945
+	 * @access     public
946
+	 * @param string $type                we can indicate just returning installed message types
947
+	 *                                    or messengers (or both) via this parameter.
948
+	 * @param bool   $skip_cache          if true then we skip the cache and retrieve via files.
949
+	 * @return array                    multidimensional array of messenger and message_type objects
950
+	 *                                    (messengers index, and message_type index);
951
+	 */
952
+	public function get_installed($type = 'all', $skip_cache = false)
953
+	{
954
+		// EE_messages has been deprecated
955
+		$this->_class_is_deprecated(__FUNCTION__);
956
+		if ($skip_cache) {
957
+			$this->_message_resource_manager->reset_active_messengers_and_message_types();
958
+		}
959
+		switch ($type) {
960
+			case 'messengers' :
961
+				return array(
962
+					'messenger' => $this->_message_resource_manager->installed_messengers(),
963
+				);
964
+				break;
965
+			case 'message_types' :
966
+				return array(
967
+					'message_type' => $this->_message_resource_manager->installed_message_types(),
968
+				);
969
+				break;
970
+			case 'all' :
971
+			default :
972
+				return array(
973
+					'messenger'    => $this->_message_resource_manager->installed_messengers(),
974
+					'message_type' => $this->_message_resource_manager->installed_message_types(),
975
+				);
976
+				break;
977
+		}
978
+	}
979
+
980
+
981
+	/**
982
+	 * @deprecated 4.9.0
983
+	 * @return \EE_messenger[]
984
+	 */
985
+	public function get_active_messengers()
986
+	{
987
+		// EE_messages has been deprecated
988
+		$this->_class_is_deprecated(__FUNCTION__);
989
+		return $this->_message_resource_manager->active_messengers();
990
+	}
991
+
992
+
993
+	/**
994
+	 * @deprecated 4.9.0
995
+	 * @return array array of message_type references (string)
996
+	 */
997
+	public function get_active_message_types()
998
+	{
999
+		// EE_messages has been deprecated
1000
+		$this->_class_is_deprecated(__FUNCTION__);
1001
+		return $this->_message_resource_manager->list_of_active_message_types();
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * @deprecated 4.9.0
1007
+	 * @return EE_message_type[]
1008
+	 */
1009
+	public function get_active_message_type_objects()
1010
+	{
1011
+		// EE_messages has been deprecated
1012
+		$this->_class_is_deprecated(__FUNCTION__);
1013
+		return $this->_message_resource_manager->get_active_message_type_objects();
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * @deprecated 4.9.0
1019
+	 * @since      4.5.0
1020
+	 * @param string $messenger The messenger being checked
1021
+	 * @return EE_message_type[]    (or empty array if none present)
1022
+	 */
1023
+	public function get_active_message_types_per_messenger($messenger)
1024
+	{
1025
+		// EE_messages has been deprecated
1026
+		$this->_class_is_deprecated(__FUNCTION__);
1027
+		return $this->_message_resource_manager->get_active_message_types_for_messenger($messenger);
1028
+	}
1029
+
1030
+
1031
+	/**
1032
+	 * @deprecated 4.9.0
1033
+	 * @param string $messenger    The string should correspond to the messenger (message types are
1034
+	 * @param string $message_type The string should correspond to a message type.
1035
+	 * @return EE_message_type|null
1036
+	 */
1037
+	public function get_active_message_type($messenger, $message_type)
1038
+	{
1039
+		// EE_messages has been deprecated
1040
+		$this->_class_is_deprecated(__FUNCTION__);
1041
+		return $this->_message_resource_manager->get_active_message_type_for_messenger($messenger, $message_type);
1042
+	}
1043
+
1044
+
1045
+	/**
1046
+	 * @deprecated 4.9.0
1047
+	 * @return array|\EE_message_type[]
1048
+	 */
1049
+	public function get_installed_message_types()
1050
+	{
1051
+		// EE_messages has been deprecated
1052
+		$this->_class_is_deprecated(__FUNCTION__);
1053
+		return $this->_message_resource_manager->installed_message_types();
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 * @deprecated 4.9.0
1059
+	 * @return array
1060
+	 */
1061
+	public function get_installed_messengers()
1062
+	{
1063
+		// EE_messages has been deprecated
1064
+		$this->_class_is_deprecated(__FUNCTION__);
1065
+		return $this->_message_resource_manager->installed_messengers();
1066
+	}
1067
+
1068
+
1069
+	/**
1070
+	 * @deprecated 4.9.0
1071
+	 * @param   bool $slugs_only Whether to return an array of just slugs and labels (true) or all contexts indexed by
1072
+	 *                           message type.
1073
+	 * @return array
1074
+	 */
1075
+	public function get_all_contexts($slugs_only = true)
1076
+	{
1077
+		// EE_messages has been deprecated
1078
+		$this->_class_is_deprecated(__FUNCTION__);
1079
+		return $this->_message_resource_manager->get_all_contexts($slugs_only);
1080
+	}
1081 1081
 
1082 1082
 
1083 1083
 }
@@ -1136,88 +1136,88 @@  discard block
 block discarded – undo
1136 1136
 
1137 1137
 
1138 1138
 add_filter(
1139
-    'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
1140
-    function ($event_list_iframe_css) {
1141
-        if (! has_filter('FHEE__EventsArchiveIframe__event_list_iframe__css')) {
1142
-            return $event_list_iframe_css;
1143
-        }
1144
-        deprecated_espresso_action_or_filter_doing_it_wrong(
1145
-            'FHEE__EventsArchiveIframe__event_list_iframe__css',
1146
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
1147
-            '\EventEspresso\modules\events_archive\EventsArchiveIframe::display()',
1148
-            '4.9.14',
1149
-            '5.0.0',
1150
-            'filter'
1151
-        );
1152
-        return apply_filters(
1153
-            'FHEE__EventsArchiveIframe__event_list_iframe__css',
1154
-            $event_list_iframe_css
1155
-        );
1156
-    }
1139
+	'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
1140
+	function ($event_list_iframe_css) {
1141
+		if (! has_filter('FHEE__EventsArchiveIframe__event_list_iframe__css')) {
1142
+			return $event_list_iframe_css;
1143
+		}
1144
+		deprecated_espresso_action_or_filter_doing_it_wrong(
1145
+			'FHEE__EventsArchiveIframe__event_list_iframe__css',
1146
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
1147
+			'\EventEspresso\modules\events_archive\EventsArchiveIframe::display()',
1148
+			'4.9.14',
1149
+			'5.0.0',
1150
+			'filter'
1151
+		);
1152
+		return apply_filters(
1153
+			'FHEE__EventsArchiveIframe__event_list_iframe__css',
1154
+			$event_list_iframe_css
1155
+		);
1156
+	}
1157 1157
 );
1158 1158
 add_filter(
1159
-    'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
1160
-    function ($event_list_iframe_js) {
1161
-        if (! has_filter('FHEE__EED_Ticket_Selector__ticket_selector_iframe__js')) {
1162
-            return $event_list_iframe_js;
1163
-        }
1164
-        deprecated_espresso_action_or_filter_doing_it_wrong(
1165
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
1166
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
1167
-            '\EventEspresso\modules\events_archive\EventsArchiveIframe::display()',
1168
-            '4.9.14',
1169
-            '5.0.0',
1170
-            'filter'
1171
-        );
1172
-        return apply_filters(
1173
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
1174
-            $event_list_iframe_js
1175
-        );
1176
-    }
1159
+	'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
1160
+	function ($event_list_iframe_js) {
1161
+		if (! has_filter('FHEE__EED_Ticket_Selector__ticket_selector_iframe__js')) {
1162
+			return $event_list_iframe_js;
1163
+		}
1164
+		deprecated_espresso_action_or_filter_doing_it_wrong(
1165
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
1166
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
1167
+			'\EventEspresso\modules\events_archive\EventsArchiveIframe::display()',
1168
+			'4.9.14',
1169
+			'5.0.0',
1170
+			'filter'
1171
+		);
1172
+		return apply_filters(
1173
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
1174
+			$event_list_iframe_js
1175
+		);
1176
+	}
1177 1177
 );
1178 1178
 add_action(
1179
-    'AHEE__EE_Capabilities__addCaps__complete',
1180
-    function ($capabilities_map) {
1181
-        if (! has_action('AHEE__EE_Capabilities__init_role_caps__complete')) {
1182
-            return;
1183
-        }
1184
-        deprecated_espresso_action_or_filter_doing_it_wrong(
1185
-            'AHEE__EE_Capabilities__init_role_caps__complete',
1186
-            'AHEE__EE_Capabilities__addCaps__complete',
1187
-            '\EE_Capabilities::addCaps()',
1188
-            '4.9.42',
1189
-            '5.0.0'
1190
-        );
1191
-        do_action(
1192
-            'AHEE__EE_Capabilities__init_role_caps__complete',
1193
-            $capabilities_map
1194
-        );
1195
-    }
1179
+	'AHEE__EE_Capabilities__addCaps__complete',
1180
+	function ($capabilities_map) {
1181
+		if (! has_action('AHEE__EE_Capabilities__init_role_caps__complete')) {
1182
+			return;
1183
+		}
1184
+		deprecated_espresso_action_or_filter_doing_it_wrong(
1185
+			'AHEE__EE_Capabilities__init_role_caps__complete',
1186
+			'AHEE__EE_Capabilities__addCaps__complete',
1187
+			'\EE_Capabilities::addCaps()',
1188
+			'4.9.42',
1189
+			'5.0.0'
1190
+		);
1191
+		do_action(
1192
+			'AHEE__EE_Capabilities__init_role_caps__complete',
1193
+			$capabilities_map
1194
+		);
1195
+	}
1196 1196
 );
1197 1197
 
1198 1198
 add_filter(
1199
-    'FHEE_EventEspresso_core_domain_services_commands_attendee_CreateAttendeeCommandHandler__findExistingAttendee__existing_attendee',
1200
-    function($existing_attendee, $registration, $attendee_data) {
1201
-        if ( ! has_filter( 'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee' )) {
1202
-            return $existing_attendee;
1203
-        }
1204
-        deprecated_espresso_action_or_filter_doing_it_wrong(
1205
-            'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee',
1206
-            'FHEE_EventEspresso_core_domain_services_commands_attendee_CreateAttendeeCommandHandler__findExistingAttendee__existing_attendee',
1207
-            '\EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler::findExistingAttendee()',
1208
-            '4.9.34',
1209
-            '5.0.0',
1210
-            'filter'
1211
-        );
1212
-        return apply_filters(
1213
-            'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee',
1214
-            $existing_attendee,
1215
-            $registration,
1216
-            $attendee_data
1217
-        );
1218
-    },
1219
-    10,
1220
-    3
1199
+	'FHEE_EventEspresso_core_domain_services_commands_attendee_CreateAttendeeCommandHandler__findExistingAttendee__existing_attendee',
1200
+	function($existing_attendee, $registration, $attendee_data) {
1201
+		if ( ! has_filter( 'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee' )) {
1202
+			return $existing_attendee;
1203
+		}
1204
+		deprecated_espresso_action_or_filter_doing_it_wrong(
1205
+			'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee',
1206
+			'FHEE_EventEspresso_core_domain_services_commands_attendee_CreateAttendeeCommandHandler__findExistingAttendee__existing_attendee',
1207
+			'\EventEspresso\core\domain\services\commands\attendee\CreateAttendeeCommandHandler::findExistingAttendee()',
1208
+			'4.9.34',
1209
+			'5.0.0',
1210
+			'filter'
1211
+		);
1212
+		return apply_filters(
1213
+			'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee',
1214
+			$existing_attendee,
1215
+			$registration,
1216
+			$attendee_data
1217
+		);
1218
+	},
1219
+	10,
1220
+	3
1221 1221
 );
1222 1222
 
1223 1223
 /**
@@ -1228,88 +1228,88 @@  discard block
 block discarded – undo
1228 1228
 class EE_Event_List_Query extends WP_Query
1229 1229
 {
1230 1230
 
1231
-    private $title;
1232
-
1233
-    private $css_class;
1234
-
1235
-    private $category_slug;
1236
-
1237
-    /**
1238
-     * EE_Event_List_Query constructor.
1239
-     *
1240
-     * @param array $args
1241
-     */
1242
-    public function __construct($args = array())
1243
-    {
1244
-        \EE_Error::doing_it_wrong(
1245
-            __METHOD__,
1246
-            esc_html__(
1247
-                'Usage is deprecated. Please use \EventEspresso\core\domain\services\wp_queries\EventListQuery instead.',
1248
-                'event_espresso'
1249
-            ),
1250
-            '4.9.27',
1251
-            '5.0.0'
1252
-        );
1253
-        $this->title = isset($args['title']) ? $args['title'] : '';
1254
-        $this->css_class = isset($args['css_class']) ? $args['css_class'] : '';
1255
-        $this->category_slug = isset($args['category_slug']) ? $args['category_slug'] : '';
1256
-        $limit = isset($args['limit']) && absint($args['limit']) ? $args['limit'] : 10;
1257
-        // the current "page" we are viewing
1258
-        $paged = max(1, get_query_var('paged'));
1259
-        // Force these args
1260
-        $args = array_merge(
1261
-            $args,
1262
-            array(
1263
-                'post_type'              => 'espresso_events',
1264
-                'posts_per_page'         => $limit,
1265
-                'update_post_term_cache' => false,
1266
-                'update_post_meta_cache' => false,
1267
-                'paged'                  => $paged,
1268
-                'offset'                 => ($paged - 1) * $limit,
1269
-            )
1270
-        );
1271
-        // run the query
1272
-        parent::__construct($args);
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * event_list_title
1278
-     *
1279
-     * @param string $event_list_title
1280
-     * @return string
1281
-     */
1282
-    public function event_list_title($event_list_title = '')
1283
-    {
1284
-        if (! empty($this->title)) {
1285
-            return $this->title;
1286
-        }
1287
-        return $event_list_title;
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * event_list_css
1293
-     *
1294
-     * @param string $event_list_css
1295
-     * @return string
1296
-     */
1297
-    public function event_list_css($event_list_css = '')
1298
-    {
1299
-        $event_list_css .= ! empty($event_list_css)
1300
-            ? ' '
1301
-            : '';
1302
-        $event_list_css .= ! empty($this->css_class)
1303
-            ? $this->css_class
1304
-            : '';
1305
-        $event_list_css .= ! empty($event_list_css)
1306
-            ? ' '
1307
-            : '';
1308
-        $event_list_css .= ! empty($this->category_slug)
1309
-            ? $this->category_slug
1310
-            : '';
1311
-        return $event_list_css;
1312
-    }
1231
+	private $title;
1232
+
1233
+	private $css_class;
1234
+
1235
+	private $category_slug;
1236
+
1237
+	/**
1238
+	 * EE_Event_List_Query constructor.
1239
+	 *
1240
+	 * @param array $args
1241
+	 */
1242
+	public function __construct($args = array())
1243
+	{
1244
+		\EE_Error::doing_it_wrong(
1245
+			__METHOD__,
1246
+			esc_html__(
1247
+				'Usage is deprecated. Please use \EventEspresso\core\domain\services\wp_queries\EventListQuery instead.',
1248
+				'event_espresso'
1249
+			),
1250
+			'4.9.27',
1251
+			'5.0.0'
1252
+		);
1253
+		$this->title = isset($args['title']) ? $args['title'] : '';
1254
+		$this->css_class = isset($args['css_class']) ? $args['css_class'] : '';
1255
+		$this->category_slug = isset($args['category_slug']) ? $args['category_slug'] : '';
1256
+		$limit = isset($args['limit']) && absint($args['limit']) ? $args['limit'] : 10;
1257
+		// the current "page" we are viewing
1258
+		$paged = max(1, get_query_var('paged'));
1259
+		// Force these args
1260
+		$args = array_merge(
1261
+			$args,
1262
+			array(
1263
+				'post_type'              => 'espresso_events',
1264
+				'posts_per_page'         => $limit,
1265
+				'update_post_term_cache' => false,
1266
+				'update_post_meta_cache' => false,
1267
+				'paged'                  => $paged,
1268
+				'offset'                 => ($paged - 1) * $limit,
1269
+			)
1270
+		);
1271
+		// run the query
1272
+		parent::__construct($args);
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * event_list_title
1278
+	 *
1279
+	 * @param string $event_list_title
1280
+	 * @return string
1281
+	 */
1282
+	public function event_list_title($event_list_title = '')
1283
+	{
1284
+		if (! empty($this->title)) {
1285
+			return $this->title;
1286
+		}
1287
+		return $event_list_title;
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * event_list_css
1293
+	 *
1294
+	 * @param string $event_list_css
1295
+	 * @return string
1296
+	 */
1297
+	public function event_list_css($event_list_css = '')
1298
+	{
1299
+		$event_list_css .= ! empty($event_list_css)
1300
+			? ' '
1301
+			: '';
1302
+		$event_list_css .= ! empty($this->css_class)
1303
+			? $this->css_class
1304
+			: '';
1305
+		$event_list_css .= ! empty($event_list_css)
1306
+			? ' '
1307
+			: '';
1308
+		$event_list_css .= ! empty($this->category_slug)
1309
+			? $this->category_slug
1310
+			: '';
1311
+		return $event_list_css;
1312
+	}
1313 1313
 
1314 1314
 }
1315 1315
 
@@ -1326,75 +1326,75 @@  discard block
 block discarded – undo
1326 1326
 {
1327 1327
 
1328 1328
 
1329
-    /**
1330
-     *    class constructor
1331
-     *
1332
-     * @deprecated 4.9.59.p
1333
-     */
1334
-    public function __construct()
1335
-    {
1336
-        EE_Error::doing_it_wrong(
1337
-            __METHOD__,
1338
-            sprintf(
1339
-                esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1340
-                __CLASS__,
1341
-                'EventEspresso\core\services\licensing\LicenseServices'
1342
-            ),
1343
-            '4.9.59.p'
1344
-        );
1345
-    }
1346
-
1347
-
1348
-    /**
1349
-     * The purpose of this function is to display information about Event Espresso data collection
1350
-     * and a optin selection for extra data collecting by users.
1351
-     *
1352
-     * @param bool $extra
1353
-     * @return string html.
1354
-     * @deprecated 4.9.59.p
1355
-     */
1356
-    public static function espresso_data_collection_optin_text($extra = true)
1357
-    {
1358
-        EE_Error::doing_it_wrong(
1359
-            __METHOD__,
1360
-            sprintf(
1361
-                esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1362
-                __METHOD__,
1363
-                'EventEspresso\core\domain\services\Stats::optinText'
1364
-            ),
1365
-            '4.9.59.p'
1366
-        );
1367
-        Stats::optinText($extra);
1368
-    }
1369
-
1370
-    /**
1371
-     * This is a handy helper method for retrieving whether there is an update available for the given plugin.
1372
-     *
1373
-     * @param  string $basename Use the equivalent result from plugin_basename() for this param as WP uses that to
1374
-     *                          identify plugins. Defaults to core update
1375
-     * @return boolean           True if update available, false if not.
1376
-     * @deprecated 4.9.59.p
1377
-     */
1378
-    public static function is_update_available($basename = '')
1379
-    {
1380
-        EE_Error::doing_it_wrong(
1381
-            __METHOD__,
1382
-            sprintf(
1383
-                esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1384
-                __METHOD__,
1385
-                'EventEspresso\core\services\licensing\LicenseService::isUpdateAvailable'
1386
-            ),
1387
-            '4.9.59.p'
1388
-        );
1389
-        return LicenseService::isUpdateAvailable($basename);
1390
-    }
1329
+	/**
1330
+	 *    class constructor
1331
+	 *
1332
+	 * @deprecated 4.9.59.p
1333
+	 */
1334
+	public function __construct()
1335
+	{
1336
+		EE_Error::doing_it_wrong(
1337
+			__METHOD__,
1338
+			sprintf(
1339
+				esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1340
+				__CLASS__,
1341
+				'EventEspresso\core\services\licensing\LicenseServices'
1342
+			),
1343
+			'4.9.59.p'
1344
+		);
1345
+	}
1346
+
1347
+
1348
+	/**
1349
+	 * The purpose of this function is to display information about Event Espresso data collection
1350
+	 * and a optin selection for extra data collecting by users.
1351
+	 *
1352
+	 * @param bool $extra
1353
+	 * @return string html.
1354
+	 * @deprecated 4.9.59.p
1355
+	 */
1356
+	public static function espresso_data_collection_optin_text($extra = true)
1357
+	{
1358
+		EE_Error::doing_it_wrong(
1359
+			__METHOD__,
1360
+			sprintf(
1361
+				esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1362
+				__METHOD__,
1363
+				'EventEspresso\core\domain\services\Stats::optinText'
1364
+			),
1365
+			'4.9.59.p'
1366
+		);
1367
+		Stats::optinText($extra);
1368
+	}
1369
+
1370
+	/**
1371
+	 * This is a handy helper method for retrieving whether there is an update available for the given plugin.
1372
+	 *
1373
+	 * @param  string $basename Use the equivalent result from plugin_basename() for this param as WP uses that to
1374
+	 *                          identify plugins. Defaults to core update
1375
+	 * @return boolean           True if update available, false if not.
1376
+	 * @deprecated 4.9.59.p
1377
+	 */
1378
+	public static function is_update_available($basename = '')
1379
+	{
1380
+		EE_Error::doing_it_wrong(
1381
+			__METHOD__,
1382
+			sprintf(
1383
+				esc_html__('%1$s has been replaced by %2$s.', 'event_espresso'),
1384
+				__METHOD__,
1385
+				'EventEspresso\core\services\licensing\LicenseService::isUpdateAvailable'
1386
+			),
1387
+			'4.9.59.p'
1388
+		);
1389
+		return LicenseService::isUpdateAvailable($basename);
1390
+	}
1391 1391
 }
1392 1392
 
1393 1393
 add_filter(
1394
-    'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
1395
-    'ee_deprecated_registrations_report_csv_legacy_fields',
1396
-    10,
1397
-    2
1394
+	'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array',
1395
+	'ee_deprecated_registrations_report_csv_legacy_fields',
1396
+	10,
1397
+	2
1398 1398
 );
1399 1399
 /**
1400 1400
  * Filters the CSV row to make it appear like the old labels (which were "$pretty_name[$field_name]").
@@ -1411,96 +1411,96 @@  discard block
 block discarded – undo
1411 1411
  */
1412 1412
 function ee_deprecated_registrations_report_csv_legacy_fields($csv_row_data, $reg_row)
1413 1413
 {
1414
-    // no need for all this if nobody is using the deprecated filter
1415
-    if (has_filter('FHEE__EE_Export__report_registrations__reg_csv_array')) {
1416
-        EE_Error::doing_it_wrong(
1417
-            __FUNCTION__,
1418
-            sprintf(
1419
-                // EE_Error::doing_it_wrong with escape HTML, so don't escape it twice by doing it here too.
1420
-                _x(
1421
-                    'The filter "%1$s" has been deprecated. Please use "%2$s" instead.',
1422
-                    'The filter "FHEE__EE_Export__report_registrations__reg_csv_array" has been deprecated. Please use "FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array" instead.',
1423
-                    'event_espresso'
1424
-                ),
1425
-                'FHEE__EE_Export__report_registrations__reg_csv_array',
1426
-                'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array'
1427
-            ),
1428
-            '4.9.69.p',
1429
-            '4.9.75.p'
1430
-        );
1431
-        // there's code that expected the old csv column headers/labels. Let's oblige. Put it back in the old format!
1432
-        // first: what model fields might be used as column headers? (whose format we need to change)
1433
-        $model_fields = array_merge(
1434
-            EEM_Registration::instance()->field_settings(),
1435
-            EEM_Attendee::instance()->field_settings()
1436
-        );
1437
-        // create an array that uses the legacy column headers/labels.
1438
-        $new_csv_row = array();
1439
-        foreach ($csv_row_data as $label => $value) {
1440
-            $new_label = $label;
1441
-            foreach ($model_fields as $field) {
1442
-                if ($label === EEH_Export::get_column_name_for_field($field)) {
1443
-                    // re-add the old field name
1444
-                    $new_label = $label . '[' . $field->get_name() . ']';
1445
-                    break;
1446
-                }
1447
-            }
1448
-            $new_csv_row[$new_label] = $value;
1449
-        }
1450
-        // before we run it through the deprecated filter, set the method `EEH_Export::get_column_name_for_field()`
1451
-        // to create the old column names, because that's what's in the row temporarily
1452
-        add_filter(
1453
-            'FHEE__EEH_Export__get_column_name_for_field__add_field_name',
1454
-            '__return_true',
1455
-            777
1456
-        );
1457
-        // now, those old filters can be run on this data. Have fun!
1458
-        /**
1459
-         * Deprecated. Use FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array instead.
1460
-         *
1461
-         * Filter to change the contents of each row of the registrations report CSV file.
1462
-         * This can be used to add or remote columns from the CSV file, or change their values.                 *
1463
-         * Note: it has this name because originally that's where this filter resided,
1464
-         * and we've left its name as-is for backward compatibility.
1465
-         * Note when using: all rows in the CSV should have the same columns.
1466
-         *
1467
-         * @param array $reg_csv_array keys are column-header names, and values are that columns' value
1468
-         *                             in this row
1469
-         * @param array $reg_row is the row from the database's wp_esp_registration table
1470
-         */
1471
-        $updated_row = apply_filters(
1472
-            'FHEE__EE_Export__report_registrations__reg_csv_array',
1473
-            $new_csv_row,
1474
-            $reg_row
1475
-        );
1476
-
1477
-        // ok now we can revert to normal for EEH_Export::get_column_name_for_field().
1478
-        remove_filter(
1479
-            'FHEE__EEH_Export__get_column_name_for_field__add_field_name',
1480
-            '__return_true',
1481
-            777
1482
-        );
1483
-
1484
-        // great. Now that the old filters are done, we can remove the ugly square brackets from column headers/labels.
1485
-        $updated_and_restored_row = array();
1486
-        foreach ($updated_row as $label => $value) {
1487
-            $matches = array();
1488
-            if (preg_match(
1489
-                    '~([^\[]*)\[(.*)\]~',
1490
-                    $label,
1491
-                    $matches
1492
-                )
1493
-                && isset(
1494
-                    $matches[0],
1495
-                    $matches[1],
1496
-                    $matches[2]
1497
-                )
1498
-            ) {
1499
-                $label = $matches[1];
1500
-            }
1501
-            $updated_and_restored_row[$label] = $value;
1502
-        }
1503
-        $csv_row_data = $updated_and_restored_row;
1504
-    }
1505
-    return $csv_row_data;
1414
+	// no need for all this if nobody is using the deprecated filter
1415
+	if (has_filter('FHEE__EE_Export__report_registrations__reg_csv_array')) {
1416
+		EE_Error::doing_it_wrong(
1417
+			__FUNCTION__,
1418
+			sprintf(
1419
+				// EE_Error::doing_it_wrong with escape HTML, so don't escape it twice by doing it here too.
1420
+				_x(
1421
+					'The filter "%1$s" has been deprecated. Please use "%2$s" instead.',
1422
+					'The filter "FHEE__EE_Export__report_registrations__reg_csv_array" has been deprecated. Please use "FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array" instead.',
1423
+					'event_espresso'
1424
+				),
1425
+				'FHEE__EE_Export__report_registrations__reg_csv_array',
1426
+				'FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array'
1427
+			),
1428
+			'4.9.69.p',
1429
+			'4.9.75.p'
1430
+		);
1431
+		// there's code that expected the old csv column headers/labels. Let's oblige. Put it back in the old format!
1432
+		// first: what model fields might be used as column headers? (whose format we need to change)
1433
+		$model_fields = array_merge(
1434
+			EEM_Registration::instance()->field_settings(),
1435
+			EEM_Attendee::instance()->field_settings()
1436
+		);
1437
+		// create an array that uses the legacy column headers/labels.
1438
+		$new_csv_row = array();
1439
+		foreach ($csv_row_data as $label => $value) {
1440
+			$new_label = $label;
1441
+			foreach ($model_fields as $field) {
1442
+				if ($label === EEH_Export::get_column_name_for_field($field)) {
1443
+					// re-add the old field name
1444
+					$new_label = $label . '[' . $field->get_name() . ']';
1445
+					break;
1446
+				}
1447
+			}
1448
+			$new_csv_row[$new_label] = $value;
1449
+		}
1450
+		// before we run it through the deprecated filter, set the method `EEH_Export::get_column_name_for_field()`
1451
+		// to create the old column names, because that's what's in the row temporarily
1452
+		add_filter(
1453
+			'FHEE__EEH_Export__get_column_name_for_field__add_field_name',
1454
+			'__return_true',
1455
+			777
1456
+		);
1457
+		// now, those old filters can be run on this data. Have fun!
1458
+		/**
1459
+		 * Deprecated. Use FHEE__EventEspressoBatchRequest__JobHandlers__RegistrationsReport__reg_csv_array instead.
1460
+		 *
1461
+		 * Filter to change the contents of each row of the registrations report CSV file.
1462
+		 * This can be used to add or remote columns from the CSV file, or change their values.                 *
1463
+		 * Note: it has this name because originally that's where this filter resided,
1464
+		 * and we've left its name as-is for backward compatibility.
1465
+		 * Note when using: all rows in the CSV should have the same columns.
1466
+		 *
1467
+		 * @param array $reg_csv_array keys are column-header names, and values are that columns' value
1468
+		 *                             in this row
1469
+		 * @param array $reg_row is the row from the database's wp_esp_registration table
1470
+		 */
1471
+		$updated_row = apply_filters(
1472
+			'FHEE__EE_Export__report_registrations__reg_csv_array',
1473
+			$new_csv_row,
1474
+			$reg_row
1475
+		);
1476
+
1477
+		// ok now we can revert to normal for EEH_Export::get_column_name_for_field().
1478
+		remove_filter(
1479
+			'FHEE__EEH_Export__get_column_name_for_field__add_field_name',
1480
+			'__return_true',
1481
+			777
1482
+		);
1483
+
1484
+		// great. Now that the old filters are done, we can remove the ugly square brackets from column headers/labels.
1485
+		$updated_and_restored_row = array();
1486
+		foreach ($updated_row as $label => $value) {
1487
+			$matches = array();
1488
+			if (preg_match(
1489
+					'~([^\[]*)\[(.*)\]~',
1490
+					$label,
1491
+					$matches
1492
+				)
1493
+				&& isset(
1494
+					$matches[0],
1495
+					$matches[1],
1496
+					$matches[2]
1497
+				)
1498
+			) {
1499
+				$label = $matches[1];
1500
+			}
1501
+			$updated_and_restored_row[$label] = $value;
1502
+		}
1503
+		$csv_row_data = $updated_and_restored_row;
1504
+	}
1505
+	return $csv_row_data;
1506 1506
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -86,20 +86,20 @@  discard block
 block discarded – undo
86 86
     // loop thru and call doing_it_wrong() or remove any that aren't being used
87 87
     foreach ($deprecated_filters as $deprecated_filter => $on) {
88 88
         // was this filter called ?
89
-        if (has_action('FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter)) {
89
+        if (has_action('FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__'.$deprecated_filter)) {
90 90
             // only display doing_it_wrong() notice to Event Admins during non-AJAX requests
91 91
             if (EE_Registry::instance()->CAP->current_user_can(
92 92
                     'ee_read_ee',
93 93
                     'hide_doing_it_wrong_for_deprecated_SPCO_filter'
94 94
                 ) && ! defined('DOING_AJAX')) {
95 95
                 EE_Error::doing_it_wrong(
96
-                    'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
96
+                    'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__'.$deprecated_filter,
97 97
                     sprintf(
98 98
                         esc_html__(
99 99
                             'The %1$s filter is deprecated.  It *may* work as an attempt to build in backwards compatibility.  However, it is recommended to use the following new filter: %2$s"%3$s" found in "%4$s"',
100 100
                             'event_espresso'
101 101
                         ),
102
-                        'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__' . $deprecated_filter,
102
+                        'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__'.$deprecated_filter,
103 103
                         '<br />',
104 104
                         'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
105 105
                         '/modules/single_page_checkout/inc/EE_SPCO_Reg_Step.class.php'
@@ -108,10 +108,10 @@  discard block
 block discarded – undo
108 108
                 );
109 109
             }
110 110
         } else {
111
-            unset($deprecated_filters[ $deprecated_filter ]);
111
+            unset($deprecated_filters[$deprecated_filter]);
112 112
         }
113 113
     }
114
-    if (! empty($deprecated_filters)) {
114
+    if ( ! empty($deprecated_filters)) {
115 115
 
116 116
         if ($checkout->current_step->slug(
117 117
             ) == 'attendee_information' && $checkout->revisit && isset($deprecated_filters['update_registration_details'])) {
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
                 $submit_button_text = apply_filters(
146 146
                                           'FHEE__EED_Single_Page_Checkout__registration_checkout__button_text__proceed_to',
147 147
                                           $submit_button_text
148
-                                      ) . $checkout->next_step->name();
148
+                                      ).$checkout->next_step->name();
149 149
             }
150 150
         }
151 151
 
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
             'event_espresso'
330 330
         );
331 331
         EE_Error::doing_it_wrong(
332
-            __CLASS__ . '::' . __FUNCTION__,
332
+            __CLASS__.'::'.__FUNCTION__,
333 333
             $msg,
334 334
             '4.8.32.rc.000'
335 335
         );
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
 function ee_deprecated_update_attendee_registration_form_old($admin_page)
357 357
 {
358 358
     // check if the old hooks are in use. If not, do the default
359
-    if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
359
+    if ( ! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
360 360
         || ! $admin_page instanceof EE_Admin_Page) {
361 361
         return;
362 362
     }
@@ -364,7 +364,7 @@  discard block
 block discarded – undo
364 364
     $qstns = isset($req_data['qstn']) ? $req_data['qstn'] : false;
365 365
     $REG_ID = isset($req_data['_REG_ID']) ? absint($req_data['_REG_ID']) : false;
366 366
     $qstns = apply_filters('FHEE__Registrations_Admin_Page___update_attendee_registration_form__qstns', $qstns);
367
-    if (! $REG_ID || ! $qstns) {
367
+    if ( ! $REG_ID || ! $qstns) {
368 368
         EE_Error::add_error(
369 369
             esc_html__('An error occurred. No registration ID and/or registration questions were received.', 'event_espresso'),
370 370
             __FILE__,
@@ -384,13 +384,13 @@  discard block
 block discarded – undo
384 384
 
385 385
     foreach ($qstns as $QST_ID => $qstn) {
386 386
         // if $qstn isn't an array then it doesn't already have an answer, so let's create the answer
387
-        if (! is_array($qstn)) {
387
+        if ( ! is_array($qstn)) {
388 388
             $set_values = [
389 389
                 'QST_ID'    => $QST_ID,
390 390
                 'REG_ID'    => $REG_ID,
391 391
                 'ANS_value' => $qstn,
392 392
             ];
393
-            $success    = EEM_Answer::instance()->insert($set_values);
393
+            $success = EEM_Answer::instance()->insert($set_values);
394 394
             continue;
395 395
         }
396 396
 
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
             );
407 407
             $answer = EEM_Answer::instance()->get_one($query_params);
408 408
             // this MAY be an array but NOT have an answer because its multi select.  If so then we need to create the answer
409
-            if (! $answer instanceof EE_Answer) {
409
+            if ( ! $answer instanceof EE_Answer) {
410 410
                 $set_values = array(
411 411
                     'QST_ID'    => $QST_ID,
412 412
                     'REG_ID'    => $REG_ID,
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
 function ee_deprecated_reg_questions_meta_box_old($do_default_action, $admin_page, $registration)
448 448
 {
449 449
     // check if the old hooks are in use. If not, do the default
450
-    if (! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
450
+    if ( ! ee_deprecated_using_old_registration_admin_custom_questions_form_hooks()
451 451
         || ! $admin_page instanceof EE_Admin_Page) {
452 452
         return $do_default_action;
453 453
     }
@@ -479,7 +479,7 @@  discard block
 block discarded – undo
479 479
         'reg_questions_form_action' => 'edit_registration',
480 480
         'REG_ID'                    => $registration->ID(),
481 481
     );
482
-    $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
482
+    $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
483 483
     echo EEH_Template::display_template($template_path, $template_args, true);
484 484
     // indicate that we should not do the default admin page code
485 485
     return false;
@@ -597,7 +597,7 @@  discard block
 block discarded – undo
597 597
     public function _class_is_deprecated($method)
598 598
     {
599 599
         EE_Error::doing_it_wrong(
600
-            'EE_messages::' . $method,
600
+            'EE_messages::'.$method,
601 601
             esc_html__('EE_messages has been deprecated.  Please use EE_Message_Resource_Manager instead.'),
602 602
             '4.9.0',
603 603
             '4.10.0.p'
@@ -736,7 +736,7 @@  discard block
 block discarded – undo
736 736
         $error = false;
737 737
         // try to intelligently determine what method we'll call based on the incoming data.
738 738
         // if generating and sending are different then generate and send immediately.
739
-        if (! empty($sending_messenger) && $sending_messenger != $generating_messenger && $send) {
739
+        if ( ! empty($sending_messenger) && $sending_messenger != $generating_messenger && $send) {
740 740
             // in the legacy system, when generating and sending were different, that means all the
741 741
             // vars are already in the request object.  So let's just use that.
742 742
             try {
@@ -749,7 +749,7 @@  discard block
 block discarded – undo
749 749
                     'event_espresso'
750 750
                 );
751 751
                 // add specific message for developers if WP_DEBUG in on
752
-                $error_msg .= '||' . $e->getMessage();
752
+                $error_msg .= '||'.$e->getMessage();
753 753
                 EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
754 754
                 $error = true;
755 755
             }
@@ -823,7 +823,7 @@  discard block
 block discarded – undo
823 823
             }
824 824
         }
825 825
         // if no error then return the generated message(s).
826
-        if (! $error && ! $send) {
826
+        if ( ! $error && ! $send) {
827 827
             $generated_queue = $processor->generate_queue(false);
828 828
             // get message and return.
829 829
             $generated_queue->get_message_repository()->rewind();
@@ -882,7 +882,7 @@  discard block
 block discarded – undo
882 882
         /** @type EE_Messages_Queue $queue */
883 883
         $queue = EE_Registry::instance()->load_lib('Messages_Queue');
884 884
         // make sure we have a proper message object
885
-        if (! $message instanceof EE_Message && is_object($message) && isset($message->content)) {
885
+        if ( ! $message instanceof EE_Message && is_object($message) && isset($message->content)) {
886 886
             $msg = EE_Message_Factory::create(
887 887
                 array(
888 888
                     'MSG_messenger'    => $messenger,
@@ -894,11 +894,11 @@  discard block
 block discarded – undo
894 894
         } else {
895 895
             $msg = $message;
896 896
         }
897
-        if (! $msg instanceof EE_Message) {
897
+        if ( ! $msg instanceof EE_Message) {
898 898
             return false;
899 899
         }
900 900
         // make sure any content in a content property (if not empty) is set on the MSG_content.
901
-        if (! empty($msg->content)) {
901
+        if ( ! empty($msg->content)) {
902 902
             $msg->set('MSG_content', $msg->content);
903 903
         }
904 904
         $queue->add($msg);
@@ -1137,8 +1137,8 @@  discard block
 block discarded – undo
1137 1137
 
1138 1138
 add_filter(
1139 1139
     'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
1140
-    function ($event_list_iframe_css) {
1141
-        if (! has_filter('FHEE__EventsArchiveIframe__event_list_iframe__css')) {
1140
+    function($event_list_iframe_css) {
1141
+        if ( ! has_filter('FHEE__EventsArchiveIframe__event_list_iframe__css')) {
1142 1142
             return $event_list_iframe_css;
1143 1143
         }
1144 1144
         deprecated_espresso_action_or_filter_doing_it_wrong(
@@ -1157,8 +1157,8 @@  discard block
 block discarded – undo
1157 1157
 );
1158 1158
 add_filter(
1159 1159
     'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
1160
-    function ($event_list_iframe_js) {
1161
-        if (! has_filter('FHEE__EED_Ticket_Selector__ticket_selector_iframe__js')) {
1160
+    function($event_list_iframe_js) {
1161
+        if ( ! has_filter('FHEE__EED_Ticket_Selector__ticket_selector_iframe__js')) {
1162 1162
             return $event_list_iframe_js;
1163 1163
         }
1164 1164
         deprecated_espresso_action_or_filter_doing_it_wrong(
@@ -1177,8 +1177,8 @@  discard block
 block discarded – undo
1177 1177
 );
1178 1178
 add_action(
1179 1179
     'AHEE__EE_Capabilities__addCaps__complete',
1180
-    function ($capabilities_map) {
1181
-        if (! has_action('AHEE__EE_Capabilities__init_role_caps__complete')) {
1180
+    function($capabilities_map) {
1181
+        if ( ! has_action('AHEE__EE_Capabilities__init_role_caps__complete')) {
1182 1182
             return;
1183 1183
         }
1184 1184
         deprecated_espresso_action_or_filter_doing_it_wrong(
@@ -1198,7 +1198,7 @@  discard block
 block discarded – undo
1198 1198
 add_filter(
1199 1199
     'FHEE_EventEspresso_core_domain_services_commands_attendee_CreateAttendeeCommandHandler__findExistingAttendee__existing_attendee',
1200 1200
     function($existing_attendee, $registration, $attendee_data) {
1201
-        if ( ! has_filter( 'FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee' )) {
1201
+        if ( ! has_filter('FHEE_EE_Single_Page_Checkout__save_registration_items__find_existing_attendee')) {
1202 1202
             return $existing_attendee;
1203 1203
         }
1204 1204
         deprecated_espresso_action_or_filter_doing_it_wrong(
@@ -1281,7 +1281,7 @@  discard block
 block discarded – undo
1281 1281
      */
1282 1282
     public function event_list_title($event_list_title = '')
1283 1283
     {
1284
-        if (! empty($this->title)) {
1284
+        if ( ! empty($this->title)) {
1285 1285
             return $this->title;
1286 1286
         }
1287 1287
         return $event_list_title;
@@ -1441,7 +1441,7 @@  discard block
 block discarded – undo
1441 1441
             foreach ($model_fields as $field) {
1442 1442
                 if ($label === EEH_Export::get_column_name_for_field($field)) {
1443 1443
                     // re-add the old field name
1444
-                    $new_label = $label . '[' . $field->get_name() . ']';
1444
+                    $new_label = $label.'['.$field->get_name().']';
1445 1445
                     break;
1446 1446
                 }
1447 1447
             }
Please login to merge, or discard this patch.
payment_methods/Paypal_Standard/EEG_Paypal_Standard.gateway.php 1 patch
Indentation   +600 added lines, -600 removed lines patch added patch discarded remove patch
@@ -18,605 +18,605 @@
 block discarded – undo
18 18
  */
19 19
 class EEG_Paypal_Standard extends EE_Offsite_Gateway
20 20
 {
21
-    /**
22
-     * Name for the wp option used to save the itemized payment
23
-     */
24
-    const itemized_payment_option_name = '_itemized_payment';
25
-
26
-    protected $_paypal_id;
27
-
28
-    protected $_image_url;
29
-
30
-    protected $_shipping_details;
31
-
32
-    protected $_paypal_shipping;
33
-
34
-    protected $_paypal_taxes;
35
-
36
-    protected $_gateway_url;
37
-
38
-    protected $_currencies_supported = array(
39
-        'USD',
40
-        'GBP',
41
-        'CAD',
42
-        'AUD',
43
-        'BRL',
44
-        'CHF',
45
-        'CZK',
46
-        'DKK',
47
-        'EUR',
48
-        'HKD',
49
-        'HUF',
50
-        'ILS',
51
-        'JPY',
52
-        'MXN',
53
-        'MYR',
54
-        'NOK',
55
-        'NZD',
56
-        'PHP',
57
-        'PLN',
58
-        'SEK',
59
-        'SGD',
60
-        'THB',
61
-        'TRY',
62
-        'TWD',
63
-        'RUB'
64
-    );
65
-
66
-
67
-    /**
68
-     * EEG_Paypal_Standard constructor.
69
-     *
70
-     * @return EEG_Paypal_Standard
71
-     */
72
-    public function __construct()
73
-    {
74
-        $this->set_uses_separate_IPN_request(true);
75
-        parent::__construct();
76
-    }
77
-
78
-
79
-    /**
80
-     * Also sets the gateway url class variable based on whether debug mode is enabled or not.
81
-     *
82
-     * @param array $settings_array
83
-     */
84
-    public function set_settings($settings_array)
85
-    {
86
-        parent::set_settings($settings_array);
87
-        $this->_gateway_url = $this->_debug_mode
88
-            ? 'https://www.sandbox.paypal.com/cgi-bin/webscr'
89
-            : 'https://www.paypal.com/cgi-bin/webscr';
90
-    }
91
-
92
-
93
-    /**
94
-     * @param EEI_Payment $payment      the payment to process
95
-     * @param array       $billing_info but should be empty for this gateway
96
-     * @param string      $return_url   URL to send the user to after payment on the payment provider's website
97
-     * @param string      $notify_url   URL to send the instant payment notification
98
-     * @param string      $cancel_url   URL to send the user to after a cancelled payment attempt
99
-     *                                  on the payment provider's website
100
-     * @return EEI_Payment
101
-     * @throws \EE_Error
102
-     */
103
-    public function set_redirection_info(
104
-        $payment,
105
-        $billing_info = array(),
106
-        $return_url = null,
107
-        $notify_url = null,
108
-        $cancel_url = null
109
-    ) {
110
-        $redirect_args = array();
111
-        $transaction = $payment->transaction();
112
-        $gateway_formatter = $this->_get_gateway_formatter();
113
-        $item_num = 1;
114
-        /** @type EE_Line_Item $total_line_item */
115
-        $total_line_item = $transaction->total_line_item();
116
-
117
-        $total_discounts_to_cart_total = $transaction->paid();
118
-        // only itemize the order if we're paying for the rest of the order's amount
119
-        if (EEH_Money::compare_floats($payment->amount(), $transaction->total(), '==')) {
120
-            $payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, true);
121
-            // this payment is for the remaining transaction amount,
122
-            // keep track of exactly how much the itemized order amount equals
123
-            $itemized_sum = 0;
124
-            $shipping_previously_added = 0;
125
-            // so let's show all the line items
126
-            foreach ($total_line_item->get_items() as $line_item) {
127
-                if ($line_item instanceof EE_Line_Item) {
128
-                    // it's some kind of discount
129
-                    if ($line_item->total() < 0) {
130
-                        $total_discounts_to_cart_total += abs($line_item->total());
131
-                        $itemized_sum += $line_item->total();
132
-                        continue;
133
-                    }
134
-                    // dont include shipping again.
135
-                    if (strpos($line_item->code(), 'paypal_shipping_') === 0) {
136
-                        $shipping_previously_added = $line_item->total();
137
-                        continue;
138
-                    }
139
-                    $redirect_args[ 'item_name_' . $item_num ] = substr(
140
-                        $gateway_formatter->formatLineItemName($line_item, $payment),
141
-                        0,
142
-                        127
143
-                    );
144
-                    $redirect_args[ 'amount_' . $item_num ] = $line_item->unit_price();
145
-                    $redirect_args[ 'quantity_' . $item_num ] = $line_item->quantity();
146
-                    // if we're not letting PayPal calculate shipping, tell them its 0
147
-                    if (! $this->_paypal_shipping) {
148
-                        $redirect_args[ 'shipping_' . $item_num ] = '0';
149
-                        $redirect_args[ 'shipping2_' . $item_num ] = '0';
150
-                    }
151
-                    $item_num++;
152
-                    $itemized_sum += $line_item->total();
153
-                }
154
-            }
155
-            $taxes_li = $this->_line_item->get_taxes_subtotal($total_line_item);
156
-            // ideally itemized sum equals the transaction total. but if not (which is weird)
157
-            // and the itemized sum is LESS than the transaction total
158
-            // add another line item
159
-            // if the itemized sum is MORE than the transaction total,
160
-            // add the difference it to the discounts
161
-            $itemized_sum_diff_from_txn_total = round(
162
-                $transaction->total() - $itemized_sum - $taxes_li->total() - $shipping_previously_added,
163
-                2
164
-            );
165
-            if ($itemized_sum_diff_from_txn_total < 0) {
166
-                // itemized sum is too big
167
-                $total_discounts_to_cart_total += abs($itemized_sum_diff_from_txn_total);
168
-            } elseif ($itemized_sum_diff_from_txn_total > 0) {
169
-                $redirect_args[ 'item_name_' . $item_num ] = substr(
170
-                    esc_html__('Other charges', 'event_espresso'),
171
-                    0,
172
-                    127
173
-                );
174
-                $redirect_args[ 'amount_' . $item_num ] = $gateway_formatter->formatCurrency(
175
-                    $itemized_sum_diff_from_txn_total
176
-                );
177
-                $redirect_args[ 'quantity_' . $item_num ] = 1;
178
-                $item_num++;
179
-            }
180
-            if ($total_discounts_to_cart_total > 0) {
181
-                $redirect_args['discount_amount_cart'] = $gateway_formatter->formatCurrency(
182
-                    $total_discounts_to_cart_total
183
-                );
184
-            }
185
-            // add our taxes to the order if we're NOT using PayPal's
186
-            if (! $this->_paypal_taxes) {
187
-                $redirect_args['tax_cart'] = $total_line_item->get_total_tax();
188
-            }
189
-        } else {
190
-            $payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, false);
191
-            // partial payment that's not for the remaining amount, so we can't send an itemized list
192
-            $redirect_args[ 'item_name_' . $item_num ] = substr(
193
-                $gateway_formatter->formatPartialPaymentLineItemName($payment),
194
-                0,
195
-                127
196
-            );
197
-            $redirect_args[ 'amount_' . $item_num ] = $payment->amount();
198
-            $redirect_args[ 'shipping_' . $item_num ] = '0';
199
-            $redirect_args[ 'shipping2_' . $item_num ] = '0';
200
-            $redirect_args['tax_cart'] = '0';
201
-            $item_num++;
202
-        }
203
-
204
-        if ($this->_debug_mode) {
205
-            $redirect_args[ 'item_name_' . $item_num ] = 'DEBUG INFO (this item only added in sandbox mode';
206
-            $redirect_args[ 'amount_' . $item_num ] = 0;
207
-            $redirect_args[ 'on0_' . $item_num ] = 'NOTIFY URL';
208
-            $redirect_args[ 'os0_' . $item_num ] = $notify_url;
209
-            $redirect_args[ 'on1_' . $item_num ] = 'RETURN URL';
210
-            $redirect_args[ 'os1_' . $item_num ] = $return_url;
21
+	/**
22
+	 * Name for the wp option used to save the itemized payment
23
+	 */
24
+	const itemized_payment_option_name = '_itemized_payment';
25
+
26
+	protected $_paypal_id;
27
+
28
+	protected $_image_url;
29
+
30
+	protected $_shipping_details;
31
+
32
+	protected $_paypal_shipping;
33
+
34
+	protected $_paypal_taxes;
35
+
36
+	protected $_gateway_url;
37
+
38
+	protected $_currencies_supported = array(
39
+		'USD',
40
+		'GBP',
41
+		'CAD',
42
+		'AUD',
43
+		'BRL',
44
+		'CHF',
45
+		'CZK',
46
+		'DKK',
47
+		'EUR',
48
+		'HKD',
49
+		'HUF',
50
+		'ILS',
51
+		'JPY',
52
+		'MXN',
53
+		'MYR',
54
+		'NOK',
55
+		'NZD',
56
+		'PHP',
57
+		'PLN',
58
+		'SEK',
59
+		'SGD',
60
+		'THB',
61
+		'TRY',
62
+		'TWD',
63
+		'RUB'
64
+	);
65
+
66
+
67
+	/**
68
+	 * EEG_Paypal_Standard constructor.
69
+	 *
70
+	 * @return EEG_Paypal_Standard
71
+	 */
72
+	public function __construct()
73
+	{
74
+		$this->set_uses_separate_IPN_request(true);
75
+		parent::__construct();
76
+	}
77
+
78
+
79
+	/**
80
+	 * Also sets the gateway url class variable based on whether debug mode is enabled or not.
81
+	 *
82
+	 * @param array $settings_array
83
+	 */
84
+	public function set_settings($settings_array)
85
+	{
86
+		parent::set_settings($settings_array);
87
+		$this->_gateway_url = $this->_debug_mode
88
+			? 'https://www.sandbox.paypal.com/cgi-bin/webscr'
89
+			: 'https://www.paypal.com/cgi-bin/webscr';
90
+	}
91
+
92
+
93
+	/**
94
+	 * @param EEI_Payment $payment      the payment to process
95
+	 * @param array       $billing_info but should be empty for this gateway
96
+	 * @param string      $return_url   URL to send the user to after payment on the payment provider's website
97
+	 * @param string      $notify_url   URL to send the instant payment notification
98
+	 * @param string      $cancel_url   URL to send the user to after a cancelled payment attempt
99
+	 *                                  on the payment provider's website
100
+	 * @return EEI_Payment
101
+	 * @throws \EE_Error
102
+	 */
103
+	public function set_redirection_info(
104
+		$payment,
105
+		$billing_info = array(),
106
+		$return_url = null,
107
+		$notify_url = null,
108
+		$cancel_url = null
109
+	) {
110
+		$redirect_args = array();
111
+		$transaction = $payment->transaction();
112
+		$gateway_formatter = $this->_get_gateway_formatter();
113
+		$item_num = 1;
114
+		/** @type EE_Line_Item $total_line_item */
115
+		$total_line_item = $transaction->total_line_item();
116
+
117
+		$total_discounts_to_cart_total = $transaction->paid();
118
+		// only itemize the order if we're paying for the rest of the order's amount
119
+		if (EEH_Money::compare_floats($payment->amount(), $transaction->total(), '==')) {
120
+			$payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, true);
121
+			// this payment is for the remaining transaction amount,
122
+			// keep track of exactly how much the itemized order amount equals
123
+			$itemized_sum = 0;
124
+			$shipping_previously_added = 0;
125
+			// so let's show all the line items
126
+			foreach ($total_line_item->get_items() as $line_item) {
127
+				if ($line_item instanceof EE_Line_Item) {
128
+					// it's some kind of discount
129
+					if ($line_item->total() < 0) {
130
+						$total_discounts_to_cart_total += abs($line_item->total());
131
+						$itemized_sum += $line_item->total();
132
+						continue;
133
+					}
134
+					// dont include shipping again.
135
+					if (strpos($line_item->code(), 'paypal_shipping_') === 0) {
136
+						$shipping_previously_added = $line_item->total();
137
+						continue;
138
+					}
139
+					$redirect_args[ 'item_name_' . $item_num ] = substr(
140
+						$gateway_formatter->formatLineItemName($line_item, $payment),
141
+						0,
142
+						127
143
+					);
144
+					$redirect_args[ 'amount_' . $item_num ] = $line_item->unit_price();
145
+					$redirect_args[ 'quantity_' . $item_num ] = $line_item->quantity();
146
+					// if we're not letting PayPal calculate shipping, tell them its 0
147
+					if (! $this->_paypal_shipping) {
148
+						$redirect_args[ 'shipping_' . $item_num ] = '0';
149
+						$redirect_args[ 'shipping2_' . $item_num ] = '0';
150
+					}
151
+					$item_num++;
152
+					$itemized_sum += $line_item->total();
153
+				}
154
+			}
155
+			$taxes_li = $this->_line_item->get_taxes_subtotal($total_line_item);
156
+			// ideally itemized sum equals the transaction total. but if not (which is weird)
157
+			// and the itemized sum is LESS than the transaction total
158
+			// add another line item
159
+			// if the itemized sum is MORE than the transaction total,
160
+			// add the difference it to the discounts
161
+			$itemized_sum_diff_from_txn_total = round(
162
+				$transaction->total() - $itemized_sum - $taxes_li->total() - $shipping_previously_added,
163
+				2
164
+			);
165
+			if ($itemized_sum_diff_from_txn_total < 0) {
166
+				// itemized sum is too big
167
+				$total_discounts_to_cart_total += abs($itemized_sum_diff_from_txn_total);
168
+			} elseif ($itemized_sum_diff_from_txn_total > 0) {
169
+				$redirect_args[ 'item_name_' . $item_num ] = substr(
170
+					esc_html__('Other charges', 'event_espresso'),
171
+					0,
172
+					127
173
+				);
174
+				$redirect_args[ 'amount_' . $item_num ] = $gateway_formatter->formatCurrency(
175
+					$itemized_sum_diff_from_txn_total
176
+				);
177
+				$redirect_args[ 'quantity_' . $item_num ] = 1;
178
+				$item_num++;
179
+			}
180
+			if ($total_discounts_to_cart_total > 0) {
181
+				$redirect_args['discount_amount_cart'] = $gateway_formatter->formatCurrency(
182
+					$total_discounts_to_cart_total
183
+				);
184
+			}
185
+			// add our taxes to the order if we're NOT using PayPal's
186
+			if (! $this->_paypal_taxes) {
187
+				$redirect_args['tax_cart'] = $total_line_item->get_total_tax();
188
+			}
189
+		} else {
190
+			$payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, false);
191
+			// partial payment that's not for the remaining amount, so we can't send an itemized list
192
+			$redirect_args[ 'item_name_' . $item_num ] = substr(
193
+				$gateway_formatter->formatPartialPaymentLineItemName($payment),
194
+				0,
195
+				127
196
+			);
197
+			$redirect_args[ 'amount_' . $item_num ] = $payment->amount();
198
+			$redirect_args[ 'shipping_' . $item_num ] = '0';
199
+			$redirect_args[ 'shipping2_' . $item_num ] = '0';
200
+			$redirect_args['tax_cart'] = '0';
201
+			$item_num++;
202
+		}
203
+
204
+		if ($this->_debug_mode) {
205
+			$redirect_args[ 'item_name_' . $item_num ] = 'DEBUG INFO (this item only added in sandbox mode';
206
+			$redirect_args[ 'amount_' . $item_num ] = 0;
207
+			$redirect_args[ 'on0_' . $item_num ] = 'NOTIFY URL';
208
+			$redirect_args[ 'os0_' . $item_num ] = $notify_url;
209
+			$redirect_args[ 'on1_' . $item_num ] = 'RETURN URL';
210
+			$redirect_args[ 'os1_' . $item_num ] = $return_url;
211 211
 //          $redirect_args['option_index_' . $item_num] = 1; // <-- dunno if this is needed ?
212
-            $redirect_args[ 'shipping_' . $item_num ] = '0';
213
-            $redirect_args[ 'shipping2_' . $item_num ] = '0';
214
-        }
215
-
216
-        $redirect_args['business'] = $this->_paypal_id;
217
-        $redirect_args['return'] = $return_url;
218
-        $redirect_args['cancel_return'] = $cancel_url;
219
-        $redirect_args['notify_url'] = $notify_url;
220
-        $redirect_args['cmd'] = '_cart';
221
-        $redirect_args['upload'] = 1;
222
-        $redirect_args['currency_code'] = $payment->currency_code();
223
-        $redirect_args['rm'] = 2;// makes the user return with method=POST
224
-        if ($this->_image_url) {
225
-            $redirect_args['image_url'] = $this->_image_url;
226
-        }
227
-        $redirect_args['no_shipping'] = $this->_shipping_details;
228
-        $redirect_args['bn'] = 'EventEspresso_SP';// EE will blow up if you change this
229
-
230
-        $redirect_args = apply_filters("FHEE__EEG_Paypal_Standard__set_redirection_info__arguments", $redirect_args, $this);
231
-
232
-        $payment->set_redirect_url($this->_gateway_url);
233
-        $payment->set_redirect_args($redirect_args);
234
-        // log the results
235
-        $this->log(
236
-            array(
237
-                'message'     => sprintf(
238
-                    esc_html__('PayPal payment request initiated.', 'event_espresso')
239
-                ),
240
-                'transaction' => $transaction->model_field_array(),
241
-            ),
242
-            $payment
243
-        );
244
-        return $payment;
245
-    }
246
-
247
-
248
-    /**
249
-     * Often used for IPNs. But applies the info in $update_info to the payment.
250
-     * What is $update_info? Often the contents of $_REQUEST, but not necessarily. Whatever
251
-     * the payment method passes in.
252
-     *
253
-     * @param array $update_info like $_POST
254
-     * @param EEI_Transaction $transaction
255
-     * @return \EEI_Payment updated
256
-     * @throws \EE_Error, IpnException
257
-     */
258
-    public function handle_payment_update($update_info, $transaction)
259
-    {
260
-        // verify there's payment data that's been sent
261
-        if (empty($update_info['payment_status']) || empty($update_info['txn_id'])) {
262
-            // log the results
263
-            $this->log(
264
-                array(
265
-                    'message'     => sprintf(
266
-                        // @codingStandardsIgnoreStart
267
-                        esc_html__('PayPal IPN response is missing critical payment data. This may indicate a PDT request and require your PayPal account settings to be corrected.', 'event_espresso')
268
-                        // @codingStandardsIgnoreEnd
269
-                    ),
270
-                    'update_info' => $update_info,
271
-                ),
272
-                $transaction
273
-            );
274
-            // waaaait... is this a PDT request? (see https://developer.paypal.com/docs/classic/products/payment-data-transfer/)
275
-            // indicated by the "tx" argument? If so, we don't need it. We'll just use the IPN data when it comes
276
-            if (isset($update_info['tx'])) {
277
-                return $transaction->last_payment();
278
-            } else {
279
-                return null;
280
-            }
281
-        }
282
-        $payment = $this->_pay_model->get_payment_by_txn_id_chq_nmbr($update_info['txn_id']);
283
-        if (! $payment instanceof EEI_Payment) {
284
-            $payment = $transaction->last_payment();
285
-        }
286
-        // ok, then validate the IPN. Even if we've already processed this payment,
287
-        // let PayPal know we don't want to hear from them anymore!
288
-        if (! $this->validate_ipn($update_info, $payment)) {
289
-            return $payment;
290
-        }
291
-        // kill request here if this is a refund, we don't support them yet (we'd need to adjust the transaction,
292
-        // registrations, ticket counts, etc)
293
-        if (
294
-            (
295
-                $update_info['payment_status'] === 'Refunded'
296
-                || $update_info['payment_status'] === 'Partially_Refunded'
297
-            )
298
-            && apply_filters('FHEE__EEG_Paypal_Standard__handle_payment_update__kill_refund_request', true)
299
-        ) {
300
-            throw new EventEspresso\core\exceptions\IpnException(
301
-                sprintf(
302
-                    esc_html__('Event Espresso does not yet support %1$s IPNs from PayPal', 'event_espresso'),
303
-                    $update_info['payment_status']
304
-                ),
305
-                EventEspresso\core\exceptions\IpnException::UNSUPPORTED,
306
-                null,
307
-                $payment,
308
-                $update_info
309
-            );
310
-        }
311
-        // ok, well let's process this payment then!
312
-        switch ($update_info['payment_status']) {
313
-            case 'Completed':
314
-                $status = $this->_pay_model->approved_status();
315
-                $gateway_response = esc_html__('The payment is approved.', 'event_espresso');
316
-                break;
317
-
318
-            case 'Pending':
319
-                $status = $this->_pay_model->pending_status();
320
-                $gateway_response = esc_html__(
321
-                    'The payment is in progress. Another message will be sent when payment is approved.',
322
-                    'event_espresso'
323
-                );
324
-                break;
325
-
326
-            case 'Denied':
327
-                $status = $this->_pay_model->declined_status();
328
-                $gateway_response = esc_html__('The payment has been declined.', 'event_espresso');
329
-                break;
330
-
331
-            case 'Expired':
332
-            case 'Failed':
333
-                $status = $this->_pay_model->failed_status();
334
-                $gateway_response = esc_html__('The payment failed for technical reasons or expired.', 'event_espresso');
335
-                break;
336
-
337
-            case 'Refunded':
338
-            case 'Partially_Refunded':
339
-                // even though it's a refund, we consider the payment as approved, it just has a negative value
340
-                $status = $this->_pay_model->approved_status();
341
-                $gateway_response = esc_html__(
342
-                    'The payment has been refunded. Please update registrations accordingly.',
343
-                    'event_espresso'
344
-                );
345
-                break;
346
-
347
-            case 'Voided':
348
-            case 'Reversed':
349
-            case 'Canceled_Reversal':
350
-            default:
351
-                $status = $this->_pay_model->cancelled_status();
352
-                $gateway_response = esc_html__(
353
-                    'The payment was cancelled, reversed, or voided. Please update registrations accordingly.',
354
-                    'event_espresso'
355
-                );
356
-                break;
357
-        }
358
-
359
-        // check if we've already processed this payment
360
-        if ($payment instanceof EEI_Payment) {
361
-            // payment exists. if this has the exact same status and amount, don't bother updating. just return
362
-            if ($payment->status() === $status && (float) $payment->amount() === (float) $update_info['mc_gross']) {
363
-                // DUPLICATED IPN! don't bother updating transaction
364
-                throw new IpnException(
365
-                    sprintf(
366
-                        esc_html__(
367
-                            'It appears we have received a duplicate IPN from PayPal for payment %d',
368
-                            'event_espresso'
369
-                        ),
370
-                        $payment->ID()
371
-                    ),
372
-                    IpnException::DUPLICATE,
373
-                    null,
374
-                    $payment,
375
-                    $update_info
376
-                );
377
-            } else {
378
-                // new payment yippee !!!
379
-                $payment->set_status($status);
380
-                $payment->set_amount((float) $update_info['mc_gross']);
381
-                $payment->set_gateway_response($gateway_response);
382
-                $payment->set_details($update_info);
383
-                $payment->set_txn_id_chq_nmbr($update_info['txn_id']);
384
-                $this->log(
385
-                    array(
386
-                        'message'  => esc_html__(
387
-                            'Updated payment either from IPN or as part of POST from PayPal',
388
-                            'event_espresso'
389
-                        ),
390
-                        'url'      => $this->_process_response_url(),
391
-                        'payment'  => $payment->model_field_array(),
392
-                        'IPN_data' => $update_info
393
-                    ),
394
-                    $payment
395
-                );
396
-            }
397
-        }
398
-        do_action('FHEE__EEG_Paypal_Standard__handle_payment_update__payment_processed', $payment, $this);
399
-        return $payment;
400
-    }
401
-
402
-
403
-    /**
404
-     * Validate the IPN notification.
405
-     *
406
-     * @param array                  $update_info like $_REQUEST
407
-     * @param EE_Payment|EEI_Payment $payment
408
-     * @return boolean
409
-     * @throws \EE_Error
410
-     */
411
-    public function validate_ipn($update_info, $payment)
412
-    {
413
-        // allow us to skip validating IPNs with PayPal (useful for testing)
414
-        if (apply_filters('FHEE__EEG_Paypal_Standard__validate_ipn__skip', false)) {
415
-            return true;
416
-        }
417
-        // ...otherwise, we actually don't care what the $update_info is, we need to look
418
-        // at the request directly because we can't use $update_info because it has issues with quotes
419
-        // Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
420
-        // Instead, read raw POST data from the input stream.
421
-        // @see https://gist.github.com/xcommerce-gists/3440401
422
-        $raw_post_data = file_get_contents('php://input');
423
-        $raw_post_array = explode('&', $raw_post_data);
424
-        $update_info = array();
425
-        foreach ($raw_post_array as $keyval) {
426
-            $keyval = explode('=', $keyval);
427
-            if (count($keyval) === 2) {
428
-                $update_info[ $keyval[0] ] = urldecode($keyval[1]);
429
-            }
430
-        }
431
-        // read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
432
-        $req = 'cmd=_notify-validate';
433
-        foreach ($update_info as $key => $value) {
434
-            $value = urlencode($value);
435
-            $req .= "&$key=$value";
436
-        }
437
-        // HTTP POST the complete, unaltered IPN back to PayPal
438
-        $response = wp_remote_post(
439
-            $this->_gateway_url,
440
-            array(
441
-                'body'              => $req,
442
-                'sslverify'         => false,
443
-                'timeout'           => 60,
444
-                // make sure to set a site specific unique "user-agent" string since the WordPres default gets declined by PayPal
445
-                // plz see: https://github.com/websharks/s2member/issues/610
446
-                'user-agent'        => 'Event Espresso v' . EVENT_ESPRESSO_VERSION . '; ' . home_url(),
447
-                'httpversion'       => '1.1'
448
-            )
449
-        );
450
-        // then check the response
451
-        if (
452
-            array_key_exists('body', $response)
453
-            && ! is_wp_error($response)
454
-            && strcmp($response['body'], "VERIFIED") === 0
455
-        ) {
456
-            return true;
457
-        }
458
-        // huh, something's wack... the IPN didn't validate. We must have replied to the IPN incorrectly,
459
-        // or their API must have changed: http://www.paypalobjects.com/en_US/ebook/PP_OrderManagement_IntegrationGuide/ipn.html
460
-        if ($response instanceof WP_Error) {
461
-            $error_msg = sprintf(
462
-                esc_html__('WP Error. Code: "%1$s", Message: "%2$s", Data: "%3$s"', 'event_espresso'),
463
-                $response->get_error_code(),
464
-                $response->get_error_message(),
465
-                print_r($response->get_error_data(), true)
466
-            );
467
-        } elseif (is_array($response) && isset($response['body'])) {
468
-            $error_msg = $response['body'];
469
-        } else {
470
-            $error_msg = print_r($response, true);
471
-        }
472
-        $payment->set_gateway_response(
473
-            sprintf(
474
-                esc_html__("IPN Validation failed! Paypal responded with '%s'", "event_espresso"),
475
-                $error_msg
476
-            )
477
-        );
478
-        $payment->set_details(array('REQUEST' => $update_info, 'VALIDATION_RESPONSE' => $response));
479
-        $payment->set_status(EEM_Payment::status_id_failed);
480
-        // log the results
481
-        $this->log(
482
-            array(
483
-                'url'     => $this->_process_response_url(),
484
-                'message' => $payment->gateway_response(),
485
-                'details' => $payment->details(),
486
-            ),
487
-            $payment
488
-        );
489
-        return false;
490
-    }
491
-
492
-
493
-    /**
494
-     * _process_response_url
495
-     * @return string
496
-     */
497
-    protected function _process_response_url()
498
-    {
499
-        if (isset($_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'])) {
500
-            $url = is_ssl() ? 'https://' : 'http://';
501
-            $url .= EEH_URL::filter_input_server_url('HTTP_HOST');
502
-            $url .= EEH_URL::filter_input_server_url();
503
-        } else {
504
-            $url = 'unknown';
505
-        }
506
-        return $url;
507
-    }
508
-
509
-
510
-    /**
511
-     * Updates the transaction and line items based on the payment IPN data from PayPal,
512
-     * like the taxes or shipping
513
-     *
514
-     * @param EEI_Payment $payment
515
-     * @throws \EE_Error
516
-     */
517
-    public function update_txn_based_on_payment($payment)
518
-    {
519
-        $update_info = $payment->details();
520
-        /** @var EE_Transaction $transaction */
521
-        $transaction = $payment->transaction();
522
-        $payment_was_itemized = $payment->get_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, true, false);
523
-        if (! $transaction) {
524
-            $this->log(
525
-                esc_html__(
526
-                    // @codingStandardsIgnoreStart
527
-                    'Payment with ID %d has no related transaction, and so update_txn_based_on_payment couldn\'t be executed properly',
528
-                    // @codingStandardsIgnoreEnd
529
-                    'event_espresso'
530
-                ),
531
-                $payment
532
-            );
533
-            return;
534
-        }
535
-        if (
536
-            ! is_array($update_info)
537
-            || ! isset($update_info['mc_shipping'])
538
-            || ! isset($update_info['tax'])
539
-        ) {
540
-            $this->log(
541
-                array(
542
-                    'message' => esc_html__(
543
-                        // @codingStandardsIgnoreStart
544
-                        'Could not update transaction based on payment because the payment details have not yet been put on the payment. This normally happens during the IPN or returning from PayPal',
545
-                        // @codingStandardsIgnoreEnd
546
-                        'event_espresso'
547
-                    ),
548
-                    'url'     => $this->_process_response_url(),
549
-                    'payment' => $payment->model_field_array()
550
-                ),
551
-                $payment
552
-            );
553
-            return;
554
-        }
555
-        if ($payment->status() !== $this->_pay_model->approved_status()) {
556
-            $this->log(
557
-                array(
558
-                    'message' => esc_html__(
559
-                        'We shouldn\'t update transactions taxes or shipping data from non-approved payments',
560
-                        'event_espresso'
561
-                    ),
562
-                    'url'     => $this->_process_response_url(),
563
-                    'payment' => $payment->model_field_array()
564
-                ),
565
-                $payment
566
-            );
567
-            return;
568
-        }
569
-        $grand_total_needs_resaving = false;
570
-        /** @var EE_Line_Item $transaction_total_line_item */
571
-        $transaction_total_line_item = $transaction->total_line_item();
572
-
573
-        // might paypal have changed the taxes?
574
-        if ($this->_paypal_taxes && $payment_was_itemized) {
575
-            // note that we're doing this BEFORE adding shipping;
576
-            // we actually want PayPal's shipping to remain non-taxable
577
-            $this->_line_item->set_line_items_taxable($transaction_total_line_item, true, 'paypal_shipping');
578
-            $this->_line_item->set_total_tax_to(
579
-                $transaction_total_line_item,
580
-                (float) $update_info['tax'],
581
-                esc_html__('Taxes', 'event_espresso'),
582
-                esc_html__('Calculated by Paypal', 'event_espresso'),
583
-                'paypal_tax'
584
-            );
585
-            $grand_total_needs_resaving = true;
586
-        }
587
-
588
-        $shipping_amount = (float) $update_info['mc_shipping'];
589
-        // might paypal have added shipping?
590
-        if ($this->_paypal_shipping && $shipping_amount && $payment_was_itemized) {
591
-            $this->_line_item->add_unrelated_item(
592
-                $transaction_total_line_item,
593
-                sprintf(esc_html__('Shipping for transaction %1$s', 'event_espresso'), $transaction->ID()),
594
-                $shipping_amount,
595
-                esc_html__('Shipping charges calculated by Paypal', 'event_espresso'),
596
-                1,
597
-                false,
598
-                'paypal_shipping_' . $transaction->ID()
599
-            );
600
-            $grand_total_needs_resaving = true;
601
-        }
602
-
603
-        if ($grand_total_needs_resaving) {
604
-            $transaction_total_line_item->save_this_and_descendants_to_txn($transaction->ID());
605
-            /** @var EE_Registration_Processor $registration_processor */
606
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
607
-            $registration_processor->update_registration_final_prices($transaction);
608
-        }
609
-        $this->log(
610
-            array(
611
-                'message'                     => esc_html__('Updated transaction related to payment', 'event_espresso'),
612
-                'url'                         => $this->_process_response_url(),
613
-                'transaction (updated)'       => $transaction->model_field_array(),
614
-                'payment (updated)'           => $payment->model_field_array(),
615
-                'use_paypal_shipping'         => $this->_paypal_shipping,
616
-                'use_paypal_tax'              => $this->_paypal_taxes,
617
-                'grand_total_needed_resaving' => $grand_total_needs_resaving,
618
-            ),
619
-            $payment
620
-        );
621
-    }
212
+			$redirect_args[ 'shipping_' . $item_num ] = '0';
213
+			$redirect_args[ 'shipping2_' . $item_num ] = '0';
214
+		}
215
+
216
+		$redirect_args['business'] = $this->_paypal_id;
217
+		$redirect_args['return'] = $return_url;
218
+		$redirect_args['cancel_return'] = $cancel_url;
219
+		$redirect_args['notify_url'] = $notify_url;
220
+		$redirect_args['cmd'] = '_cart';
221
+		$redirect_args['upload'] = 1;
222
+		$redirect_args['currency_code'] = $payment->currency_code();
223
+		$redirect_args['rm'] = 2;// makes the user return with method=POST
224
+		if ($this->_image_url) {
225
+			$redirect_args['image_url'] = $this->_image_url;
226
+		}
227
+		$redirect_args['no_shipping'] = $this->_shipping_details;
228
+		$redirect_args['bn'] = 'EventEspresso_SP';// EE will blow up if you change this
229
+
230
+		$redirect_args = apply_filters("FHEE__EEG_Paypal_Standard__set_redirection_info__arguments", $redirect_args, $this);
231
+
232
+		$payment->set_redirect_url($this->_gateway_url);
233
+		$payment->set_redirect_args($redirect_args);
234
+		// log the results
235
+		$this->log(
236
+			array(
237
+				'message'     => sprintf(
238
+					esc_html__('PayPal payment request initiated.', 'event_espresso')
239
+				),
240
+				'transaction' => $transaction->model_field_array(),
241
+			),
242
+			$payment
243
+		);
244
+		return $payment;
245
+	}
246
+
247
+
248
+	/**
249
+	 * Often used for IPNs. But applies the info in $update_info to the payment.
250
+	 * What is $update_info? Often the contents of $_REQUEST, but not necessarily. Whatever
251
+	 * the payment method passes in.
252
+	 *
253
+	 * @param array $update_info like $_POST
254
+	 * @param EEI_Transaction $transaction
255
+	 * @return \EEI_Payment updated
256
+	 * @throws \EE_Error, IpnException
257
+	 */
258
+	public function handle_payment_update($update_info, $transaction)
259
+	{
260
+		// verify there's payment data that's been sent
261
+		if (empty($update_info['payment_status']) || empty($update_info['txn_id'])) {
262
+			// log the results
263
+			$this->log(
264
+				array(
265
+					'message'     => sprintf(
266
+						// @codingStandardsIgnoreStart
267
+						esc_html__('PayPal IPN response is missing critical payment data. This may indicate a PDT request and require your PayPal account settings to be corrected.', 'event_espresso')
268
+						// @codingStandardsIgnoreEnd
269
+					),
270
+					'update_info' => $update_info,
271
+				),
272
+				$transaction
273
+			);
274
+			// waaaait... is this a PDT request? (see https://developer.paypal.com/docs/classic/products/payment-data-transfer/)
275
+			// indicated by the "tx" argument? If so, we don't need it. We'll just use the IPN data when it comes
276
+			if (isset($update_info['tx'])) {
277
+				return $transaction->last_payment();
278
+			} else {
279
+				return null;
280
+			}
281
+		}
282
+		$payment = $this->_pay_model->get_payment_by_txn_id_chq_nmbr($update_info['txn_id']);
283
+		if (! $payment instanceof EEI_Payment) {
284
+			$payment = $transaction->last_payment();
285
+		}
286
+		// ok, then validate the IPN. Even if we've already processed this payment,
287
+		// let PayPal know we don't want to hear from them anymore!
288
+		if (! $this->validate_ipn($update_info, $payment)) {
289
+			return $payment;
290
+		}
291
+		// kill request here if this is a refund, we don't support them yet (we'd need to adjust the transaction,
292
+		// registrations, ticket counts, etc)
293
+		if (
294
+			(
295
+				$update_info['payment_status'] === 'Refunded'
296
+				|| $update_info['payment_status'] === 'Partially_Refunded'
297
+			)
298
+			&& apply_filters('FHEE__EEG_Paypal_Standard__handle_payment_update__kill_refund_request', true)
299
+		) {
300
+			throw new EventEspresso\core\exceptions\IpnException(
301
+				sprintf(
302
+					esc_html__('Event Espresso does not yet support %1$s IPNs from PayPal', 'event_espresso'),
303
+					$update_info['payment_status']
304
+				),
305
+				EventEspresso\core\exceptions\IpnException::UNSUPPORTED,
306
+				null,
307
+				$payment,
308
+				$update_info
309
+			);
310
+		}
311
+		// ok, well let's process this payment then!
312
+		switch ($update_info['payment_status']) {
313
+			case 'Completed':
314
+				$status = $this->_pay_model->approved_status();
315
+				$gateway_response = esc_html__('The payment is approved.', 'event_espresso');
316
+				break;
317
+
318
+			case 'Pending':
319
+				$status = $this->_pay_model->pending_status();
320
+				$gateway_response = esc_html__(
321
+					'The payment is in progress. Another message will be sent when payment is approved.',
322
+					'event_espresso'
323
+				);
324
+				break;
325
+
326
+			case 'Denied':
327
+				$status = $this->_pay_model->declined_status();
328
+				$gateway_response = esc_html__('The payment has been declined.', 'event_espresso');
329
+				break;
330
+
331
+			case 'Expired':
332
+			case 'Failed':
333
+				$status = $this->_pay_model->failed_status();
334
+				$gateway_response = esc_html__('The payment failed for technical reasons or expired.', 'event_espresso');
335
+				break;
336
+
337
+			case 'Refunded':
338
+			case 'Partially_Refunded':
339
+				// even though it's a refund, we consider the payment as approved, it just has a negative value
340
+				$status = $this->_pay_model->approved_status();
341
+				$gateway_response = esc_html__(
342
+					'The payment has been refunded. Please update registrations accordingly.',
343
+					'event_espresso'
344
+				);
345
+				break;
346
+
347
+			case 'Voided':
348
+			case 'Reversed':
349
+			case 'Canceled_Reversal':
350
+			default:
351
+				$status = $this->_pay_model->cancelled_status();
352
+				$gateway_response = esc_html__(
353
+					'The payment was cancelled, reversed, or voided. Please update registrations accordingly.',
354
+					'event_espresso'
355
+				);
356
+				break;
357
+		}
358
+
359
+		// check if we've already processed this payment
360
+		if ($payment instanceof EEI_Payment) {
361
+			// payment exists. if this has the exact same status and amount, don't bother updating. just return
362
+			if ($payment->status() === $status && (float) $payment->amount() === (float) $update_info['mc_gross']) {
363
+				// DUPLICATED IPN! don't bother updating transaction
364
+				throw new IpnException(
365
+					sprintf(
366
+						esc_html__(
367
+							'It appears we have received a duplicate IPN from PayPal for payment %d',
368
+							'event_espresso'
369
+						),
370
+						$payment->ID()
371
+					),
372
+					IpnException::DUPLICATE,
373
+					null,
374
+					$payment,
375
+					$update_info
376
+				);
377
+			} else {
378
+				// new payment yippee !!!
379
+				$payment->set_status($status);
380
+				$payment->set_amount((float) $update_info['mc_gross']);
381
+				$payment->set_gateway_response($gateway_response);
382
+				$payment->set_details($update_info);
383
+				$payment->set_txn_id_chq_nmbr($update_info['txn_id']);
384
+				$this->log(
385
+					array(
386
+						'message'  => esc_html__(
387
+							'Updated payment either from IPN or as part of POST from PayPal',
388
+							'event_espresso'
389
+						),
390
+						'url'      => $this->_process_response_url(),
391
+						'payment'  => $payment->model_field_array(),
392
+						'IPN_data' => $update_info
393
+					),
394
+					$payment
395
+				);
396
+			}
397
+		}
398
+		do_action('FHEE__EEG_Paypal_Standard__handle_payment_update__payment_processed', $payment, $this);
399
+		return $payment;
400
+	}
401
+
402
+
403
+	/**
404
+	 * Validate the IPN notification.
405
+	 *
406
+	 * @param array                  $update_info like $_REQUEST
407
+	 * @param EE_Payment|EEI_Payment $payment
408
+	 * @return boolean
409
+	 * @throws \EE_Error
410
+	 */
411
+	public function validate_ipn($update_info, $payment)
412
+	{
413
+		// allow us to skip validating IPNs with PayPal (useful for testing)
414
+		if (apply_filters('FHEE__EEG_Paypal_Standard__validate_ipn__skip', false)) {
415
+			return true;
416
+		}
417
+		// ...otherwise, we actually don't care what the $update_info is, we need to look
418
+		// at the request directly because we can't use $update_info because it has issues with quotes
419
+		// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
420
+		// Instead, read raw POST data from the input stream.
421
+		// @see https://gist.github.com/xcommerce-gists/3440401
422
+		$raw_post_data = file_get_contents('php://input');
423
+		$raw_post_array = explode('&', $raw_post_data);
424
+		$update_info = array();
425
+		foreach ($raw_post_array as $keyval) {
426
+			$keyval = explode('=', $keyval);
427
+			if (count($keyval) === 2) {
428
+				$update_info[ $keyval[0] ] = urldecode($keyval[1]);
429
+			}
430
+		}
431
+		// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
432
+		$req = 'cmd=_notify-validate';
433
+		foreach ($update_info as $key => $value) {
434
+			$value = urlencode($value);
435
+			$req .= "&$key=$value";
436
+		}
437
+		// HTTP POST the complete, unaltered IPN back to PayPal
438
+		$response = wp_remote_post(
439
+			$this->_gateway_url,
440
+			array(
441
+				'body'              => $req,
442
+				'sslverify'         => false,
443
+				'timeout'           => 60,
444
+				// make sure to set a site specific unique "user-agent" string since the WordPres default gets declined by PayPal
445
+				// plz see: https://github.com/websharks/s2member/issues/610
446
+				'user-agent'        => 'Event Espresso v' . EVENT_ESPRESSO_VERSION . '; ' . home_url(),
447
+				'httpversion'       => '1.1'
448
+			)
449
+		);
450
+		// then check the response
451
+		if (
452
+			array_key_exists('body', $response)
453
+			&& ! is_wp_error($response)
454
+			&& strcmp($response['body'], "VERIFIED") === 0
455
+		) {
456
+			return true;
457
+		}
458
+		// huh, something's wack... the IPN didn't validate. We must have replied to the IPN incorrectly,
459
+		// or their API must have changed: http://www.paypalobjects.com/en_US/ebook/PP_OrderManagement_IntegrationGuide/ipn.html
460
+		if ($response instanceof WP_Error) {
461
+			$error_msg = sprintf(
462
+				esc_html__('WP Error. Code: "%1$s", Message: "%2$s", Data: "%3$s"', 'event_espresso'),
463
+				$response->get_error_code(),
464
+				$response->get_error_message(),
465
+				print_r($response->get_error_data(), true)
466
+			);
467
+		} elseif (is_array($response) && isset($response['body'])) {
468
+			$error_msg = $response['body'];
469
+		} else {
470
+			$error_msg = print_r($response, true);
471
+		}
472
+		$payment->set_gateway_response(
473
+			sprintf(
474
+				esc_html__("IPN Validation failed! Paypal responded with '%s'", "event_espresso"),
475
+				$error_msg
476
+			)
477
+		);
478
+		$payment->set_details(array('REQUEST' => $update_info, 'VALIDATION_RESPONSE' => $response));
479
+		$payment->set_status(EEM_Payment::status_id_failed);
480
+		// log the results
481
+		$this->log(
482
+			array(
483
+				'url'     => $this->_process_response_url(),
484
+				'message' => $payment->gateway_response(),
485
+				'details' => $payment->details(),
486
+			),
487
+			$payment
488
+		);
489
+		return false;
490
+	}
491
+
492
+
493
+	/**
494
+	 * _process_response_url
495
+	 * @return string
496
+	 */
497
+	protected function _process_response_url()
498
+	{
499
+		if (isset($_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'])) {
500
+			$url = is_ssl() ? 'https://' : 'http://';
501
+			$url .= EEH_URL::filter_input_server_url('HTTP_HOST');
502
+			$url .= EEH_URL::filter_input_server_url();
503
+		} else {
504
+			$url = 'unknown';
505
+		}
506
+		return $url;
507
+	}
508
+
509
+
510
+	/**
511
+	 * Updates the transaction and line items based on the payment IPN data from PayPal,
512
+	 * like the taxes or shipping
513
+	 *
514
+	 * @param EEI_Payment $payment
515
+	 * @throws \EE_Error
516
+	 */
517
+	public function update_txn_based_on_payment($payment)
518
+	{
519
+		$update_info = $payment->details();
520
+		/** @var EE_Transaction $transaction */
521
+		$transaction = $payment->transaction();
522
+		$payment_was_itemized = $payment->get_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, true, false);
523
+		if (! $transaction) {
524
+			$this->log(
525
+				esc_html__(
526
+					// @codingStandardsIgnoreStart
527
+					'Payment with ID %d has no related transaction, and so update_txn_based_on_payment couldn\'t be executed properly',
528
+					// @codingStandardsIgnoreEnd
529
+					'event_espresso'
530
+				),
531
+				$payment
532
+			);
533
+			return;
534
+		}
535
+		if (
536
+			! is_array($update_info)
537
+			|| ! isset($update_info['mc_shipping'])
538
+			|| ! isset($update_info['tax'])
539
+		) {
540
+			$this->log(
541
+				array(
542
+					'message' => esc_html__(
543
+						// @codingStandardsIgnoreStart
544
+						'Could not update transaction based on payment because the payment details have not yet been put on the payment. This normally happens during the IPN or returning from PayPal',
545
+						// @codingStandardsIgnoreEnd
546
+						'event_espresso'
547
+					),
548
+					'url'     => $this->_process_response_url(),
549
+					'payment' => $payment->model_field_array()
550
+				),
551
+				$payment
552
+			);
553
+			return;
554
+		}
555
+		if ($payment->status() !== $this->_pay_model->approved_status()) {
556
+			$this->log(
557
+				array(
558
+					'message' => esc_html__(
559
+						'We shouldn\'t update transactions taxes or shipping data from non-approved payments',
560
+						'event_espresso'
561
+					),
562
+					'url'     => $this->_process_response_url(),
563
+					'payment' => $payment->model_field_array()
564
+				),
565
+				$payment
566
+			);
567
+			return;
568
+		}
569
+		$grand_total_needs_resaving = false;
570
+		/** @var EE_Line_Item $transaction_total_line_item */
571
+		$transaction_total_line_item = $transaction->total_line_item();
572
+
573
+		// might paypal have changed the taxes?
574
+		if ($this->_paypal_taxes && $payment_was_itemized) {
575
+			// note that we're doing this BEFORE adding shipping;
576
+			// we actually want PayPal's shipping to remain non-taxable
577
+			$this->_line_item->set_line_items_taxable($transaction_total_line_item, true, 'paypal_shipping');
578
+			$this->_line_item->set_total_tax_to(
579
+				$transaction_total_line_item,
580
+				(float) $update_info['tax'],
581
+				esc_html__('Taxes', 'event_espresso'),
582
+				esc_html__('Calculated by Paypal', 'event_espresso'),
583
+				'paypal_tax'
584
+			);
585
+			$grand_total_needs_resaving = true;
586
+		}
587
+
588
+		$shipping_amount = (float) $update_info['mc_shipping'];
589
+		// might paypal have added shipping?
590
+		if ($this->_paypal_shipping && $shipping_amount && $payment_was_itemized) {
591
+			$this->_line_item->add_unrelated_item(
592
+				$transaction_total_line_item,
593
+				sprintf(esc_html__('Shipping for transaction %1$s', 'event_espresso'), $transaction->ID()),
594
+				$shipping_amount,
595
+				esc_html__('Shipping charges calculated by Paypal', 'event_espresso'),
596
+				1,
597
+				false,
598
+				'paypal_shipping_' . $transaction->ID()
599
+			);
600
+			$grand_total_needs_resaving = true;
601
+		}
602
+
603
+		if ($grand_total_needs_resaving) {
604
+			$transaction_total_line_item->save_this_and_descendants_to_txn($transaction->ID());
605
+			/** @var EE_Registration_Processor $registration_processor */
606
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
607
+			$registration_processor->update_registration_final_prices($transaction);
608
+		}
609
+		$this->log(
610
+			array(
611
+				'message'                     => esc_html__('Updated transaction related to payment', 'event_espresso'),
612
+				'url'                         => $this->_process_response_url(),
613
+				'transaction (updated)'       => $transaction->model_field_array(),
614
+				'payment (updated)'           => $payment->model_field_array(),
615
+				'use_paypal_shipping'         => $this->_paypal_shipping,
616
+				'use_paypal_tax'              => $this->_paypal_taxes,
617
+				'grand_total_needed_resaving' => $grand_total_needs_resaving,
618
+			),
619
+			$payment
620
+		);
621
+	}
622 622
 }
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 2 patches
Indentation   +1293 added lines, -1293 removed lines patch added patch discarded remove patch
@@ -12,242 +12,242 @@  discard block
 block discarded – undo
12 12
  */
13 13
 class Extend_Events_Admin_Page extends Events_Admin_Page
14 14
 {
15
-    /**
16
-     * Extend_Events_Admin_Page constructor.
17
-     *
18
-     * @param bool $routing
19
-     * @throws EE_Error
20
-     * @throws ReflectionException
21
-     */
22
-    public function __construct($routing = true)
23
-    {
24
-        parent::__construct($routing);
25
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
-        }
30
-    }
31
-
32
-
33
-    /**
34
-     * Sets routes.
35
-     *
36
-     * @throws EE_Error
37
-     */
38
-    protected function _extend_page_config()
39
-    {
40
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
-        // is there a evt_id in the request?
42
-        $EVT_ID             = $this->request->getRequestParam('EVT_ID', 0, 'int');
43
-        $EVT_ID             = $this->request->getRequestParam('post', $EVT_ID, 'int');
44
-        $TKT_ID             = $this->request->getRequestParam('TKT_ID', 0, 'int');
45
-        $new_page_routes    = [
46
-            'duplicate_event'          => [
47
-                'func'       => '_duplicate_event',
48
-                'capability' => 'ee_edit_event',
49
-                'obj_id'     => $EVT_ID,
50
-                'noheader'   => true,
51
-            ],
52
-            'ticket_list_table'        => [
53
-                'func'       => '_tickets_overview_list_table',
54
-                'capability' => 'ee_read_default_tickets',
55
-            ],
56
-            'trash_ticket'             => [
57
-                'func'       => '_trash_or_restore_ticket',
58
-                'capability' => 'ee_delete_default_ticket',
59
-                'obj_id'     => $TKT_ID,
60
-                'noheader'   => true,
61
-                'args'       => ['trash' => true],
62
-            ],
63
-            'trash_tickets'            => [
64
-                'func'       => '_trash_or_restore_ticket',
65
-                'capability' => 'ee_delete_default_tickets',
66
-                'noheader'   => true,
67
-                'args'       => ['trash' => true],
68
-            ],
69
-            'restore_ticket'           => [
70
-                'func'       => '_trash_or_restore_ticket',
71
-                'capability' => 'ee_delete_default_ticket',
72
-                'obj_id'     => $TKT_ID,
73
-                'noheader'   => true,
74
-            ],
75
-            'restore_tickets'          => [
76
-                'func'       => '_trash_or_restore_ticket',
77
-                'capability' => 'ee_delete_default_tickets',
78
-                'noheader'   => true,
79
-            ],
80
-            'delete_ticket'            => [
81
-                'func'       => '_delete_ticket',
82
-                'capability' => 'ee_delete_default_ticket',
83
-                'obj_id'     => $TKT_ID,
84
-                'noheader'   => true,
85
-            ],
86
-            'delete_tickets'           => [
87
-                'func'       => '_delete_ticket',
88
-                'capability' => 'ee_delete_default_tickets',
89
-                'noheader'   => true,
90
-            ],
91
-            'import_page'              => [
92
-                'func'       => '_import_page',
93
-                'capability' => 'import',
94
-            ],
95
-            'import'                   => [
96
-                'func'       => '_import_events',
97
-                'capability' => 'import',
98
-                'noheader'   => true,
99
-            ],
100
-            'import_events'            => [
101
-                'func'       => '_import_events',
102
-                'capability' => 'import',
103
-                'noheader'   => true,
104
-            ],
105
-            'export_events'            => [
106
-                'func'       => '_events_export',
107
-                'capability' => 'export',
108
-                'noheader'   => true,
109
-            ],
110
-            'export_categories'        => [
111
-                'func'       => '_categories_export',
112
-                'capability' => 'export',
113
-                'noheader'   => true,
114
-            ],
115
-            'sample_export_file'       => [
116
-                'func'       => '_sample_export_file',
117
-                'capability' => 'export',
118
-                'noheader'   => true,
119
-            ],
120
-            'update_template_settings' => [
121
-                'func'       => '_update_template_settings',
122
-                'capability' => 'manage_options',
123
-                'noheader'   => true,
124
-            ],
125
-        ];
126
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
127
-        // partial route/config override
128
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
129
-        $this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
130
-        $this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
131
-        $this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
132
-        $this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
133
-        $this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
134
-        // add tickets tab but only if there are more than one default ticket!
135
-        $ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
136
-            [['TKT_is_default' => 1]],
137
-            'TKT_ID',
138
-            true
139
-        );
140
-        if ($ticket_count > 1) {
141
-            $new_page_config = [
142
-                'ticket_list_table' => [
143
-                    'nav'           => [
144
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
145
-                        'order' => 60,
146
-                    ],
147
-                    'list_table'    => 'Tickets_List_Table',
148
-                    'require_nonce' => false,
149
-                ],
150
-            ];
151
-        }
152
-        // template settings
153
-        $new_page_config['template_settings'] = [
154
-            'nav'           => [
155
-                'label' => esc_html__('Templates', 'event_espresso'),
156
-                'order' => 30,
157
-            ],
158
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
159
-            'help_tabs'     => [
160
-                'general_settings_templates_help_tab' => [
161
-                    'title'    => esc_html__('Templates', 'event_espresso'),
162
-                    'filename' => 'general_settings_templates',
163
-                ],
164
-            ],
165
-            'require_nonce' => false,
166
-        ];
167
-        $this->_page_config                   = array_merge($this->_page_config, $new_page_config);
168
-        // add filters and actions
169
-        // modifying _views
170
-        add_filter(
171
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
172
-            [$this, 'add_additional_datetime_button'],
173
-            10,
174
-            2
175
-        );
176
-        add_filter(
177
-            'FHEE_event_datetime_metabox_clone_button_template',
178
-            [$this, 'add_datetime_clone_button'],
179
-            10,
180
-            2
181
-        );
182
-        add_filter(
183
-            'FHEE_event_datetime_metabox_timezones_template',
184
-            [$this, 'datetime_timezones_template'],
185
-            10,
186
-            2
187
-        );
188
-        // filters for event list table
189
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', [$this, 'list_table_filters'], 10, 2);
190
-        add_filter(
191
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
192
-            [$this, 'extra_list_table_actions'],
193
-            10,
194
-            2
195
-        );
196
-        // legend item
197
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
198
-        add_action('admin_init', [$this, 'admin_init']);
199
-    }
200
-
201
-
202
-    /**
203
-     * admin_init
204
-     */
205
-    public function admin_init()
206
-    {
207
-        EE_Registry::$i18n_js_strings = array_merge(
208
-            EE_Registry::$i18n_js_strings,
209
-            [
210
-                'image_confirm'          => esc_html__(
211
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
212
-                    'event_espresso'
213
-                ),
214
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
215
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
216
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
217
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
218
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
219
-            ]
220
-        );
221
-    }
222
-
223
-
224
-    /**
225
-     * Add per page screen options to the default ticket list table view.
226
-     */
227
-    protected function _add_screen_options_ticket_list_table()
228
-    {
229
-        $this->_per_page_screen_option();
230
-    }
231
-
232
-
233
-    /**
234
-     * @param string $return
235
-     * @param int    $id
236
-     * @param string $new_title
237
-     * @param string $new_slug
238
-     * @return string
239
-     */
240
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
241
-    {
242
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
243
-        // make sure this is only when editing
244
-        if (! empty($id)) {
245
-            $href   = EE_Admin_Page::add_query_args_and_nonce(
246
-                ['action' => 'duplicate_event', 'EVT_ID' => $id],
247
-                $this->_admin_base_url
248
-            );
249
-            $title  = esc_attr__('Duplicate Event', 'event_espresso');
250
-            $return .= '
15
+	/**
16
+	 * Extend_Events_Admin_Page constructor.
17
+	 *
18
+	 * @param bool $routing
19
+	 * @throws EE_Error
20
+	 * @throws ReflectionException
21
+	 */
22
+	public function __construct($routing = true)
23
+	{
24
+		parent::__construct($routing);
25
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
+		}
30
+	}
31
+
32
+
33
+	/**
34
+	 * Sets routes.
35
+	 *
36
+	 * @throws EE_Error
37
+	 */
38
+	protected function _extend_page_config()
39
+	{
40
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
+		// is there a evt_id in the request?
42
+		$EVT_ID             = $this->request->getRequestParam('EVT_ID', 0, 'int');
43
+		$EVT_ID             = $this->request->getRequestParam('post', $EVT_ID, 'int');
44
+		$TKT_ID             = $this->request->getRequestParam('TKT_ID', 0, 'int');
45
+		$new_page_routes    = [
46
+			'duplicate_event'          => [
47
+				'func'       => '_duplicate_event',
48
+				'capability' => 'ee_edit_event',
49
+				'obj_id'     => $EVT_ID,
50
+				'noheader'   => true,
51
+			],
52
+			'ticket_list_table'        => [
53
+				'func'       => '_tickets_overview_list_table',
54
+				'capability' => 'ee_read_default_tickets',
55
+			],
56
+			'trash_ticket'             => [
57
+				'func'       => '_trash_or_restore_ticket',
58
+				'capability' => 'ee_delete_default_ticket',
59
+				'obj_id'     => $TKT_ID,
60
+				'noheader'   => true,
61
+				'args'       => ['trash' => true],
62
+			],
63
+			'trash_tickets'            => [
64
+				'func'       => '_trash_or_restore_ticket',
65
+				'capability' => 'ee_delete_default_tickets',
66
+				'noheader'   => true,
67
+				'args'       => ['trash' => true],
68
+			],
69
+			'restore_ticket'           => [
70
+				'func'       => '_trash_or_restore_ticket',
71
+				'capability' => 'ee_delete_default_ticket',
72
+				'obj_id'     => $TKT_ID,
73
+				'noheader'   => true,
74
+			],
75
+			'restore_tickets'          => [
76
+				'func'       => '_trash_or_restore_ticket',
77
+				'capability' => 'ee_delete_default_tickets',
78
+				'noheader'   => true,
79
+			],
80
+			'delete_ticket'            => [
81
+				'func'       => '_delete_ticket',
82
+				'capability' => 'ee_delete_default_ticket',
83
+				'obj_id'     => $TKT_ID,
84
+				'noheader'   => true,
85
+			],
86
+			'delete_tickets'           => [
87
+				'func'       => '_delete_ticket',
88
+				'capability' => 'ee_delete_default_tickets',
89
+				'noheader'   => true,
90
+			],
91
+			'import_page'              => [
92
+				'func'       => '_import_page',
93
+				'capability' => 'import',
94
+			],
95
+			'import'                   => [
96
+				'func'       => '_import_events',
97
+				'capability' => 'import',
98
+				'noheader'   => true,
99
+			],
100
+			'import_events'            => [
101
+				'func'       => '_import_events',
102
+				'capability' => 'import',
103
+				'noheader'   => true,
104
+			],
105
+			'export_events'            => [
106
+				'func'       => '_events_export',
107
+				'capability' => 'export',
108
+				'noheader'   => true,
109
+			],
110
+			'export_categories'        => [
111
+				'func'       => '_categories_export',
112
+				'capability' => 'export',
113
+				'noheader'   => true,
114
+			],
115
+			'sample_export_file'       => [
116
+				'func'       => '_sample_export_file',
117
+				'capability' => 'export',
118
+				'noheader'   => true,
119
+			],
120
+			'update_template_settings' => [
121
+				'func'       => '_update_template_settings',
122
+				'capability' => 'manage_options',
123
+				'noheader'   => true,
124
+			],
125
+		];
126
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
127
+		// partial route/config override
128
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
129
+		$this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
130
+		$this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
131
+		$this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
132
+		$this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
133
+		$this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
134
+		// add tickets tab but only if there are more than one default ticket!
135
+		$ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
136
+			[['TKT_is_default' => 1]],
137
+			'TKT_ID',
138
+			true
139
+		);
140
+		if ($ticket_count > 1) {
141
+			$new_page_config = [
142
+				'ticket_list_table' => [
143
+					'nav'           => [
144
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
145
+						'order' => 60,
146
+					],
147
+					'list_table'    => 'Tickets_List_Table',
148
+					'require_nonce' => false,
149
+				],
150
+			];
151
+		}
152
+		// template settings
153
+		$new_page_config['template_settings'] = [
154
+			'nav'           => [
155
+				'label' => esc_html__('Templates', 'event_espresso'),
156
+				'order' => 30,
157
+			],
158
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
159
+			'help_tabs'     => [
160
+				'general_settings_templates_help_tab' => [
161
+					'title'    => esc_html__('Templates', 'event_espresso'),
162
+					'filename' => 'general_settings_templates',
163
+				],
164
+			],
165
+			'require_nonce' => false,
166
+		];
167
+		$this->_page_config                   = array_merge($this->_page_config, $new_page_config);
168
+		// add filters and actions
169
+		// modifying _views
170
+		add_filter(
171
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
172
+			[$this, 'add_additional_datetime_button'],
173
+			10,
174
+			2
175
+		);
176
+		add_filter(
177
+			'FHEE_event_datetime_metabox_clone_button_template',
178
+			[$this, 'add_datetime_clone_button'],
179
+			10,
180
+			2
181
+		);
182
+		add_filter(
183
+			'FHEE_event_datetime_metabox_timezones_template',
184
+			[$this, 'datetime_timezones_template'],
185
+			10,
186
+			2
187
+		);
188
+		// filters for event list table
189
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', [$this, 'list_table_filters'], 10, 2);
190
+		add_filter(
191
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
192
+			[$this, 'extra_list_table_actions'],
193
+			10,
194
+			2
195
+		);
196
+		// legend item
197
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
198
+		add_action('admin_init', [$this, 'admin_init']);
199
+	}
200
+
201
+
202
+	/**
203
+	 * admin_init
204
+	 */
205
+	public function admin_init()
206
+	{
207
+		EE_Registry::$i18n_js_strings = array_merge(
208
+			EE_Registry::$i18n_js_strings,
209
+			[
210
+				'image_confirm'          => esc_html__(
211
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
212
+					'event_espresso'
213
+				),
214
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
215
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
216
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
217
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
218
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
219
+			]
220
+		);
221
+	}
222
+
223
+
224
+	/**
225
+	 * Add per page screen options to the default ticket list table view.
226
+	 */
227
+	protected function _add_screen_options_ticket_list_table()
228
+	{
229
+		$this->_per_page_screen_option();
230
+	}
231
+
232
+
233
+	/**
234
+	 * @param string $return
235
+	 * @param int    $id
236
+	 * @param string $new_title
237
+	 * @param string $new_slug
238
+	 * @return string
239
+	 */
240
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
241
+	{
242
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
243
+		// make sure this is only when editing
244
+		if (! empty($id)) {
245
+			$href   = EE_Admin_Page::add_query_args_and_nonce(
246
+				['action' => 'duplicate_event', 'EVT_ID' => $id],
247
+				$this->_admin_base_url
248
+			);
249
+			$title  = esc_attr__('Duplicate Event', 'event_espresso');
250
+			$return .= '
251 251
                 <a href="' . $href . '" 
252 252
                    aria-label="' . $title . '" 
253 253
                    id="ee-duplicate-event-button" 
@@ -256,1066 +256,1066 @@  discard block
 block discarded – undo
256 256
                 >
257 257
                     ' . $title . '
258 258
                 </a>';
259
-        }
260
-        return $return;
261
-    }
262
-
263
-
264
-    /**
265
-     * Set the list table views for the default ticket list table view.
266
-     */
267
-    public function _set_list_table_views_ticket_list_table()
268
-    {
269
-        $this->_views = [
270
-            'all'     => [
271
-                'slug'        => 'all',
272
-                'label'       => esc_html__('All', 'event_espresso'),
273
-                'count'       => 0,
274
-                'bulk_action' => [
275
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
276
-                ],
277
-            ],
278
-            'trashed' => [
279
-                'slug'        => 'trashed',
280
-                'label'       => esc_html__('Trash', 'event_espresso'),
281
-                'count'       => 0,
282
-                'bulk_action' => [
283
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
284
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
285
-                ],
286
-            ],
287
-        ];
288
-    }
289
-
290
-
291
-    /**
292
-     * Enqueue scripts and styles for the event editor.
293
-     */
294
-    public function load_scripts_styles_edit()
295
-    {
296
-        wp_register_script(
297
-            'ee-event-editor-heartbeat',
298
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
299
-            ['ee_admin_js', 'heartbeat'],
300
-            EVENT_ESPRESSO_VERSION,
301
-            true
302
-        );
303
-        wp_enqueue_script('ee-accounting');
304
-        // styles
305
-        wp_enqueue_style('espresso-ui-theme');
306
-        wp_enqueue_script('event_editor_js');
307
-        wp_enqueue_script('ee-event-editor-heartbeat');
308
-    }
309
-
310
-
311
-    /**
312
-     * Returns template for the additional datetime.
313
-     *
314
-     * @param string $template
315
-     * @param array  $template_args
316
-     * @return string
317
-     * @throws DomainException
318
-     */
319
-    public function add_additional_datetime_button($template, $template_args)
320
-    {
321
-        return EEH_Template::display_template(
322
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
323
-            $template_args,
324
-            true
325
-        );
326
-    }
327
-
328
-
329
-    /**
330
-     * Returns the template for cloning a datetime.
331
-     *
332
-     * @param $template
333
-     * @param $template_args
334
-     * @return string
335
-     * @throws DomainException
336
-     */
337
-    public function add_datetime_clone_button($template, $template_args)
338
-    {
339
-        return EEH_Template::display_template(
340
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
341
-            $template_args,
342
-            true
343
-        );
344
-    }
345
-
346
-
347
-    /**
348
-     * Returns the template for datetime timezones.
349
-     *
350
-     * @param $template
351
-     * @param $template_args
352
-     * @return string
353
-     * @throws DomainException
354
-     */
355
-    public function datetime_timezones_template($template, $template_args)
356
-    {
357
-        return EEH_Template::display_template(
358
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
359
-            $template_args,
360
-            true
361
-        );
362
-    }
363
-
364
-
365
-    /**
366
-     * Sets the views for the default list table view.
367
-     *
368
-     * @throws EE_Error
369
-     */
370
-    protected function _set_list_table_views_default()
371
-    {
372
-        parent::_set_list_table_views_default();
373
-        $new_views    = [
374
-            'today' => [
375
-                'slug'        => 'today',
376
-                'label'       => esc_html__('Today', 'event_espresso'),
377
-                'count'       => $this->total_events_today(),
378
-                'bulk_action' => [
379
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
380
-                ],
381
-            ],
382
-            'month' => [
383
-                'slug'        => 'month',
384
-                'label'       => esc_html__('This Month', 'event_espresso'),
385
-                'count'       => $this->total_events_this_month(),
386
-                'bulk_action' => [
387
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
388
-                ],
389
-            ],
390
-        ];
391
-        $this->_views = array_merge($this->_views, $new_views);
392
-    }
393
-
394
-
395
-    /**
396
-     * Returns the extra action links for the default list table view.
397
-     *
398
-     * @param array    $action_links
399
-     * @param EE_Event $event
400
-     * @return array
401
-     * @throws EE_Error
402
-     * @throws ReflectionException
403
-     */
404
-    public function extra_list_table_actions(array $action_links, EE_Event $event)
405
-    {
406
-        if (
407
-            EE_Registry::instance()->CAP->current_user_can(
408
-                'ee_read_registrations',
409
-                'espresso_registrations_reports',
410
-                $event->ID()
411
-            )
412
-        ) {
413
-            $reports_query_args = [
414
-                'action' => 'reports',
415
-                'EVT_ID' => $event->ID(),
416
-            ];
417
-            $reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
418
-            $action_links[]     = '
259
+		}
260
+		return $return;
261
+	}
262
+
263
+
264
+	/**
265
+	 * Set the list table views for the default ticket list table view.
266
+	 */
267
+	public function _set_list_table_views_ticket_list_table()
268
+	{
269
+		$this->_views = [
270
+			'all'     => [
271
+				'slug'        => 'all',
272
+				'label'       => esc_html__('All', 'event_espresso'),
273
+				'count'       => 0,
274
+				'bulk_action' => [
275
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
276
+				],
277
+			],
278
+			'trashed' => [
279
+				'slug'        => 'trashed',
280
+				'label'       => esc_html__('Trash', 'event_espresso'),
281
+				'count'       => 0,
282
+				'bulk_action' => [
283
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
284
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
285
+				],
286
+			],
287
+		];
288
+	}
289
+
290
+
291
+	/**
292
+	 * Enqueue scripts and styles for the event editor.
293
+	 */
294
+	public function load_scripts_styles_edit()
295
+	{
296
+		wp_register_script(
297
+			'ee-event-editor-heartbeat',
298
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
299
+			['ee_admin_js', 'heartbeat'],
300
+			EVENT_ESPRESSO_VERSION,
301
+			true
302
+		);
303
+		wp_enqueue_script('ee-accounting');
304
+		// styles
305
+		wp_enqueue_style('espresso-ui-theme');
306
+		wp_enqueue_script('event_editor_js');
307
+		wp_enqueue_script('ee-event-editor-heartbeat');
308
+	}
309
+
310
+
311
+	/**
312
+	 * Returns template for the additional datetime.
313
+	 *
314
+	 * @param string $template
315
+	 * @param array  $template_args
316
+	 * @return string
317
+	 * @throws DomainException
318
+	 */
319
+	public function add_additional_datetime_button($template, $template_args)
320
+	{
321
+		return EEH_Template::display_template(
322
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
323
+			$template_args,
324
+			true
325
+		);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Returns the template for cloning a datetime.
331
+	 *
332
+	 * @param $template
333
+	 * @param $template_args
334
+	 * @return string
335
+	 * @throws DomainException
336
+	 */
337
+	public function add_datetime_clone_button($template, $template_args)
338
+	{
339
+		return EEH_Template::display_template(
340
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
341
+			$template_args,
342
+			true
343
+		);
344
+	}
345
+
346
+
347
+	/**
348
+	 * Returns the template for datetime timezones.
349
+	 *
350
+	 * @param $template
351
+	 * @param $template_args
352
+	 * @return string
353
+	 * @throws DomainException
354
+	 */
355
+	public function datetime_timezones_template($template, $template_args)
356
+	{
357
+		return EEH_Template::display_template(
358
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
359
+			$template_args,
360
+			true
361
+		);
362
+	}
363
+
364
+
365
+	/**
366
+	 * Sets the views for the default list table view.
367
+	 *
368
+	 * @throws EE_Error
369
+	 */
370
+	protected function _set_list_table_views_default()
371
+	{
372
+		parent::_set_list_table_views_default();
373
+		$new_views    = [
374
+			'today' => [
375
+				'slug'        => 'today',
376
+				'label'       => esc_html__('Today', 'event_espresso'),
377
+				'count'       => $this->total_events_today(),
378
+				'bulk_action' => [
379
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
380
+				],
381
+			],
382
+			'month' => [
383
+				'slug'        => 'month',
384
+				'label'       => esc_html__('This Month', 'event_espresso'),
385
+				'count'       => $this->total_events_this_month(),
386
+				'bulk_action' => [
387
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
388
+				],
389
+			],
390
+		];
391
+		$this->_views = array_merge($this->_views, $new_views);
392
+	}
393
+
394
+
395
+	/**
396
+	 * Returns the extra action links for the default list table view.
397
+	 *
398
+	 * @param array    $action_links
399
+	 * @param EE_Event $event
400
+	 * @return array
401
+	 * @throws EE_Error
402
+	 * @throws ReflectionException
403
+	 */
404
+	public function extra_list_table_actions(array $action_links, EE_Event $event)
405
+	{
406
+		if (
407
+			EE_Registry::instance()->CAP->current_user_can(
408
+				'ee_read_registrations',
409
+				'espresso_registrations_reports',
410
+				$event->ID()
411
+			)
412
+		) {
413
+			$reports_query_args = [
414
+				'action' => 'reports',
415
+				'EVT_ID' => $event->ID(),
416
+			];
417
+			$reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
418
+			$action_links[]     = '
419 419
                 <a href="' . $reports_link . '" 
420 420
                    aria-label="' . esc_attr__('View Report', 'event_espresso') . '"
421 421
                 >
422 422
                     <div class="dashicons dashicons-chart-bar"></div>
423 423
                 </a>';
424
-        }
425
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
426
-            EE_Registry::instance()->load_helper('MSG_Template');
427
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
428
-                'see_notifications_for',
429
-                null,
430
-                ['EVT_ID' => $event->ID()]
431
-            );
432
-        }
433
-        return $action_links;
434
-    }
435
-
436
-
437
-    /**
438
-     * @param $items
439
-     * @return mixed
440
-     */
441
-    public function additional_legend_items($items)
442
-    {
443
-        if (
444
-            EE_Registry::instance()->CAP->current_user_can(
445
-                'ee_read_registrations',
446
-                'espresso_registrations_reports'
447
-            )
448
-        ) {
449
-            $items['reports'] = [
450
-                'class' => 'dashicons dashicons-chart-bar',
451
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
452
-            ];
453
-        }
454
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
-                $items['view_related_messages'] = [
458
-                    'class' => $related_for_icon['css_class'],
459
-                    'desc'  => $related_for_icon['label'],
460
-                ];
461
-            }
462
-        }
463
-        return $items;
464
-    }
465
-
466
-
467
-    /**
468
-     * This is the callback method for the duplicate event route
469
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
470
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
471
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
472
-     * After duplication the redirect is to the new event edit page.
473
-     *
474
-     * @return void
475
-     * @throws EE_Error If EE_Event is not available with given ID
476
-     * @throws ReflectionException
477
-     * @access protected
478
-     */
479
-    protected function _duplicate_event()
480
-    {
481
-        // first make sure the ID for the event is in the request.
482
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
483
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
484
-        if (! $EVT_ID) {
485
-            EE_Error::add_error(
486
-                esc_html__(
487
-                    'In order to duplicate an event an Event ID is required.  None was given.',
488
-                    'event_espresso'
489
-                ),
490
-                __FILE__,
491
-                __FUNCTION__,
492
-                __LINE__
493
-            );
494
-            $this->_redirect_after_action(false, '', '', [], true);
495
-            return;
496
-        }
497
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
498
-        $orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
499
-        if (! $orig_event instanceof EE_Event) {
500
-            throw new EE_Error(
501
-                sprintf(
502
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
503
-                    $EVT_ID
504
-                )
505
-            );
506
-        }
507
-        // k now let's clone the $orig_event before getting relations
508
-        $new_event = clone $orig_event;
509
-        // original datetimes
510
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
511
-        // other original relations
512
-        $orig_ven = $orig_event->get_many_related('Venue');
513
-        // reset the ID and modify other details to make it clear this is a dupe
514
-        $new_event->set('EVT_ID', 0);
515
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
516
-        $new_event->set('EVT_name', $new_name);
517
-        $new_event->set(
518
-            'EVT_slug',
519
-            wp_unique_post_slug(
520
-                sanitize_title($orig_event->name()),
521
-                0,
522
-                'publish',
523
-                'espresso_events',
524
-                0
525
-            )
526
-        );
527
-        $new_event->set('status', 'draft');
528
-        // duplicate discussion settings
529
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
530
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
531
-        // save the new event
532
-        $new_event->save();
533
-        // venues
534
-        foreach ($orig_ven as $ven) {
535
-            $new_event->_add_relation_to($ven, 'Venue');
536
-        }
537
-        $new_event->save();
538
-        // now we need to get the question group relations and handle that
539
-        // first primary question groups
540
-        $orig_primary_qgs = $orig_event->get_many_related(
541
-            'Question_Group',
542
-            [['Event_Question_Group.EQG_primary' => true]]
543
-        );
544
-        if (! empty($orig_primary_qgs)) {
545
-            foreach ($orig_primary_qgs as $obj) {
546
-                if ($obj instanceof EE_Question_Group) {
547
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
548
-                }
549
-            }
550
-        }
551
-        // next additional attendee question groups
552
-        $orig_additional_qgs = $orig_event->get_many_related(
553
-            'Question_Group',
554
-            [['Event_Question_Group.EQG_additional' => true]]
555
-        );
556
-        if (! empty($orig_additional_qgs)) {
557
-            foreach ($orig_additional_qgs as $obj) {
558
-                if ($obj instanceof EE_Question_Group) {
559
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
560
-                }
561
-            }
562
-        }
563
-
564
-        $new_event->save();
565
-
566
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
567
-        $cloned_tickets = [];
568
-        foreach ($orig_datetimes as $orig_dtt) {
569
-            if (! $orig_dtt instanceof EE_Datetime) {
570
-                continue;
571
-            }
572
-            $new_dtt      = clone $orig_dtt;
573
-            $orig_tickets = $orig_dtt->tickets();
574
-            // save new dtt then add to event
575
-            $new_dtt->set('DTT_ID', 0);
576
-            $new_dtt->set('DTT_sold', 0);
577
-            $new_dtt->set_reserved(0);
578
-            $new_dtt->save();
579
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
580
-            $new_event->save();
581
-            // now let's get the ticket relations setup.
582
-            foreach ((array) $orig_tickets as $orig_ticket) {
583
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
584
-                if (! $orig_ticket instanceof EE_Ticket) {
585
-                    continue;
586
-                }
587
-                // is this ticket archived?  If it is then let's skip
588
-                if ($orig_ticket->get('TKT_deleted')) {
589
-                    continue;
590
-                }
591
-                // does this original ticket already exist in the clone_tickets cache?
592
-                //  If so we'll just use the new ticket from it.
593
-                if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
594
-                    $new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
595
-                } else {
596
-                    $new_ticket = clone $orig_ticket;
597
-                    // get relations on the $orig_ticket that we need to setup.
598
-                    $orig_prices = $orig_ticket->prices();
599
-                    $new_ticket->set('TKT_ID', 0);
600
-                    $new_ticket->set('TKT_sold', 0);
601
-                    $new_ticket->set('TKT_reserved', 0);
602
-                    $new_ticket->save(); // make sure new ticket has ID.
603
-                    // price relations on new ticket need to be setup.
604
-                    foreach ($orig_prices as $orig_price) {
605
-                        $new_price = clone $orig_price;
606
-                        $new_price->set('PRC_ID', 0);
607
-                        $new_price->save();
608
-                        $new_ticket->_add_relation_to($new_price, 'Price');
609
-                        $new_ticket->save();
610
-                    }
611
-
612
-                    do_action(
613
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
614
-                        $orig_ticket,
615
-                        $new_ticket,
616
-                        $orig_prices,
617
-                        $orig_event,
618
-                        $orig_dtt,
619
-                        $new_dtt
620
-                    );
621
-                }
622
-                // k now we can add the new ticket as a relation to the new datetime
623
-                // and make sure its added to our cached $cloned_tickets array
624
-                // for use with later datetimes that have the same ticket.
625
-                $new_dtt->_add_relation_to($new_ticket, 'Ticket');
626
-                $new_dtt->save();
627
-                $cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
628
-            }
629
-        }
630
-        // clone taxonomy information
631
-        $taxonomies_to_clone_with = apply_filters(
632
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
633
-            ['espresso_event_categories', 'espresso_event_type', 'post_tag']
634
-        );
635
-        // get terms for original event (notice)
636
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
637
-        // loop through terms and add them to new event.
638
-        foreach ($orig_terms as $term) {
639
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
640
-        }
641
-
642
-        // duplicate other core WP_Post items for this event.
643
-        // post thumbnail (feature image).
644
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
645
-        if ($feature_image_id) {
646
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
647
-        }
648
-
649
-        // duplicate page_template setting
650
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
651
-        if ($page_template) {
652
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
653
-        }
654
-
655
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
656
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
657
-        if ($new_event->ID()) {
658
-            $redirect_args = [
659
-                'post'   => $new_event->ID(),
660
-                'action' => 'edit',
661
-            ];
662
-            EE_Error::add_success(
663
-                esc_html__(
664
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
665
-                    'event_espresso'
666
-                )
667
-            );
668
-        } else {
669
-            $redirect_args = [
670
-                'action' => 'default',
671
-            ];
672
-            EE_Error::add_error(
673
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
674
-                __FILE__,
675
-                __FUNCTION__,
676
-                __LINE__
677
-            );
678
-        }
679
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
680
-    }
681
-
682
-
683
-    /**
684
-     * Generates output for the import page.
685
-     *
686
-     * @throws EE_Error
687
-     */
688
-    protected function _import_page()
689
-    {
690
-        $title = esc_html__('Import', 'event_espresso');
691
-        $intro = esc_html__(
692
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
693
-            'event_espresso'
694
-        );
695
-
696
-        $form_url = EVENTS_ADMIN_URL;
697
-        $action   = 'import_events';
698
-        $type     = 'csv';
699
-
700
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
701
-            $title,
702
-            $intro,
703
-            $form_url,
704
-            $action,
705
-            $type
706
-        );
707
-
708
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
709
-            ['action' => 'sample_export_file'],
710
-            $this->_admin_base_url
711
-        );
712
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
713
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
714
-            $this->_template_args,
715
-            true
716
-        );
717
-        $this->display_admin_page_with_sidebar();
718
-    }
719
-
720
-
721
-    /**
722
-     * _import_events
723
-     * This handles displaying the screen and running imports for importing events.
724
-     *
725
-     * @return void
726
-     * @throws EE_Error
727
-     */
728
-    protected function _import_events()
729
-    {
730
-        require_once(EE_CLASSES . 'EE_Import.class.php');
731
-        $success = EE_Import::instance()->import();
732
-        $this->_redirect_after_action(
733
-            $success,
734
-            esc_html__('Import File', 'event_espresso'),
735
-            'ran',
736
-            ['action' => 'import_page'],
737
-            true
738
-        );
739
-    }
740
-
741
-
742
-    /**
743
-     * _events_export
744
-     * Will export all (or just the given event) to a Excel compatible file.
745
-     *
746
-     * @access protected
747
-     * @return void
748
-     */
749
-    protected function _events_export()
750
-    {
751
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
752
-        $EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
753
-        $this->request->mergeRequestParams(
754
-            [
755
-                'export' => 'report',
756
-                'action' => 'all_event_data',
757
-                'EVT_ID' => $EVT_ID,
758
-            ]
759
-        );
760
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
761
-            require_once(EE_CLASSES . 'EE_Export.class.php');
762
-            $EE_Export = EE_Export::instance($this->request->requestParams());
763
-            $EE_Export->export();
764
-        }
765
-    }
766
-
767
-
768
-    /**
769
-     * handle category exports()
770
-     *
771
-     * @return void
772
-     */
773
-    protected function _categories_export()
774
-    {
775
-        $EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
776
-        $this->request->mergeRequestParams(
777
-            [
778
-                'export' => 'report',
779
-                'action' => 'categories',
780
-                'EVT_ID' => $EVT_ID,
781
-            ]
782
-        );
783
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
784
-            require_once(EE_CLASSES . 'EE_Export.class.php');
785
-            $EE_Export = EE_Export::instance($this->request->requestParams());
786
-            $EE_Export->export();
787
-        }
788
-    }
789
-
790
-
791
-    /**
792
-     * Creates a sample CSV file for importing
793
-     */
794
-    protected function _sample_export_file()
795
-    {
796
-        // require_once(EE_CLASSES . 'EE_Export.class.php');
797
-        EE_Export::instance()->export_sample();
798
-    }
799
-
800
-
801
-    /*************        Template Settings        *************/
802
-    /**
803
-     * Generates template settings page output
804
-     *
805
-     * @throws DomainException
806
-     * @throws EE_Error
807
-     */
808
-    protected function _template_settings()
809
-    {
810
-        $this->_template_args['values'] = $this->_yes_no_values;
811
-        /**
812
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
813
-         * from General_Settings_Admin_Page to here.
814
-         */
815
-        $this->_template_args = apply_filters(
816
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
817
-            $this->_template_args
818
-        );
819
-        $this->_set_add_edit_form_tags('update_template_settings');
820
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
821
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
822
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
823
-            $this->_template_args,
824
-            true
825
-        );
826
-        $this->display_admin_page_with_sidebar();
827
-    }
828
-
829
-
830
-    /**
831
-     * Handler for updating template settings.
832
-     *
833
-     * @throws EE_Error
834
-     */
835
-    protected function _update_template_settings()
836
-    {
837
-        /**
838
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
839
-         * from General_Settings_Admin_Page to here.
840
-         */
841
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
842
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
843
-            EE_Registry::instance()->CFG->template_settings,
844
-            $this->request->requestParams()
845
-        );
846
-        // update custom post type slugs and detect if we need to flush rewrite rules
847
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
848
-
849
-        $event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
850
-
851
-        EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
852
-            ? EEH_URL::slugify($event_cpt_slug, 'events')
853
-            : EE_Registry::instance()->CFG->core->event_cpt_slug;
854
-
855
-        $what    = esc_html__('Template Settings', 'event_espresso');
856
-        $success = $this->_update_espresso_configuration(
857
-            $what,
858
-            EE_Registry::instance()->CFG->template_settings,
859
-            __FILE__,
860
-            __FUNCTION__,
861
-            __LINE__
862
-        );
863
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
864
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
865
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
866
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
867
-            );
868
-            $rewrite_rules->flush();
869
-        }
870
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
871
-    }
872
-
873
-
874
-    /**
875
-     * _premium_event_editor_meta_boxes
876
-     * add all metaboxes related to the event_editor
877
-     *
878
-     * @access protected
879
-     * @return void
880
-     * @throws EE_Error
881
-     * @throws ReflectionException
882
-     */
883
-    protected function _premium_event_editor_meta_boxes()
884
-    {
885
-        $this->verify_cpt_object();
886
-        add_meta_box(
887
-            'espresso_event_editor_event_options',
888
-            esc_html__('Event Registration Options', 'event_espresso'),
889
-            [$this, 'registration_options_meta_box'],
890
-            $this->page_slug,
891
-            'side',
892
-            'core'
893
-        );
894
-    }
895
-
896
-
897
-    /**
898
-     * override caf metabox
899
-     *
900
-     * @return void
901
-     * @throws EE_Error
902
-     * @throws ReflectionException
903
-     */
904
-    public function registration_options_meta_box()
905
-    {
906
-        $yes_no_values = [
907
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
908
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
909
-        ];
910
-
911
-        $default_reg_status_values = EEM_Registration::reg_status_array(
912
-            [
913
-                EEM_Registration::status_id_cancelled,
914
-                EEM_Registration::status_id_declined,
915
-                EEM_Registration::status_id_incomplete,
916
-                EEM_Registration::status_id_wait_list,
917
-            ],
918
-            true
919
-        );
920
-
921
-        $template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
922
-        $template_args['_event']           = $this->_cpt_model_obj;
923
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
924
-
925
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
926
-            'default_reg_status',
927
-            $default_reg_status_values,
928
-            $this->_cpt_model_obj->default_registration_status()
929
-        );
930
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
931
-            'display_desc',
932
-            $yes_no_values,
933
-            $this->_cpt_model_obj->display_description()
934
-        );
935
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
936
-            'display_ticket_selector',
937
-            $yes_no_values,
938
-            $this->_cpt_model_obj->display_ticket_selector(),
939
-            '',
940
-            '',
941
-            false
942
-        );
943
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
944
-            'EVT_default_registration_status',
945
-            $default_reg_status_values,
946
-            $this->_cpt_model_obj->default_registration_status()
947
-        );
948
-        $template_args['additional_registration_options'] = apply_filters(
949
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
950
-            '',
951
-            $template_args,
952
-            $yes_no_values,
953
-            $default_reg_status_values
954
-        );
955
-        EEH_Template::display_template(
956
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
957
-            $template_args
958
-        );
959
-    }
960
-
961
-
962
-
963
-    /**
964
-     * wp_list_table_mods for caf
965
-     * ============================
966
-     */
967
-    /**
968
-     * hook into list table filters and provide filters for caffeinated list table
969
-     *
970
-     * @param array $old_filters    any existing filters present
971
-     * @param array $list_table_obj the list table object
972
-     * @return array                  new filters
973
-     * @throws EE_Error
974
-     * @throws ReflectionException
975
-     */
976
-    public function list_table_filters($old_filters, $list_table_obj)
977
-    {
978
-        $filters = [];
979
-        // first month/year filters
980
-        $filters[] = $this->espresso_event_months_dropdown();
981
-        $status    = $this->request->getRequestParam('status');
982
-        // active status dropdown
983
-        if ($status !== 'draft') {
984
-            $filters[] = $this->active_status_dropdown($this->request->getRequestParam('active_status'));
985
-            $filters[] = $this->venuesDropdown($this->request->getRequestParam('venue'));
986
-        }
987
-        // category filter
988
-        $filters[] = $this->category_dropdown();
989
-        return array_merge($old_filters, $filters);
990
-    }
991
-
992
-
993
-    /**
994
-     * espresso_event_months_dropdown
995
-     *
996
-     * @access public
997
-     * @return string                dropdown listing month/year selections for events.
998
-     * @throws EE_Error
999
-     */
1000
-    public function espresso_event_months_dropdown()
1001
-    {
1002
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
1003
-        // Note we need to include any other filters that are set!
1004
-        return EEH_Form_Fields::generate_event_months_dropdown(
1005
-            $this->request->getRequestParam('month_range'),
1006
-            $this->request->getRequestParam('status'),
1007
-            $this->request->getRequestParam('EVT_CAT', 0, 'int'),
1008
-            $this->request->getRequestParam('active_status')
1009
-        );
1010
-    }
1011
-
1012
-
1013
-    /**
1014
-     * returns a list of "active" statuses on the event
1015
-     *
1016
-     * @param string $current_value whatever the current active status is
1017
-     * @return string
1018
-     */
1019
-    public function active_status_dropdown($current_value = '')
1020
-    {
1021
-        $select_name = 'active_status';
1022
-        $values      = [
1023
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1024
-            'active'   => esc_html__('Active', 'event_espresso'),
1025
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1026
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1027
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1028
-        ];
1029
-
1030
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1031
-    }
1032
-
1033
-
1034
-    /**
1035
-     * returns a list of "venues"
1036
-     *
1037
-     * @param string $current_value whatever the current active status is
1038
-     * @return string
1039
-     * @throws EE_Error
1040
-     * @throws ReflectionException
1041
-     */
1042
-    protected function venuesDropdown($current_value = '')
1043
-    {
1044
-        $values = [
1045
-            '' => esc_html__('All Venues', 'event_espresso'),
1046
-        ];
1047
-        // populate the list of venues.
1048
-        $venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1049
-
1050
-        foreach ($venues as $venue) {
1051
-            $values[ $venue->ID() ] = $venue->name();
1052
-        }
1053
-
1054
-        return EEH_Form_Fields::select_input('venue', $values, $current_value, '', 'wide');
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * output a dropdown of the categories for the category filter on the event admin list table
1060
-     *
1061
-     * @access  public
1062
-     * @return string html
1063
-     * @throws EE_Error
1064
-     * @throws ReflectionException
1065
-     */
1066
-    public function category_dropdown()
1067
-    {
1068
-        return EEH_Form_Fields::generate_event_category_dropdown(
1069
-            $this->request->getRequestParam('EVT_CAT', -1, 'int')
1070
-        );
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * get total number of events today
1076
-     *
1077
-     * @access public
1078
-     * @return int
1079
-     * @throws EE_Error
1080
-     */
1081
-    public function total_events_today()
1082
-    {
1083
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1084
-            'DTT_EVT_start',
1085
-            date('Y-m-d') . ' 00:00:00',
1086
-            'Y-m-d H:i:s',
1087
-            'UTC'
1088
-        );
1089
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1090
-            'DTT_EVT_start',
1091
-            date('Y-m-d') . ' 23:59:59',
1092
-            'Y-m-d H:i:s',
1093
-            'UTC'
1094
-        );
1095
-        $where = [
1096
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1097
-        ];
1098
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * get total number of events this month
1104
-     *
1105
-     * @access public
1106
-     * @return int
1107
-     * @throws EE_Error
1108
-     */
1109
-    public function total_events_this_month()
1110
-    {
1111
-        // Dates
1112
-        $this_year_r     = date('Y');
1113
-        $this_month_r    = date('m');
1114
-        $days_this_month = date('t');
1115
-        $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1116
-            'DTT_EVT_start',
1117
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1118
-            'Y-m-d H:i:s',
1119
-            'UTC'
1120
-        );
1121
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1122
-            'DTT_EVT_start',
1123
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1124
-            'Y-m-d H:i:s',
1125
-            'UTC'
1126
-        );
1127
-        $where           = [
1128
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1129
-        ];
1130
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1131
-    }
1132
-
1133
-
1134
-    /** DEFAULT TICKETS STUFF **/
1135
-
1136
-    /**
1137
-     * Output default tickets list table view.
1138
-     *
1139
-     * @throws EE_Error
1140
-     */
1141
-    public function _tickets_overview_list_table()
1142
-    {
1143
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1144
-        $this->display_admin_list_table_page_with_no_sidebar();
1145
-    }
1146
-
1147
-
1148
-    /**
1149
-     * @param int  $per_page
1150
-     * @param bool $count
1151
-     * @param bool $trashed
1152
-     * @return EE_Soft_Delete_Base_Class[]|int
1153
-     * @throws EE_Error
1154
-     */
1155
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1156
-    {
1157
-        $orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1158
-        $order   = $this->request->getRequestParam('order', 'ASC');
1159
-        switch ($orderby) {
1160
-            case 'TKT_name':
1161
-                $orderby = ['TKT_name' => $order];
1162
-                break;
1163
-            case 'TKT_price':
1164
-                $orderby = ['TKT_price' => $order];
1165
-                break;
1166
-            case 'TKT_uses':
1167
-                $orderby = ['TKT_uses' => $order];
1168
-                break;
1169
-            case 'TKT_min':
1170
-                $orderby = ['TKT_min' => $order];
1171
-                break;
1172
-            case 'TKT_max':
1173
-                $orderby = ['TKT_max' => $order];
1174
-                break;
1175
-            case 'TKT_qty':
1176
-                $orderby = ['TKT_qty' => $order];
1177
-                break;
1178
-        }
1179
-
1180
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1181
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1182
-        $offset       = ($current_page - 1) * $per_page;
1183
-
1184
-        $where = [
1185
-            'TKT_is_default' => 1,
1186
-            'TKT_deleted'    => $trashed,
1187
-        ];
1188
-
1189
-        $search_term = $this->request->getRequestParam('s');
1190
-        if ($search_term) {
1191
-            $search_term = '%' . $search_term . '%';
1192
-            $where['OR'] = [
1193
-                'TKT_name'        => ['LIKE', $search_term],
1194
-                'TKT_description' => ['LIKE', $search_term],
1195
-            ];
1196
-        }
1197
-
1198
-        return $count
1199
-            ? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1200
-            : EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1201
-                [
1202
-                    $where,
1203
-                    'order_by' => $orderby,
1204
-                    'limit'    => [$offset, $per_page],
1205
-                    'group_by' => 'TKT_ID',
1206
-                ]
1207
-            );
1208
-    }
1209
-
1210
-
1211
-    /**
1212
-     * @param bool $trash
1213
-     * @throws EE_Error
1214
-     */
1215
-    protected function _trash_or_restore_ticket($trash = false)
1216
-    {
1217
-        $success = 1;
1218
-        $TKT     = EEM_Ticket::instance();
1219
-        // checkboxes?
1220
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1221
-        if (! empty($checkboxes)) {
1222
-            // if array has more than one element then success message should be plural
1223
-            $success = count($checkboxes) > 1 ? 2 : 1;
1224
-            // cycle thru the boxes
1225
-            $checkboxes = $this->_req_data['checkbox'];
1226
-            foreach (array_keys($checkboxes) as $TKT_ID) {
1227
-                if ($trash) {
1228
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1229
-                        $success = 0;
1230
-                    }
1231
-                } else {
1232
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1233
-                        $success = 0;
1234
-                    }
1235
-                }
1236
-            }
1237
-        } else {
1238
-            // grab single id and trash
1239
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1240
-            if ($trash) {
1241
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1242
-                    $success = 0;
1243
-                }
1244
-            } else {
1245
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1246
-                    $success = 0;
1247
-                }
1248
-            }
1249
-        }
1250
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1251
-        $query_args  = [
1252
-            'action' => 'ticket_list_table',
1253
-            'status' => $trash ? '' : 'trashed',
1254
-        ];
1255
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * Handles trashing default ticket.
1261
-     *
1262
-     * @throws EE_Error
1263
-     * @throws ReflectionException
1264
-     */
1265
-    protected function _delete_ticket()
1266
-    {
1267
-        $success = 1;
1268
-        // checkboxes?
1269
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1270
-        if (! empty($checkboxes)) {
1271
-            // if array has more than one element then success message should be plural
1272
-            $success = count($checkboxes) > 1 ? 2 : 1;
1273
-            // cycle thru the boxes
1274
-            $checkboxes = $this->_req_data['checkbox'];
1275
-            foreach (array_keys($checkboxes) as $TKT_ID) {
1276
-                // delete
1277
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1278
-                    $success = 0;
1279
-                }
1280
-            }
1281
-        } else {
1282
-            // grab single id and trash
1283
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1284
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1285
-                $success = 0;
1286
-            }
1287
-        }
1288
-        $action_desc = 'deleted';
1289
-        $query_args  = [
1290
-            'action' => 'ticket_list_table',
1291
-            'status' => 'trashed',
1292
-        ];
1293
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1294
-        if (
1295
-            EEM_Ticket::instance()->count_deleted_and_undeleted(
1296
-                [['TKT_is_default' => 1]],
1297
-                'TKT_ID',
1298
-                true
1299
-            )
1300
-        ) {
1301
-            $query_args = [];
1302
-        }
1303
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * @param int $TKT_ID
1309
-     * @return bool|int
1310
-     * @throws EE_Error
1311
-     * @throws ReflectionException
1312
-     */
1313
-    protected function _delete_the_ticket($TKT_ID)
1314
-    {
1315
-        $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1316
-        $ticket->_remove_relations('Datetime');
1317
-        // delete all related prices first
1318
-        $ticket->delete_related_permanently('Price');
1319
-        return $ticket->delete_permanently();
1320
-    }
424
+		}
425
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
426
+			EE_Registry::instance()->load_helper('MSG_Template');
427
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
428
+				'see_notifications_for',
429
+				null,
430
+				['EVT_ID' => $event->ID()]
431
+			);
432
+		}
433
+		return $action_links;
434
+	}
435
+
436
+
437
+	/**
438
+	 * @param $items
439
+	 * @return mixed
440
+	 */
441
+	public function additional_legend_items($items)
442
+	{
443
+		if (
444
+			EE_Registry::instance()->CAP->current_user_can(
445
+				'ee_read_registrations',
446
+				'espresso_registrations_reports'
447
+			)
448
+		) {
449
+			$items['reports'] = [
450
+				'class' => 'dashicons dashicons-chart-bar',
451
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
452
+			];
453
+		}
454
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
455
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
456
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
457
+				$items['view_related_messages'] = [
458
+					'class' => $related_for_icon['css_class'],
459
+					'desc'  => $related_for_icon['label'],
460
+				];
461
+			}
462
+		}
463
+		return $items;
464
+	}
465
+
466
+
467
+	/**
468
+	 * This is the callback method for the duplicate event route
469
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
470
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
471
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
472
+	 * After duplication the redirect is to the new event edit page.
473
+	 *
474
+	 * @return void
475
+	 * @throws EE_Error If EE_Event is not available with given ID
476
+	 * @throws ReflectionException
477
+	 * @access protected
478
+	 */
479
+	protected function _duplicate_event()
480
+	{
481
+		// first make sure the ID for the event is in the request.
482
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
483
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
484
+		if (! $EVT_ID) {
485
+			EE_Error::add_error(
486
+				esc_html__(
487
+					'In order to duplicate an event an Event ID is required.  None was given.',
488
+					'event_espresso'
489
+				),
490
+				__FILE__,
491
+				__FUNCTION__,
492
+				__LINE__
493
+			);
494
+			$this->_redirect_after_action(false, '', '', [], true);
495
+			return;
496
+		}
497
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
498
+		$orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
499
+		if (! $orig_event instanceof EE_Event) {
500
+			throw new EE_Error(
501
+				sprintf(
502
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
503
+					$EVT_ID
504
+				)
505
+			);
506
+		}
507
+		// k now let's clone the $orig_event before getting relations
508
+		$new_event = clone $orig_event;
509
+		// original datetimes
510
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
511
+		// other original relations
512
+		$orig_ven = $orig_event->get_many_related('Venue');
513
+		// reset the ID and modify other details to make it clear this is a dupe
514
+		$new_event->set('EVT_ID', 0);
515
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
516
+		$new_event->set('EVT_name', $new_name);
517
+		$new_event->set(
518
+			'EVT_slug',
519
+			wp_unique_post_slug(
520
+				sanitize_title($orig_event->name()),
521
+				0,
522
+				'publish',
523
+				'espresso_events',
524
+				0
525
+			)
526
+		);
527
+		$new_event->set('status', 'draft');
528
+		// duplicate discussion settings
529
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
530
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
531
+		// save the new event
532
+		$new_event->save();
533
+		// venues
534
+		foreach ($orig_ven as $ven) {
535
+			$new_event->_add_relation_to($ven, 'Venue');
536
+		}
537
+		$new_event->save();
538
+		// now we need to get the question group relations and handle that
539
+		// first primary question groups
540
+		$orig_primary_qgs = $orig_event->get_many_related(
541
+			'Question_Group',
542
+			[['Event_Question_Group.EQG_primary' => true]]
543
+		);
544
+		if (! empty($orig_primary_qgs)) {
545
+			foreach ($orig_primary_qgs as $obj) {
546
+				if ($obj instanceof EE_Question_Group) {
547
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
548
+				}
549
+			}
550
+		}
551
+		// next additional attendee question groups
552
+		$orig_additional_qgs = $orig_event->get_many_related(
553
+			'Question_Group',
554
+			[['Event_Question_Group.EQG_additional' => true]]
555
+		);
556
+		if (! empty($orig_additional_qgs)) {
557
+			foreach ($orig_additional_qgs as $obj) {
558
+				if ($obj instanceof EE_Question_Group) {
559
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
560
+				}
561
+			}
562
+		}
563
+
564
+		$new_event->save();
565
+
566
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
567
+		$cloned_tickets = [];
568
+		foreach ($orig_datetimes as $orig_dtt) {
569
+			if (! $orig_dtt instanceof EE_Datetime) {
570
+				continue;
571
+			}
572
+			$new_dtt      = clone $orig_dtt;
573
+			$orig_tickets = $orig_dtt->tickets();
574
+			// save new dtt then add to event
575
+			$new_dtt->set('DTT_ID', 0);
576
+			$new_dtt->set('DTT_sold', 0);
577
+			$new_dtt->set_reserved(0);
578
+			$new_dtt->save();
579
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
580
+			$new_event->save();
581
+			// now let's get the ticket relations setup.
582
+			foreach ((array) $orig_tickets as $orig_ticket) {
583
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
584
+				if (! $orig_ticket instanceof EE_Ticket) {
585
+					continue;
586
+				}
587
+				// is this ticket archived?  If it is then let's skip
588
+				if ($orig_ticket->get('TKT_deleted')) {
589
+					continue;
590
+				}
591
+				// does this original ticket already exist in the clone_tickets cache?
592
+				//  If so we'll just use the new ticket from it.
593
+				if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
594
+					$new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
595
+				} else {
596
+					$new_ticket = clone $orig_ticket;
597
+					// get relations on the $orig_ticket that we need to setup.
598
+					$orig_prices = $orig_ticket->prices();
599
+					$new_ticket->set('TKT_ID', 0);
600
+					$new_ticket->set('TKT_sold', 0);
601
+					$new_ticket->set('TKT_reserved', 0);
602
+					$new_ticket->save(); // make sure new ticket has ID.
603
+					// price relations on new ticket need to be setup.
604
+					foreach ($orig_prices as $orig_price) {
605
+						$new_price = clone $orig_price;
606
+						$new_price->set('PRC_ID', 0);
607
+						$new_price->save();
608
+						$new_ticket->_add_relation_to($new_price, 'Price');
609
+						$new_ticket->save();
610
+					}
611
+
612
+					do_action(
613
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
614
+						$orig_ticket,
615
+						$new_ticket,
616
+						$orig_prices,
617
+						$orig_event,
618
+						$orig_dtt,
619
+						$new_dtt
620
+					);
621
+				}
622
+				// k now we can add the new ticket as a relation to the new datetime
623
+				// and make sure its added to our cached $cloned_tickets array
624
+				// for use with later datetimes that have the same ticket.
625
+				$new_dtt->_add_relation_to($new_ticket, 'Ticket');
626
+				$new_dtt->save();
627
+				$cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
628
+			}
629
+		}
630
+		// clone taxonomy information
631
+		$taxonomies_to_clone_with = apply_filters(
632
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
633
+			['espresso_event_categories', 'espresso_event_type', 'post_tag']
634
+		);
635
+		// get terms for original event (notice)
636
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
637
+		// loop through terms and add them to new event.
638
+		foreach ($orig_terms as $term) {
639
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
640
+		}
641
+
642
+		// duplicate other core WP_Post items for this event.
643
+		// post thumbnail (feature image).
644
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
645
+		if ($feature_image_id) {
646
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
647
+		}
648
+
649
+		// duplicate page_template setting
650
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
651
+		if ($page_template) {
652
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
653
+		}
654
+
655
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
656
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
657
+		if ($new_event->ID()) {
658
+			$redirect_args = [
659
+				'post'   => $new_event->ID(),
660
+				'action' => 'edit',
661
+			];
662
+			EE_Error::add_success(
663
+				esc_html__(
664
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
665
+					'event_espresso'
666
+				)
667
+			);
668
+		} else {
669
+			$redirect_args = [
670
+				'action' => 'default',
671
+			];
672
+			EE_Error::add_error(
673
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
674
+				__FILE__,
675
+				__FUNCTION__,
676
+				__LINE__
677
+			);
678
+		}
679
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
680
+	}
681
+
682
+
683
+	/**
684
+	 * Generates output for the import page.
685
+	 *
686
+	 * @throws EE_Error
687
+	 */
688
+	protected function _import_page()
689
+	{
690
+		$title = esc_html__('Import', 'event_espresso');
691
+		$intro = esc_html__(
692
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
693
+			'event_espresso'
694
+		);
695
+
696
+		$form_url = EVENTS_ADMIN_URL;
697
+		$action   = 'import_events';
698
+		$type     = 'csv';
699
+
700
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
701
+			$title,
702
+			$intro,
703
+			$form_url,
704
+			$action,
705
+			$type
706
+		);
707
+
708
+		$this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
709
+			['action' => 'sample_export_file'],
710
+			$this->_admin_base_url
711
+		);
712
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
713
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
714
+			$this->_template_args,
715
+			true
716
+		);
717
+		$this->display_admin_page_with_sidebar();
718
+	}
719
+
720
+
721
+	/**
722
+	 * _import_events
723
+	 * This handles displaying the screen and running imports for importing events.
724
+	 *
725
+	 * @return void
726
+	 * @throws EE_Error
727
+	 */
728
+	protected function _import_events()
729
+	{
730
+		require_once(EE_CLASSES . 'EE_Import.class.php');
731
+		$success = EE_Import::instance()->import();
732
+		$this->_redirect_after_action(
733
+			$success,
734
+			esc_html__('Import File', 'event_espresso'),
735
+			'ran',
736
+			['action' => 'import_page'],
737
+			true
738
+		);
739
+	}
740
+
741
+
742
+	/**
743
+	 * _events_export
744
+	 * Will export all (or just the given event) to a Excel compatible file.
745
+	 *
746
+	 * @access protected
747
+	 * @return void
748
+	 */
749
+	protected function _events_export()
750
+	{
751
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
752
+		$EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
753
+		$this->request->mergeRequestParams(
754
+			[
755
+				'export' => 'report',
756
+				'action' => 'all_event_data',
757
+				'EVT_ID' => $EVT_ID,
758
+			]
759
+		);
760
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
761
+			require_once(EE_CLASSES . 'EE_Export.class.php');
762
+			$EE_Export = EE_Export::instance($this->request->requestParams());
763
+			$EE_Export->export();
764
+		}
765
+	}
766
+
767
+
768
+	/**
769
+	 * handle category exports()
770
+	 *
771
+	 * @return void
772
+	 */
773
+	protected function _categories_export()
774
+	{
775
+		$EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
776
+		$this->request->mergeRequestParams(
777
+			[
778
+				'export' => 'report',
779
+				'action' => 'categories',
780
+				'EVT_ID' => $EVT_ID,
781
+			]
782
+		);
783
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
784
+			require_once(EE_CLASSES . 'EE_Export.class.php');
785
+			$EE_Export = EE_Export::instance($this->request->requestParams());
786
+			$EE_Export->export();
787
+		}
788
+	}
789
+
790
+
791
+	/**
792
+	 * Creates a sample CSV file for importing
793
+	 */
794
+	protected function _sample_export_file()
795
+	{
796
+		// require_once(EE_CLASSES . 'EE_Export.class.php');
797
+		EE_Export::instance()->export_sample();
798
+	}
799
+
800
+
801
+	/*************        Template Settings        *************/
802
+	/**
803
+	 * Generates template settings page output
804
+	 *
805
+	 * @throws DomainException
806
+	 * @throws EE_Error
807
+	 */
808
+	protected function _template_settings()
809
+	{
810
+		$this->_template_args['values'] = $this->_yes_no_values;
811
+		/**
812
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
813
+		 * from General_Settings_Admin_Page to here.
814
+		 */
815
+		$this->_template_args = apply_filters(
816
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
817
+			$this->_template_args
818
+		);
819
+		$this->_set_add_edit_form_tags('update_template_settings');
820
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
821
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
822
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
823
+			$this->_template_args,
824
+			true
825
+		);
826
+		$this->display_admin_page_with_sidebar();
827
+	}
828
+
829
+
830
+	/**
831
+	 * Handler for updating template settings.
832
+	 *
833
+	 * @throws EE_Error
834
+	 */
835
+	protected function _update_template_settings()
836
+	{
837
+		/**
838
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
839
+		 * from General_Settings_Admin_Page to here.
840
+		 */
841
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
842
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
843
+			EE_Registry::instance()->CFG->template_settings,
844
+			$this->request->requestParams()
845
+		);
846
+		// update custom post type slugs and detect if we need to flush rewrite rules
847
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
848
+
849
+		$event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
850
+
851
+		EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
852
+			? EEH_URL::slugify($event_cpt_slug, 'events')
853
+			: EE_Registry::instance()->CFG->core->event_cpt_slug;
854
+
855
+		$what    = esc_html__('Template Settings', 'event_espresso');
856
+		$success = $this->_update_espresso_configuration(
857
+			$what,
858
+			EE_Registry::instance()->CFG->template_settings,
859
+			__FILE__,
860
+			__FUNCTION__,
861
+			__LINE__
862
+		);
863
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
864
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
865
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
866
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
867
+			);
868
+			$rewrite_rules->flush();
869
+		}
870
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
871
+	}
872
+
873
+
874
+	/**
875
+	 * _premium_event_editor_meta_boxes
876
+	 * add all metaboxes related to the event_editor
877
+	 *
878
+	 * @access protected
879
+	 * @return void
880
+	 * @throws EE_Error
881
+	 * @throws ReflectionException
882
+	 */
883
+	protected function _premium_event_editor_meta_boxes()
884
+	{
885
+		$this->verify_cpt_object();
886
+		add_meta_box(
887
+			'espresso_event_editor_event_options',
888
+			esc_html__('Event Registration Options', 'event_espresso'),
889
+			[$this, 'registration_options_meta_box'],
890
+			$this->page_slug,
891
+			'side',
892
+			'core'
893
+		);
894
+	}
895
+
896
+
897
+	/**
898
+	 * override caf metabox
899
+	 *
900
+	 * @return void
901
+	 * @throws EE_Error
902
+	 * @throws ReflectionException
903
+	 */
904
+	public function registration_options_meta_box()
905
+	{
906
+		$yes_no_values = [
907
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
908
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
909
+		];
910
+
911
+		$default_reg_status_values = EEM_Registration::reg_status_array(
912
+			[
913
+				EEM_Registration::status_id_cancelled,
914
+				EEM_Registration::status_id_declined,
915
+				EEM_Registration::status_id_incomplete,
916
+				EEM_Registration::status_id_wait_list,
917
+			],
918
+			true
919
+		);
920
+
921
+		$template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
922
+		$template_args['_event']           = $this->_cpt_model_obj;
923
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
924
+
925
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
926
+			'default_reg_status',
927
+			$default_reg_status_values,
928
+			$this->_cpt_model_obj->default_registration_status()
929
+		);
930
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
931
+			'display_desc',
932
+			$yes_no_values,
933
+			$this->_cpt_model_obj->display_description()
934
+		);
935
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
936
+			'display_ticket_selector',
937
+			$yes_no_values,
938
+			$this->_cpt_model_obj->display_ticket_selector(),
939
+			'',
940
+			'',
941
+			false
942
+		);
943
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
944
+			'EVT_default_registration_status',
945
+			$default_reg_status_values,
946
+			$this->_cpt_model_obj->default_registration_status()
947
+		);
948
+		$template_args['additional_registration_options'] = apply_filters(
949
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
950
+			'',
951
+			$template_args,
952
+			$yes_no_values,
953
+			$default_reg_status_values
954
+		);
955
+		EEH_Template::display_template(
956
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
957
+			$template_args
958
+		);
959
+	}
960
+
961
+
962
+
963
+	/**
964
+	 * wp_list_table_mods for caf
965
+	 * ============================
966
+	 */
967
+	/**
968
+	 * hook into list table filters and provide filters for caffeinated list table
969
+	 *
970
+	 * @param array $old_filters    any existing filters present
971
+	 * @param array $list_table_obj the list table object
972
+	 * @return array                  new filters
973
+	 * @throws EE_Error
974
+	 * @throws ReflectionException
975
+	 */
976
+	public function list_table_filters($old_filters, $list_table_obj)
977
+	{
978
+		$filters = [];
979
+		// first month/year filters
980
+		$filters[] = $this->espresso_event_months_dropdown();
981
+		$status    = $this->request->getRequestParam('status');
982
+		// active status dropdown
983
+		if ($status !== 'draft') {
984
+			$filters[] = $this->active_status_dropdown($this->request->getRequestParam('active_status'));
985
+			$filters[] = $this->venuesDropdown($this->request->getRequestParam('venue'));
986
+		}
987
+		// category filter
988
+		$filters[] = $this->category_dropdown();
989
+		return array_merge($old_filters, $filters);
990
+	}
991
+
992
+
993
+	/**
994
+	 * espresso_event_months_dropdown
995
+	 *
996
+	 * @access public
997
+	 * @return string                dropdown listing month/year selections for events.
998
+	 * @throws EE_Error
999
+	 */
1000
+	public function espresso_event_months_dropdown()
1001
+	{
1002
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
1003
+		// Note we need to include any other filters that are set!
1004
+		return EEH_Form_Fields::generate_event_months_dropdown(
1005
+			$this->request->getRequestParam('month_range'),
1006
+			$this->request->getRequestParam('status'),
1007
+			$this->request->getRequestParam('EVT_CAT', 0, 'int'),
1008
+			$this->request->getRequestParam('active_status')
1009
+		);
1010
+	}
1011
+
1012
+
1013
+	/**
1014
+	 * returns a list of "active" statuses on the event
1015
+	 *
1016
+	 * @param string $current_value whatever the current active status is
1017
+	 * @return string
1018
+	 */
1019
+	public function active_status_dropdown($current_value = '')
1020
+	{
1021
+		$select_name = 'active_status';
1022
+		$values      = [
1023
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1024
+			'active'   => esc_html__('Active', 'event_espresso'),
1025
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1026
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1027
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1028
+		];
1029
+
1030
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1031
+	}
1032
+
1033
+
1034
+	/**
1035
+	 * returns a list of "venues"
1036
+	 *
1037
+	 * @param string $current_value whatever the current active status is
1038
+	 * @return string
1039
+	 * @throws EE_Error
1040
+	 * @throws ReflectionException
1041
+	 */
1042
+	protected function venuesDropdown($current_value = '')
1043
+	{
1044
+		$values = [
1045
+			'' => esc_html__('All Venues', 'event_espresso'),
1046
+		];
1047
+		// populate the list of venues.
1048
+		$venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1049
+
1050
+		foreach ($venues as $venue) {
1051
+			$values[ $venue->ID() ] = $venue->name();
1052
+		}
1053
+
1054
+		return EEH_Form_Fields::select_input('venue', $values, $current_value, '', 'wide');
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * output a dropdown of the categories for the category filter on the event admin list table
1060
+	 *
1061
+	 * @access  public
1062
+	 * @return string html
1063
+	 * @throws EE_Error
1064
+	 * @throws ReflectionException
1065
+	 */
1066
+	public function category_dropdown()
1067
+	{
1068
+		return EEH_Form_Fields::generate_event_category_dropdown(
1069
+			$this->request->getRequestParam('EVT_CAT', -1, 'int')
1070
+		);
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * get total number of events today
1076
+	 *
1077
+	 * @access public
1078
+	 * @return int
1079
+	 * @throws EE_Error
1080
+	 */
1081
+	public function total_events_today()
1082
+	{
1083
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1084
+			'DTT_EVT_start',
1085
+			date('Y-m-d') . ' 00:00:00',
1086
+			'Y-m-d H:i:s',
1087
+			'UTC'
1088
+		);
1089
+		$end   = EEM_Datetime::instance()->convert_datetime_for_query(
1090
+			'DTT_EVT_start',
1091
+			date('Y-m-d') . ' 23:59:59',
1092
+			'Y-m-d H:i:s',
1093
+			'UTC'
1094
+		);
1095
+		$where = [
1096
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1097
+		];
1098
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * get total number of events this month
1104
+	 *
1105
+	 * @access public
1106
+	 * @return int
1107
+	 * @throws EE_Error
1108
+	 */
1109
+	public function total_events_this_month()
1110
+	{
1111
+		// Dates
1112
+		$this_year_r     = date('Y');
1113
+		$this_month_r    = date('m');
1114
+		$days_this_month = date('t');
1115
+		$start           = EEM_Datetime::instance()->convert_datetime_for_query(
1116
+			'DTT_EVT_start',
1117
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1118
+			'Y-m-d H:i:s',
1119
+			'UTC'
1120
+		);
1121
+		$end             = EEM_Datetime::instance()->convert_datetime_for_query(
1122
+			'DTT_EVT_start',
1123
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1124
+			'Y-m-d H:i:s',
1125
+			'UTC'
1126
+		);
1127
+		$where           = [
1128
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1129
+		];
1130
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1131
+	}
1132
+
1133
+
1134
+	/** DEFAULT TICKETS STUFF **/
1135
+
1136
+	/**
1137
+	 * Output default tickets list table view.
1138
+	 *
1139
+	 * @throws EE_Error
1140
+	 */
1141
+	public function _tickets_overview_list_table()
1142
+	{
1143
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1144
+		$this->display_admin_list_table_page_with_no_sidebar();
1145
+	}
1146
+
1147
+
1148
+	/**
1149
+	 * @param int  $per_page
1150
+	 * @param bool $count
1151
+	 * @param bool $trashed
1152
+	 * @return EE_Soft_Delete_Base_Class[]|int
1153
+	 * @throws EE_Error
1154
+	 */
1155
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1156
+	{
1157
+		$orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1158
+		$order   = $this->request->getRequestParam('order', 'ASC');
1159
+		switch ($orderby) {
1160
+			case 'TKT_name':
1161
+				$orderby = ['TKT_name' => $order];
1162
+				break;
1163
+			case 'TKT_price':
1164
+				$orderby = ['TKT_price' => $order];
1165
+				break;
1166
+			case 'TKT_uses':
1167
+				$orderby = ['TKT_uses' => $order];
1168
+				break;
1169
+			case 'TKT_min':
1170
+				$orderby = ['TKT_min' => $order];
1171
+				break;
1172
+			case 'TKT_max':
1173
+				$orderby = ['TKT_max' => $order];
1174
+				break;
1175
+			case 'TKT_qty':
1176
+				$orderby = ['TKT_qty' => $order];
1177
+				break;
1178
+		}
1179
+
1180
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1181
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1182
+		$offset       = ($current_page - 1) * $per_page;
1183
+
1184
+		$where = [
1185
+			'TKT_is_default' => 1,
1186
+			'TKT_deleted'    => $trashed,
1187
+		];
1188
+
1189
+		$search_term = $this->request->getRequestParam('s');
1190
+		if ($search_term) {
1191
+			$search_term = '%' . $search_term . '%';
1192
+			$where['OR'] = [
1193
+				'TKT_name'        => ['LIKE', $search_term],
1194
+				'TKT_description' => ['LIKE', $search_term],
1195
+			];
1196
+		}
1197
+
1198
+		return $count
1199
+			? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1200
+			: EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1201
+				[
1202
+					$where,
1203
+					'order_by' => $orderby,
1204
+					'limit'    => [$offset, $per_page],
1205
+					'group_by' => 'TKT_ID',
1206
+				]
1207
+			);
1208
+	}
1209
+
1210
+
1211
+	/**
1212
+	 * @param bool $trash
1213
+	 * @throws EE_Error
1214
+	 */
1215
+	protected function _trash_or_restore_ticket($trash = false)
1216
+	{
1217
+		$success = 1;
1218
+		$TKT     = EEM_Ticket::instance();
1219
+		// checkboxes?
1220
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1221
+		if (! empty($checkboxes)) {
1222
+			// if array has more than one element then success message should be plural
1223
+			$success = count($checkboxes) > 1 ? 2 : 1;
1224
+			// cycle thru the boxes
1225
+			$checkboxes = $this->_req_data['checkbox'];
1226
+			foreach (array_keys($checkboxes) as $TKT_ID) {
1227
+				if ($trash) {
1228
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1229
+						$success = 0;
1230
+					}
1231
+				} else {
1232
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1233
+						$success = 0;
1234
+					}
1235
+				}
1236
+			}
1237
+		} else {
1238
+			// grab single id and trash
1239
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1240
+			if ($trash) {
1241
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1242
+					$success = 0;
1243
+				}
1244
+			} else {
1245
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1246
+					$success = 0;
1247
+				}
1248
+			}
1249
+		}
1250
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1251
+		$query_args  = [
1252
+			'action' => 'ticket_list_table',
1253
+			'status' => $trash ? '' : 'trashed',
1254
+		];
1255
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * Handles trashing default ticket.
1261
+	 *
1262
+	 * @throws EE_Error
1263
+	 * @throws ReflectionException
1264
+	 */
1265
+	protected function _delete_ticket()
1266
+	{
1267
+		$success = 1;
1268
+		// checkboxes?
1269
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1270
+		if (! empty($checkboxes)) {
1271
+			// if array has more than one element then success message should be plural
1272
+			$success = count($checkboxes) > 1 ? 2 : 1;
1273
+			// cycle thru the boxes
1274
+			$checkboxes = $this->_req_data['checkbox'];
1275
+			foreach (array_keys($checkboxes) as $TKT_ID) {
1276
+				// delete
1277
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1278
+					$success = 0;
1279
+				}
1280
+			}
1281
+		} else {
1282
+			// grab single id and trash
1283
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1284
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1285
+				$success = 0;
1286
+			}
1287
+		}
1288
+		$action_desc = 'deleted';
1289
+		$query_args  = [
1290
+			'action' => 'ticket_list_table',
1291
+			'status' => 'trashed',
1292
+		];
1293
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1294
+		if (
1295
+			EEM_Ticket::instance()->count_deleted_and_undeleted(
1296
+				[['TKT_is_default' => 1]],
1297
+				'TKT_ID',
1298
+				true
1299
+			)
1300
+		) {
1301
+			$query_args = [];
1302
+		}
1303
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * @param int $TKT_ID
1309
+	 * @return bool|int
1310
+	 * @throws EE_Error
1311
+	 * @throws ReflectionException
1312
+	 */
1313
+	protected function _delete_the_ticket($TKT_ID)
1314
+	{
1315
+		$ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1316
+		$ticket->_remove_relations('Datetime');
1317
+		// delete all related prices first
1318
+		$ticket->delete_related_permanently('Price');
1319
+		return $ticket->delete_permanently();
1320
+	}
1321 1321
 }
Please login to merge, or discard this patch.
Spacing   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -22,10 +22,10 @@  discard block
 block discarded – undo
22 22
     public function __construct($routing = true)
23 23
     {
24 24
         parent::__construct($routing);
25
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
25
+        if ( ! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
+            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'events/templates/');
27
+            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'events/assets/');
28
+            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'events/assets/');
29 29
         }
30 30
     }
31 31
 
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
      */
38 38
     protected function _extend_page_config()
39 39
     {
40
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
40
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'events';
41 41
         // is there a evt_id in the request?
42 42
         $EVT_ID             = $this->request->getRequestParam('EVT_ID', 0, 'int');
43 43
         $EVT_ID             = $this->request->getRequestParam('post', $EVT_ID, 'int');
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
             ],
165 165
             'require_nonce' => false,
166 166
         ];
167
-        $this->_page_config                   = array_merge($this->_page_config, $new_page_config);
167
+        $this->_page_config = array_merge($this->_page_config, $new_page_config);
168 168
         // add filters and actions
169 169
         // modifying _views
170 170
         add_filter(
@@ -241,20 +241,20 @@  discard block
 block discarded – undo
241 241
     {
242 242
         $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
243 243
         // make sure this is only when editing
244
-        if (! empty($id)) {
245
-            $href   = EE_Admin_Page::add_query_args_and_nonce(
244
+        if ( ! empty($id)) {
245
+            $href = EE_Admin_Page::add_query_args_and_nonce(
246 246
                 ['action' => 'duplicate_event', 'EVT_ID' => $id],
247 247
                 $this->_admin_base_url
248 248
             );
249
-            $title  = esc_attr__('Duplicate Event', 'event_espresso');
249
+            $title = esc_attr__('Duplicate Event', 'event_espresso');
250 250
             $return .= '
251
-                <a href="' . $href . '" 
252
-                   aria-label="' . $title . '" 
251
+                <a href="' . $href.'" 
252
+                   aria-label="' . $title.'" 
253 253
                    id="ee-duplicate-event-button" 
254 254
                    class="button button-small"
255 255
                    value="duplicate_event"
256 256
                 >
257
-                    ' . $title . '
257
+                    ' . $title.'
258 258
                 </a>';
259 259
         }
260 260
         return $return;
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
     {
296 296
         wp_register_script(
297 297
             'ee-event-editor-heartbeat',
298
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
298
+            EVENTS_CAF_ASSETS_URL.'event-editor-heartbeat.js',
299 299
             ['ee_admin_js', 'heartbeat'],
300 300
             EVENT_ESPRESSO_VERSION,
301 301
             true
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
     public function add_additional_datetime_button($template, $template_args)
320 320
     {
321 321
         return EEH_Template::display_template(
322
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
322
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_add_additional_time.template.php',
323 323
             $template_args,
324 324
             true
325 325
         );
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
     public function add_datetime_clone_button($template, $template_args)
338 338
     {
339 339
         return EEH_Template::display_template(
340
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
340
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_metabox_clone_button.template.php',
341 341
             $template_args,
342 342
             true
343 343
         );
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
     public function datetime_timezones_template($template, $template_args)
356 356
     {
357 357
         return EEH_Template::display_template(
358
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
358
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_timezones.template.php',
359 359
             $template_args,
360 360
             true
361 361
         );
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
     protected function _set_list_table_views_default()
371 371
     {
372 372
         parent::_set_list_table_views_default();
373
-        $new_views    = [
373
+        $new_views = [
374 374
             'today' => [
375 375
                 'slug'        => 'today',
376 376
                 'label'       => esc_html__('Today', 'event_espresso'),
@@ -416,8 +416,8 @@  discard block
 block discarded – undo
416 416
             ];
417 417
             $reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
418 418
             $action_links[]     = '
419
-                <a href="' . $reports_link . '" 
420
-                   aria-label="' . esc_attr__('View Report', 'event_espresso') . '"
419
+                <a href="' . $reports_link.'" 
420
+                   aria-label="' . esc_attr__('View Report', 'event_espresso').'"
421 421
                 >
422 422
                     <div class="dashicons dashicons-chart-bar"></div>
423 423
                 </a>';
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
         // first make sure the ID for the event is in the request.
482 482
         //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
483 483
         $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
484
-        if (! $EVT_ID) {
484
+        if ( ! $EVT_ID) {
485 485
             EE_Error::add_error(
486 486
                 esc_html__(
487 487
                     'In order to duplicate an event an Event ID is required.  None was given.',
@@ -496,7 +496,7 @@  discard block
 block discarded – undo
496 496
         }
497 497
         // k we've got EVT_ID so let's use that to get the event we'll duplicate
498 498
         $orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
499
-        if (! $orig_event instanceof EE_Event) {
499
+        if ( ! $orig_event instanceof EE_Event) {
500 500
             throw new EE_Error(
501 501
                 sprintf(
502 502
                     esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
@@ -512,7 +512,7 @@  discard block
 block discarded – undo
512 512
         $orig_ven = $orig_event->get_many_related('Venue');
513 513
         // reset the ID and modify other details to make it clear this is a dupe
514 514
         $new_event->set('EVT_ID', 0);
515
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
515
+        $new_name = $new_event->name().' '.esc_html__('**DUPLICATE**', 'event_espresso');
516 516
         $new_event->set('EVT_name', $new_name);
517 517
         $new_event->set(
518 518
             'EVT_slug',
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
             'Question_Group',
542 542
             [['Event_Question_Group.EQG_primary' => true]]
543 543
         );
544
-        if (! empty($orig_primary_qgs)) {
544
+        if ( ! empty($orig_primary_qgs)) {
545 545
             foreach ($orig_primary_qgs as $obj) {
546 546
                 if ($obj instanceof EE_Question_Group) {
547 547
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
@@ -553,7 +553,7 @@  discard block
 block discarded – undo
553 553
             'Question_Group',
554 554
             [['Event_Question_Group.EQG_additional' => true]]
555 555
         );
556
-        if (! empty($orig_additional_qgs)) {
556
+        if ( ! empty($orig_additional_qgs)) {
557 557
             foreach ($orig_additional_qgs as $obj) {
558 558
                 if ($obj instanceof EE_Question_Group) {
559 559
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
         // k now that we have the new event saved we can loop through the datetimes and start adding relations.
567 567
         $cloned_tickets = [];
568 568
         foreach ($orig_datetimes as $orig_dtt) {
569
-            if (! $orig_dtt instanceof EE_Datetime) {
569
+            if ( ! $orig_dtt instanceof EE_Datetime) {
570 570
                 continue;
571 571
             }
572 572
             $new_dtt      = clone $orig_dtt;
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
             // now let's get the ticket relations setup.
582 582
             foreach ((array) $orig_tickets as $orig_ticket) {
583 583
                 // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
584
-                if (! $orig_ticket instanceof EE_Ticket) {
584
+                if ( ! $orig_ticket instanceof EE_Ticket) {
585 585
                     continue;
586 586
                 }
587 587
                 // is this ticket archived?  If it is then let's skip
@@ -590,8 +590,8 @@  discard block
 block discarded – undo
590 590
                 }
591 591
                 // does this original ticket already exist in the clone_tickets cache?
592 592
                 //  If so we'll just use the new ticket from it.
593
-                if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
594
-                    $new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
593
+                if (isset($cloned_tickets[$orig_ticket->ID()])) {
594
+                    $new_ticket = $cloned_tickets[$orig_ticket->ID()];
595 595
                 } else {
596 596
                     $new_ticket = clone $orig_ticket;
597 597
                     // get relations on the $orig_ticket that we need to setup.
@@ -624,7 +624,7 @@  discard block
 block discarded – undo
624 624
                 // for use with later datetimes that have the same ticket.
625 625
                 $new_dtt->_add_relation_to($new_ticket, 'Ticket');
626 626
                 $new_dtt->save();
627
-                $cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
627
+                $cloned_tickets[$orig_ticket->ID()] = $new_ticket;
628 628
             }
629 629
         }
630 630
         // clone taxonomy information
@@ -705,12 +705,12 @@  discard block
 block discarded – undo
705 705
             $type
706 706
         );
707 707
 
708
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
708
+        $this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
709 709
             ['action' => 'sample_export_file'],
710 710
             $this->_admin_base_url
711 711
         );
712 712
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
713
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
713
+            EVENTS_CAF_TEMPLATE_PATH.'import_page.template.php',
714 714
             $this->_template_args,
715 715
             true
716 716
         );
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
      */
728 728
     protected function _import_events()
729 729
     {
730
-        require_once(EE_CLASSES . 'EE_Import.class.php');
730
+        require_once(EE_CLASSES.'EE_Import.class.php');
731 731
         $success = EE_Import::instance()->import();
732 732
         $this->_redirect_after_action(
733 733
             $success,
@@ -757,8 +757,8 @@  discard block
 block discarded – undo
757 757
                 'EVT_ID' => $EVT_ID,
758 758
             ]
759 759
         );
760
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
761
-            require_once(EE_CLASSES . 'EE_Export.class.php');
760
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
761
+            require_once(EE_CLASSES.'EE_Export.class.php');
762 762
             $EE_Export = EE_Export::instance($this->request->requestParams());
763 763
             $EE_Export->export();
764 764
         }
@@ -780,8 +780,8 @@  discard block
 block discarded – undo
780 780
                 'EVT_ID' => $EVT_ID,
781 781
             ]
782 782
         );
783
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
784
-            require_once(EE_CLASSES . 'EE_Export.class.php');
783
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
784
+            require_once(EE_CLASSES.'EE_Export.class.php');
785 785
             $EE_Export = EE_Export::instance($this->request->requestParams());
786 786
             $EE_Export->export();
787 787
         }
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
         $this->_set_add_edit_form_tags('update_template_settings');
820 820
         $this->_set_publish_post_box_vars(null, false, false, null, false);
821 821
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
822
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
822
+            EVENTS_CAF_TEMPLATE_PATH.'template_settings.template.php',
823 823
             $this->_template_args,
824 824
             true
825 825
         );
@@ -922,17 +922,17 @@  discard block
 block discarded – undo
922 922
         $template_args['_event']           = $this->_cpt_model_obj;
923 923
         $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
924 924
 
925
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
925
+        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
926 926
             'default_reg_status',
927 927
             $default_reg_status_values,
928 928
             $this->_cpt_model_obj->default_registration_status()
929 929
         );
930
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
930
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
931 931
             'display_desc',
932 932
             $yes_no_values,
933 933
             $this->_cpt_model_obj->display_description()
934 934
         );
935
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
935
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
936 936
             'display_ticket_selector',
937 937
             $yes_no_values,
938 938
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -953,7 +953,7 @@  discard block
 block discarded – undo
953 953
             $default_reg_status_values
954 954
         );
955 955
         EEH_Template::display_template(
956
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
956
+            EVENTS_CAF_TEMPLATE_PATH.'event_registration_options.template.php',
957 957
             $template_args
958 958
         );
959 959
     }
@@ -1048,7 +1048,7 @@  discard block
 block discarded – undo
1048 1048
         $venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1049 1049
 
1050 1050
         foreach ($venues as $venue) {
1051
-            $values[ $venue->ID() ] = $venue->name();
1051
+            $values[$venue->ID()] = $venue->name();
1052 1052
         }
1053 1053
 
1054 1054
         return EEH_Form_Fields::select_input('venue', $values, $current_value, '', 'wide');
@@ -1082,13 +1082,13 @@  discard block
 block discarded – undo
1082 1082
     {
1083 1083
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1084 1084
             'DTT_EVT_start',
1085
-            date('Y-m-d') . ' 00:00:00',
1085
+            date('Y-m-d').' 00:00:00',
1086 1086
             'Y-m-d H:i:s',
1087 1087
             'UTC'
1088 1088
         );
1089
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1089
+        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1090 1090
             'DTT_EVT_start',
1091
-            date('Y-m-d') . ' 23:59:59',
1091
+            date('Y-m-d').' 23:59:59',
1092 1092
             'Y-m-d H:i:s',
1093 1093
             'UTC'
1094 1094
         );
@@ -1114,17 +1114,17 @@  discard block
 block discarded – undo
1114 1114
         $days_this_month = date('t');
1115 1115
         $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1116 1116
             'DTT_EVT_start',
1117
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1117
+            $this_year_r.'-'.$this_month_r.'-01 00:00:00',
1118 1118
             'Y-m-d H:i:s',
1119 1119
             'UTC'
1120 1120
         );
1121
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1121
+        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1122 1122
             'DTT_EVT_start',
1123
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1123
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.' 23:59:59',
1124 1124
             'Y-m-d H:i:s',
1125 1125
             'UTC'
1126 1126
         );
1127
-        $where           = [
1127
+        $where = [
1128 1128
             'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1129 1129
         ];
1130 1130
         return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
 
1189 1189
         $search_term = $this->request->getRequestParam('s');
1190 1190
         if ($search_term) {
1191
-            $search_term = '%' . $search_term . '%';
1191
+            $search_term = '%'.$search_term.'%';
1192 1192
             $where['OR'] = [
1193 1193
                 'TKT_name'        => ['LIKE', $search_term],
1194 1194
                 'TKT_description' => ['LIKE', $search_term],
@@ -1218,18 +1218,18 @@  discard block
 block discarded – undo
1218 1218
         $TKT     = EEM_Ticket::instance();
1219 1219
         // checkboxes?
1220 1220
         $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1221
-        if (! empty($checkboxes)) {
1221
+        if ( ! empty($checkboxes)) {
1222 1222
             // if array has more than one element then success message should be plural
1223 1223
             $success = count($checkboxes) > 1 ? 2 : 1;
1224 1224
             // cycle thru the boxes
1225 1225
             $checkboxes = $this->_req_data['checkbox'];
1226 1226
             foreach (array_keys($checkboxes) as $TKT_ID) {
1227 1227
                 if ($trash) {
1228
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1228
+                    if ( ! $TKT->delete_by_ID($TKT_ID)) {
1229 1229
                         $success = 0;
1230 1230
                     }
1231 1231
                 } else {
1232
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1232
+                    if ( ! $TKT->restore_by_ID($TKT_ID)) {
1233 1233
                         $success = 0;
1234 1234
                     }
1235 1235
                 }
@@ -1238,11 +1238,11 @@  discard block
 block discarded – undo
1238 1238
             // grab single id and trash
1239 1239
             $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1240 1240
             if ($trash) {
1241
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1241
+                if ( ! $TKT->delete_by_ID($TKT_ID)) {
1242 1242
                     $success = 0;
1243 1243
                 }
1244 1244
             } else {
1245
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1245
+                if ( ! $TKT->restore_by_ID($TKT_ID)) {
1246 1246
                     $success = 0;
1247 1247
                 }
1248 1248
             }
@@ -1267,21 +1267,21 @@  discard block
 block discarded – undo
1267 1267
         $success = 1;
1268 1268
         // checkboxes?
1269 1269
         $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1270
-        if (! empty($checkboxes)) {
1270
+        if ( ! empty($checkboxes)) {
1271 1271
             // if array has more than one element then success message should be plural
1272 1272
             $success = count($checkboxes) > 1 ? 2 : 1;
1273 1273
             // cycle thru the boxes
1274 1274
             $checkboxes = $this->_req_data['checkbox'];
1275 1275
             foreach (array_keys($checkboxes) as $TKT_ID) {
1276 1276
                 // delete
1277
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1277
+                if ( ! $this->_delete_the_ticket($TKT_ID)) {
1278 1278
                     $success = 0;
1279 1279
                 }
1280 1280
             }
1281 1281
         } else {
1282 1282
             // grab single id and trash
1283 1283
             $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1284
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1284
+            if ( ! $this->_delete_the_ticket($TKT_ID)) {
1285 1285
                 $success = 0;
1286 1286
             }
1287 1287
         }
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 2 patches
Indentation   +1220 added lines, -1220 removed lines patch added patch discarded remove patch
@@ -14,1278 +14,1278 @@
 block discarded – undo
14 14
  */
15 15
 class Extend_Registrations_Admin_Page extends Registrations_Admin_Page
16 16
 {
17
-    /**
18
-     * This is used to hold the reports template data which is setup early in the request.
19
-     *
20
-     * @type array
21
-     */
22
-    protected $_reports_template_data = array();
17
+	/**
18
+	 * This is used to hold the reports template data which is setup early in the request.
19
+	 *
20
+	 * @type array
21
+	 */
22
+	protected $_reports_template_data = array();
23 23
 
24 24
 
25
-    /**
26
-     * Extend_Registrations_Admin_Page constructor.
27
-     *
28
-     * @param bool $routing
29
-     */
30
-    public function __construct($routing = true)
31
-    {
32
-        parent::__construct($routing);
33
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
34
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
35
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
36
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
37
-        }
38
-    }
25
+	/**
26
+	 * Extend_Registrations_Admin_Page constructor.
27
+	 *
28
+	 * @param bool $routing
29
+	 */
30
+	public function __construct($routing = true)
31
+	{
32
+		parent::__construct($routing);
33
+		if (! defined('REG_CAF_TEMPLATE_PATH')) {
34
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
35
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
36
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
37
+		}
38
+	}
39 39
 
40 40
 
41
-    /**
42
-     * Extending page configuration.
43
-     */
44
-    protected function _extend_page_config()
45
-    {
46
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
47
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
48
-            ? $this->_req_data['_REG_ID']
49
-            : 0;
50
-        $new_page_routes = array(
51
-            'reports'                      => array(
52
-                'func'       => '_registration_reports',
53
-                'capability' => 'ee_read_registrations',
54
-            ),
55
-            'registration_checkins'        => array(
56
-                'func'       => '_registration_checkin_list_table',
57
-                'capability' => 'ee_read_checkins',
58
-            ),
59
-            'newsletter_selected_send'     => array(
60
-                'func'       => '_newsletter_selected_send',
61
-                'noheader'   => true,
62
-                'capability' => 'ee_send_message',
63
-            ),
64
-            'delete_checkin_rows'          => array(
65
-                'func'       => '_delete_checkin_rows',
66
-                'noheader'   => true,
67
-                'capability' => 'ee_delete_checkins',
68
-            ),
69
-            'delete_checkin_row'           => array(
70
-                'func'       => '_delete_checkin_row',
71
-                'noheader'   => true,
72
-                'capability' => 'ee_delete_checkin',
73
-                'obj_id'     => $reg_id,
74
-            ),
75
-            'toggle_checkin_status'        => array(
76
-                'func'       => '_toggle_checkin_status',
77
-                'noheader'   => true,
78
-                'capability' => 'ee_edit_checkin',
79
-                'obj_id'     => $reg_id,
80
-            ),
81
-            'toggle_checkin_status_bulk'   => array(
82
-                'func'       => '_toggle_checkin_status',
83
-                'noheader'   => true,
84
-                'capability' => 'ee_edit_checkins',
85
-            ),
86
-            'event_registrations'          => array(
87
-                'func'       => '_event_registrations_list_table',
88
-                'capability' => 'ee_read_checkins',
89
-            ),
90
-            'registrations_checkin_report' => array(
91
-                'func'       => '_registrations_checkin_report',
92
-                'noheader'   => true,
93
-                'capability' => 'ee_read_registrations',
94
-            ),
95
-        );
96
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
97
-        $new_page_config = array(
98
-            'reports'               => array(
99
-                'nav'           => array(
100
-                    'label' => esc_html__('Reports', 'event_espresso'),
101
-                    'order' => 30,
102
-                ),
103
-                'help_tabs'     => array(
104
-                    'registrations_reports_help_tab' => array(
105
-                        'title'    => esc_html__('Registration Reports', 'event_espresso'),
106
-                        'filename' => 'registrations_reports',
107
-                    ),
108
-                ),
109
-                'require_nonce' => false,
110
-            ),
111
-            'event_registrations'   => array(
112
-                'nav'           => array(
113
-                    'label'      => esc_html__('Event Check-In', 'event_espresso'),
114
-                    'order'      => 10,
115
-                    'persistent' => true,
116
-                ),
117
-                'help_tabs'     => array(
118
-                    'registrations_event_checkin_help_tab'                       => array(
119
-                        'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
120
-                        'filename' => 'registrations_event_checkin',
121
-                    ),
122
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
123
-                        'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
124
-                        'filename' => 'registrations_event_checkin_table_column_headings',
125
-                    ),
126
-                    'registrations_event_checkin_filters_help_tab'               => array(
127
-                        'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
128
-                        'filename' => 'registrations_event_checkin_filters',
129
-                    ),
130
-                    'registrations_event_checkin_views_help_tab'                 => array(
131
-                        'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
132
-                        'filename' => 'registrations_event_checkin_views',
133
-                    ),
134
-                    'registrations_event_checkin_other_help_tab'                 => array(
135
-                        'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
136
-                        'filename' => 'registrations_event_checkin_other',
137
-                    ),
138
-                ),
139
-                'qtips'         => array('Registration_List_Table_Tips'),
140
-                'list_table'    => 'EE_Event_Registrations_List_Table',
141
-                'metaboxes'     => array(),
142
-                'require_nonce' => false,
143
-            ),
144
-            'registration_checkins' => array(
145
-                'nav'           => array(
146
-                    'label'      => esc_html__('Check-In Records', 'event_espresso'),
147
-                    'order'      => 15,
148
-                    'persistent' => false,
149
-                    'url'        => '',
150
-                ),
151
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
152
-                'metaboxes'     => array(),
153
-                'require_nonce' => false,
154
-            ),
155
-        );
156
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
157
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
158
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
159
-    }
41
+	/**
42
+	 * Extending page configuration.
43
+	 */
44
+	protected function _extend_page_config()
45
+	{
46
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
47
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
48
+			? $this->_req_data['_REG_ID']
49
+			: 0;
50
+		$new_page_routes = array(
51
+			'reports'                      => array(
52
+				'func'       => '_registration_reports',
53
+				'capability' => 'ee_read_registrations',
54
+			),
55
+			'registration_checkins'        => array(
56
+				'func'       => '_registration_checkin_list_table',
57
+				'capability' => 'ee_read_checkins',
58
+			),
59
+			'newsletter_selected_send'     => array(
60
+				'func'       => '_newsletter_selected_send',
61
+				'noheader'   => true,
62
+				'capability' => 'ee_send_message',
63
+			),
64
+			'delete_checkin_rows'          => array(
65
+				'func'       => '_delete_checkin_rows',
66
+				'noheader'   => true,
67
+				'capability' => 'ee_delete_checkins',
68
+			),
69
+			'delete_checkin_row'           => array(
70
+				'func'       => '_delete_checkin_row',
71
+				'noheader'   => true,
72
+				'capability' => 'ee_delete_checkin',
73
+				'obj_id'     => $reg_id,
74
+			),
75
+			'toggle_checkin_status'        => array(
76
+				'func'       => '_toggle_checkin_status',
77
+				'noheader'   => true,
78
+				'capability' => 'ee_edit_checkin',
79
+				'obj_id'     => $reg_id,
80
+			),
81
+			'toggle_checkin_status_bulk'   => array(
82
+				'func'       => '_toggle_checkin_status',
83
+				'noheader'   => true,
84
+				'capability' => 'ee_edit_checkins',
85
+			),
86
+			'event_registrations'          => array(
87
+				'func'       => '_event_registrations_list_table',
88
+				'capability' => 'ee_read_checkins',
89
+			),
90
+			'registrations_checkin_report' => array(
91
+				'func'       => '_registrations_checkin_report',
92
+				'noheader'   => true,
93
+				'capability' => 'ee_read_registrations',
94
+			),
95
+		);
96
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
97
+		$new_page_config = array(
98
+			'reports'               => array(
99
+				'nav'           => array(
100
+					'label' => esc_html__('Reports', 'event_espresso'),
101
+					'order' => 30,
102
+				),
103
+				'help_tabs'     => array(
104
+					'registrations_reports_help_tab' => array(
105
+						'title'    => esc_html__('Registration Reports', 'event_espresso'),
106
+						'filename' => 'registrations_reports',
107
+					),
108
+				),
109
+				'require_nonce' => false,
110
+			),
111
+			'event_registrations'   => array(
112
+				'nav'           => array(
113
+					'label'      => esc_html__('Event Check-In', 'event_espresso'),
114
+					'order'      => 10,
115
+					'persistent' => true,
116
+				),
117
+				'help_tabs'     => array(
118
+					'registrations_event_checkin_help_tab'                       => array(
119
+						'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
120
+						'filename' => 'registrations_event_checkin',
121
+					),
122
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
123
+						'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
124
+						'filename' => 'registrations_event_checkin_table_column_headings',
125
+					),
126
+					'registrations_event_checkin_filters_help_tab'               => array(
127
+						'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
128
+						'filename' => 'registrations_event_checkin_filters',
129
+					),
130
+					'registrations_event_checkin_views_help_tab'                 => array(
131
+						'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
132
+						'filename' => 'registrations_event_checkin_views',
133
+					),
134
+					'registrations_event_checkin_other_help_tab'                 => array(
135
+						'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
136
+						'filename' => 'registrations_event_checkin_other',
137
+					),
138
+				),
139
+				'qtips'         => array('Registration_List_Table_Tips'),
140
+				'list_table'    => 'EE_Event_Registrations_List_Table',
141
+				'metaboxes'     => array(),
142
+				'require_nonce' => false,
143
+			),
144
+			'registration_checkins' => array(
145
+				'nav'           => array(
146
+					'label'      => esc_html__('Check-In Records', 'event_espresso'),
147
+					'order'      => 15,
148
+					'persistent' => false,
149
+					'url'        => '',
150
+				),
151
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
152
+				'metaboxes'     => array(),
153
+				'require_nonce' => false,
154
+			),
155
+		);
156
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
157
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
158
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
159
+	}
160 160
 
161 161
 
162
-    /**
163
-     * Ajax hooks for all routes in this page.
164
-     */
165
-    protected function _ajax_hooks()
166
-    {
167
-        parent::_ajax_hooks();
168
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
169
-    }
162
+	/**
163
+	 * Ajax hooks for all routes in this page.
164
+	 */
165
+	protected function _ajax_hooks()
166
+	{
167
+		parent::_ajax_hooks();
168
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
169
+	}
170 170
 
171 171
 
172
-    /**
173
-     * Global scripts for all routes in this page.
174
-     */
175
-    public function load_scripts_styles()
176
-    {
177
-        parent::load_scripts_styles();
178
-        // if newsletter message type is active then let's add filter and load js for it.
179
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
180
-            // enqueue newsletter js
181
-            wp_enqueue_script(
182
-                'ee-newsletter-trigger',
183
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
184
-                array('ee-dialog'),
185
-                EVENT_ESPRESSO_VERSION,
186
-                true
187
-            );
188
-            wp_enqueue_style(
189
-                'ee-newsletter-trigger-css',
190
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
191
-                array(),
192
-                EVENT_ESPRESSO_VERSION
193
-            );
194
-            // hook in buttons for newsletter message type trigger.
195
-            add_action(
196
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
197
-                array($this, 'add_newsletter_action_buttons'),
198
-                10
199
-            );
200
-        }
201
-    }
172
+	/**
173
+	 * Global scripts for all routes in this page.
174
+	 */
175
+	public function load_scripts_styles()
176
+	{
177
+		parent::load_scripts_styles();
178
+		// if newsletter message type is active then let's add filter and load js for it.
179
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
180
+			// enqueue newsletter js
181
+			wp_enqueue_script(
182
+				'ee-newsletter-trigger',
183
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
184
+				array('ee-dialog'),
185
+				EVENT_ESPRESSO_VERSION,
186
+				true
187
+			);
188
+			wp_enqueue_style(
189
+				'ee-newsletter-trigger-css',
190
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
191
+				array(),
192
+				EVENT_ESPRESSO_VERSION
193
+			);
194
+			// hook in buttons for newsletter message type trigger.
195
+			add_action(
196
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
197
+				array($this, 'add_newsletter_action_buttons'),
198
+				10
199
+			);
200
+		}
201
+	}
202 202
 
203 203
 
204
-    /**
205
-     * Scripts and styles for just the reports route.
206
-     */
207
-    public function load_scripts_styles_reports()
208
-    {
209
-        wp_register_script(
210
-            'ee-reg-reports-js',
211
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
212
-            array('google-charts'),
213
-            EVENT_ESPRESSO_VERSION,
214
-            true
215
-        );
216
-        wp_enqueue_script('ee-reg-reports-js');
217
-        $this->_registration_reports_js_setup();
218
-    }
204
+	/**
205
+	 * Scripts and styles for just the reports route.
206
+	 */
207
+	public function load_scripts_styles_reports()
208
+	{
209
+		wp_register_script(
210
+			'ee-reg-reports-js',
211
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
212
+			array('google-charts'),
213
+			EVENT_ESPRESSO_VERSION,
214
+			true
215
+		);
216
+		wp_enqueue_script('ee-reg-reports-js');
217
+		$this->_registration_reports_js_setup();
218
+	}
219 219
 
220 220
 
221
-    /**
222
-     * Register screen options for event_registrations route.
223
-     */
224
-    protected function _add_screen_options_event_registrations()
225
-    {
226
-        $this->_per_page_screen_option();
227
-    }
221
+	/**
222
+	 * Register screen options for event_registrations route.
223
+	 */
224
+	protected function _add_screen_options_event_registrations()
225
+	{
226
+		$this->_per_page_screen_option();
227
+	}
228 228
 
229 229
 
230
-    /**
231
-     * Register screen options for registration_checkins route
232
-     */
233
-    protected function _add_screen_options_registration_checkins()
234
-    {
235
-        $page_title = $this->_admin_page_title;
236
-        $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
237
-        $this->_per_page_screen_option();
238
-        $this->_admin_page_title = $page_title;
239
-    }
230
+	/**
231
+	 * Register screen options for registration_checkins route
232
+	 */
233
+	protected function _add_screen_options_registration_checkins()
234
+	{
235
+		$page_title = $this->_admin_page_title;
236
+		$this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
237
+		$this->_per_page_screen_option();
238
+		$this->_admin_page_title = $page_title;
239
+	}
240 240
 
241 241
 
242
-    /**
243
-     * Set views property for event_registrations route.
244
-     */
245
-    protected function _set_list_table_views_event_registrations()
246
-    {
247
-        $this->_views = array(
248
-            'all' => array(
249
-                'slug'        => 'all',
250
-                'label'       => esc_html__('All', 'event_espresso'),
251
-                'count'       => 0,
252
-                'bulk_action' => ! isset($this->_req_data['event_id'])
253
-                    ? array()
254
-                    : array(
255
-                        'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
256
-                    ),
257
-            ),
258
-        );
259
-    }
242
+	/**
243
+	 * Set views property for event_registrations route.
244
+	 */
245
+	protected function _set_list_table_views_event_registrations()
246
+	{
247
+		$this->_views = array(
248
+			'all' => array(
249
+				'slug'        => 'all',
250
+				'label'       => esc_html__('All', 'event_espresso'),
251
+				'count'       => 0,
252
+				'bulk_action' => ! isset($this->_req_data['event_id'])
253
+					? array()
254
+					: array(
255
+						'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
256
+					),
257
+			),
258
+		);
259
+	}
260 260
 
261 261
 
262
-    /**
263
-     * Set views property for registration_checkins route.
264
-     */
265
-    protected function _set_list_table_views_registration_checkins()
266
-    {
267
-        $this->_views = array(
268
-            'all' => array(
269
-                'slug'        => 'all',
270
-                'label'       => esc_html__('All', 'event_espresso'),
271
-                'count'       => 0,
272
-                'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
273
-            ),
274
-        );
275
-    }
262
+	/**
263
+	 * Set views property for registration_checkins route.
264
+	 */
265
+	protected function _set_list_table_views_registration_checkins()
266
+	{
267
+		$this->_views = array(
268
+			'all' => array(
269
+				'slug'        => 'all',
270
+				'label'       => esc_html__('All', 'event_espresso'),
271
+				'count'       => 0,
272
+				'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
273
+			),
274
+		);
275
+	}
276 276
 
277 277
 
278
-    /**
279
-     * callback for ajax action.
280
-     *
281
-     * @since 4.3.0
282
-     * @return void (JSON)
283
-     * @throws EE_Error
284
-     * @throws InvalidArgumentException
285
-     * @throws InvalidDataTypeException
286
-     * @throws InvalidInterfaceException
287
-     */
288
-    public function get_newsletter_form_content()
289
-    {
290
-        // do a nonce check cause we're not coming in from an normal route here.
291
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
292
-            $this->_req_data['get_newsletter_form_content_nonce']
293
-        ) : '';
294
-        $nonce_ref = 'get_newsletter_form_content_nonce';
295
-        $this->_verify_nonce($nonce, $nonce_ref);
296
-        // let's get the mtp for the incoming MTP_ ID
297
-        if (! isset($this->_req_data['GRP_ID'])) {
298
-            EE_Error::add_error(
299
-                esc_html__(
300
-                    'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
301
-                    'event_espresso'
302
-                ),
303
-                __FILE__,
304
-                __FUNCTION__,
305
-                __LINE__
306
-            );
307
-            $this->_template_args['success'] = false;
308
-            $this->_template_args['error'] = true;
309
-            $this->_return_json();
310
-        }
311
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
312
-        if (! $MTPG instanceof EE_Message_Template_Group) {
313
-            EE_Error::add_error(
314
-                sprintf(
315
-                    esc_html__(
316
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
317
-                        'event_espresso'
318
-                    ),
319
-                    $this->_req_data['GRP_ID']
320
-                ),
321
-                __FILE__,
322
-                __FUNCTION__,
323
-                __LINE__
324
-            );
325
-            $this->_template_args['success'] = false;
326
-            $this->_template_args['error'] = true;
327
-            $this->_return_json();
328
-        }
329
-        $MTPs = $MTPG->context_templates();
330
-        $MTPs = $MTPs['attendee'];
331
-        $template_fields = array();
332
-        /** @var EE_Message_Template $MTP */
333
-        foreach ($MTPs as $MTP) {
334
-            $field = $MTP->get('MTP_template_field');
335
-            if ($field === 'content') {
336
-                $content = $MTP->get('MTP_content');
337
-                if (! empty($content['newsletter_content'])) {
338
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
339
-                }
340
-                continue;
341
-            }
342
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
343
-        }
344
-        $this->_template_args['success'] = true;
345
-        $this->_template_args['error'] = false;
346
-        $this->_template_args['data'] = array(
347
-            'batch_message_from'    => isset($template_fields['from'])
348
-                ? $template_fields['from']
349
-                : '',
350
-            'batch_message_subject' => isset($template_fields['subject'])
351
-                ? $template_fields['subject']
352
-                : '',
353
-            'batch_message_content' => isset($template_fields['newsletter_content'])
354
-                ? $template_fields['newsletter_content']
355
-                : '',
356
-        );
357
-        $this->_return_json();
358
-    }
278
+	/**
279
+	 * callback for ajax action.
280
+	 *
281
+	 * @since 4.3.0
282
+	 * @return void (JSON)
283
+	 * @throws EE_Error
284
+	 * @throws InvalidArgumentException
285
+	 * @throws InvalidDataTypeException
286
+	 * @throws InvalidInterfaceException
287
+	 */
288
+	public function get_newsletter_form_content()
289
+	{
290
+		// do a nonce check cause we're not coming in from an normal route here.
291
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
292
+			$this->_req_data['get_newsletter_form_content_nonce']
293
+		) : '';
294
+		$nonce_ref = 'get_newsletter_form_content_nonce';
295
+		$this->_verify_nonce($nonce, $nonce_ref);
296
+		// let's get the mtp for the incoming MTP_ ID
297
+		if (! isset($this->_req_data['GRP_ID'])) {
298
+			EE_Error::add_error(
299
+				esc_html__(
300
+					'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
301
+					'event_espresso'
302
+				),
303
+				__FILE__,
304
+				__FUNCTION__,
305
+				__LINE__
306
+			);
307
+			$this->_template_args['success'] = false;
308
+			$this->_template_args['error'] = true;
309
+			$this->_return_json();
310
+		}
311
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
312
+		if (! $MTPG instanceof EE_Message_Template_Group) {
313
+			EE_Error::add_error(
314
+				sprintf(
315
+					esc_html__(
316
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
317
+						'event_espresso'
318
+					),
319
+					$this->_req_data['GRP_ID']
320
+				),
321
+				__FILE__,
322
+				__FUNCTION__,
323
+				__LINE__
324
+			);
325
+			$this->_template_args['success'] = false;
326
+			$this->_template_args['error'] = true;
327
+			$this->_return_json();
328
+		}
329
+		$MTPs = $MTPG->context_templates();
330
+		$MTPs = $MTPs['attendee'];
331
+		$template_fields = array();
332
+		/** @var EE_Message_Template $MTP */
333
+		foreach ($MTPs as $MTP) {
334
+			$field = $MTP->get('MTP_template_field');
335
+			if ($field === 'content') {
336
+				$content = $MTP->get('MTP_content');
337
+				if (! empty($content['newsletter_content'])) {
338
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
339
+				}
340
+				continue;
341
+			}
342
+			$template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
343
+		}
344
+		$this->_template_args['success'] = true;
345
+		$this->_template_args['error'] = false;
346
+		$this->_template_args['data'] = array(
347
+			'batch_message_from'    => isset($template_fields['from'])
348
+				? $template_fields['from']
349
+				: '',
350
+			'batch_message_subject' => isset($template_fields['subject'])
351
+				? $template_fields['subject']
352
+				: '',
353
+			'batch_message_content' => isset($template_fields['newsletter_content'])
354
+				? $template_fields['newsletter_content']
355
+				: '',
356
+		);
357
+		$this->_return_json();
358
+	}
359 359
 
360 360
 
361
-    /**
362
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
363
-     *
364
-     * @since 4.3.0
365
-     * @param EE_Admin_List_Table $list_table
366
-     * @return void
367
-     * @throws InvalidArgumentException
368
-     * @throws InvalidDataTypeException
369
-     * @throws InvalidInterfaceException
370
-     */
371
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
372
-    {
373
-        if (
374
-            ! EE_Registry::instance()->CAP->current_user_can(
375
-                'ee_send_message',
376
-                'espresso_registrations_newsletter_selected_send'
377
-            )
378
-        ) {
379
-            return;
380
-        }
381
-        $routes_to_add_to = array(
382
-            'contact_list',
383
-            'event_registrations',
384
-            'default',
385
-        );
386
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
387
-            if (
388
-                ($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
389
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
390
-            ) {
391
-                echo '';
392
-            } else {
393
-                $button_text = sprintf(
394
-                    esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
395
-                    '<span class="send-selected-newsletter-count">0</span>'
396
-                );
397
-                echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
398
-                     . '<span class="dashicons dashicons-email "></span>'
399
-                     . $button_text
400
-                     . '</button>';
401
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
402
-            }
403
-        }
404
-    }
361
+	/**
362
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
363
+	 *
364
+	 * @since 4.3.0
365
+	 * @param EE_Admin_List_Table $list_table
366
+	 * @return void
367
+	 * @throws InvalidArgumentException
368
+	 * @throws InvalidDataTypeException
369
+	 * @throws InvalidInterfaceException
370
+	 */
371
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
372
+	{
373
+		if (
374
+			! EE_Registry::instance()->CAP->current_user_can(
375
+				'ee_send_message',
376
+				'espresso_registrations_newsletter_selected_send'
377
+			)
378
+		) {
379
+			return;
380
+		}
381
+		$routes_to_add_to = array(
382
+			'contact_list',
383
+			'event_registrations',
384
+			'default',
385
+		);
386
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
387
+			if (
388
+				($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
389
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
390
+			) {
391
+				echo '';
392
+			} else {
393
+				$button_text = sprintf(
394
+					esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
395
+					'<span class="send-selected-newsletter-count">0</span>'
396
+				);
397
+				echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
398
+					 . '<span class="dashicons dashicons-email "></span>'
399
+					 . $button_text
400
+					 . '</button>';
401
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
402
+			}
403
+		}
404
+	}
405 405
 
406 406
 
407
-    /**
408
-     * @throws DomainException
409
-     * @throws EE_Error
410
-     * @throws InvalidArgumentException
411
-     * @throws InvalidDataTypeException
412
-     * @throws InvalidInterfaceException
413
-     */
414
-    public function newsletter_send_form_skeleton()
415
-    {
416
-        $list_table = $this->_list_table_object;
417
-        $codes = array();
418
-        // need to templates for the newsletter message type for the template selector.
419
-        $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
420
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
421
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
422
-        );
423
-        foreach ($mtps as $mtp) {
424
-            $name = $mtp->name();
425
-            $values[] = array(
426
-                'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
427
-                'id'   => $mtp->ID(),
428
-            );
429
-        }
430
-        // need to get a list of shortcodes that are available for the newsletter message type.
431
-        $shortcodes = EEH_MSG_Template::get_shortcodes(
432
-            'newsletter',
433
-            'email',
434
-            array(),
435
-            'attendee',
436
-            false
437
-        );
438
-        foreach ($shortcodes as $field => $shortcode_array) {
439
-            $available_shortcodes = array();
440
-            foreach ($shortcode_array as $shortcode => $shortcode_details) {
441
-                $field_id = $field === '[NEWSLETTER_CONTENT]'
442
-                    ? 'content'
443
-                    : $field;
444
-                $field_id = 'batch-message-' . strtolower($field_id);
445
-                $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
446
-                                          . $shortcode
447
-                                          . '" data-linked-input-id="' . $field_id . '">'
448
-                                          . $shortcode
449
-                                          . '</span>';
450
-            }
451
-            $codes[ $field ] = implode(', ', $available_shortcodes);
452
-        }
453
-        $shortcodes = $codes;
454
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
455
-        $form_template_args = array(
456
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
457
-            'form_route'        => 'newsletter_selected_send',
458
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
459
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
460
-            'redirect_back_to'  => $this->_req_action,
461
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
462
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
463
-            'shortcodes'        => $shortcodes,
464
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
465
-        );
466
-        EEH_Template::display_template($form_template, $form_template_args);
467
-    }
407
+	/**
408
+	 * @throws DomainException
409
+	 * @throws EE_Error
410
+	 * @throws InvalidArgumentException
411
+	 * @throws InvalidDataTypeException
412
+	 * @throws InvalidInterfaceException
413
+	 */
414
+	public function newsletter_send_form_skeleton()
415
+	{
416
+		$list_table = $this->_list_table_object;
417
+		$codes = array();
418
+		// need to templates for the newsletter message type for the template selector.
419
+		$values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
420
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
421
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
422
+		);
423
+		foreach ($mtps as $mtp) {
424
+			$name = $mtp->name();
425
+			$values[] = array(
426
+				'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
427
+				'id'   => $mtp->ID(),
428
+			);
429
+		}
430
+		// need to get a list of shortcodes that are available for the newsletter message type.
431
+		$shortcodes = EEH_MSG_Template::get_shortcodes(
432
+			'newsletter',
433
+			'email',
434
+			array(),
435
+			'attendee',
436
+			false
437
+		);
438
+		foreach ($shortcodes as $field => $shortcode_array) {
439
+			$available_shortcodes = array();
440
+			foreach ($shortcode_array as $shortcode => $shortcode_details) {
441
+				$field_id = $field === '[NEWSLETTER_CONTENT]'
442
+					? 'content'
443
+					: $field;
444
+				$field_id = 'batch-message-' . strtolower($field_id);
445
+				$available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
446
+										  . $shortcode
447
+										  . '" data-linked-input-id="' . $field_id . '">'
448
+										  . $shortcode
449
+										  . '</span>';
450
+			}
451
+			$codes[ $field ] = implode(', ', $available_shortcodes);
452
+		}
453
+		$shortcodes = $codes;
454
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
455
+		$form_template_args = array(
456
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
457
+			'form_route'        => 'newsletter_selected_send',
458
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
459
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
460
+			'redirect_back_to'  => $this->_req_action,
461
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
462
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
463
+			'shortcodes'        => $shortcodes,
464
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
465
+		);
466
+		EEH_Template::display_template($form_template, $form_template_args);
467
+	}
468 468
 
469 469
 
470
-    /**
471
-     * Handles sending selected registrations/contacts a newsletter.
472
-     *
473
-     * @since  4.3.0
474
-     * @return void
475
-     * @throws EE_Error
476
-     * @throws InvalidArgumentException
477
-     * @throws InvalidDataTypeException
478
-     * @throws InvalidInterfaceException
479
-     */
480
-    protected function _newsletter_selected_send()
481
-    {
482
-        $success = true;
483
-        // first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
484
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
485
-            EE_Error::add_error(
486
-                esc_html__(
487
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
488
-                    'event_espresso'
489
-                ),
490
-                __FILE__,
491
-                __FUNCTION__,
492
-                __LINE__
493
-            );
494
-            $success = false;
495
-        }
496
-        if ($success) {
497
-            // update Message template in case there are any changes
498
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
499
-                $this->_req_data['newsletter_mtp_selected']
500
-            );
501
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
502
-                ? $Message_Template_Group->context_templates()
503
-                : array();
504
-            if (empty($Message_Templates)) {
505
-                EE_Error::add_error(
506
-                    esc_html__(
507
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
508
-                        'event_espresso'
509
-                    ),
510
-                    __FILE__,
511
-                    __FUNCTION__,
512
-                    __LINE__
513
-                );
514
-            }
515
-            // let's just update the specific fields
516
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
517
-                if ($Message_Template instanceof EE_Message_Template) {
518
-                    $field = $Message_Template->get('MTP_template_field');
519
-                    $content = $Message_Template->get('MTP_content');
520
-                    $new_content = $content;
521
-                    switch ($field) {
522
-                        case 'from':
523
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
524
-                                ? $this->_req_data['batch_message']['from']
525
-                                : $content;
526
-                            break;
527
-                        case 'subject':
528
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
529
-                                ? $this->_req_data['batch_message']['subject']
530
-                                : $content;
531
-                            break;
532
-                        case 'content':
533
-                            $new_content = $content;
534
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
535
-                                ? $this->_req_data['batch_message']['content']
536
-                                : $content['newsletter_content'];
537
-                            break;
538
-                        default:
539
-                            // continue the foreach loop, we don't want to set $new_content nor save.
540
-                            continue 2;
541
-                    }
542
-                    $Message_Template->set('MTP_content', $new_content);
543
-                    $Message_Template->save();
544
-                }
545
-            }
546
-            // great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
547
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
548
-                ? $this->_req_data['batch_message']['id_type']
549
-                : 'registration';
550
-            // id_type will affect how we assemble the ids.
551
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
552
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
553
-                : array();
554
-            $registrations_used_for_contact_data = array();
555
-            // using switch because eventually we'll have other contexts that will be used for generating messages.
556
-            switch ($id_type) {
557
-                case 'registration':
558
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
559
-                        array(
560
-                            array(
561
-                                'REG_ID' => array('IN', $ids),
562
-                            ),
563
-                        )
564
-                    );
565
-                    break;
566
-                case 'contact':
567
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
568
-                                                                           ->get_latest_registration_for_each_of_given_contacts(
569
-                                                                               $ids
570
-                                                                           );
571
-                    break;
572
-            }
573
-            do_action_ref_array(
574
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
575
-                array(
576
-                    $registrations_used_for_contact_data,
577
-                    $Message_Template_Group->ID(),
578
-                )
579
-            );
580
-            // kept for backward compat, internally we no longer use this action.
581
-            // @deprecated 4.8.36.rc.002
582
-            $contacts = $id_type === 'registration'
583
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
584
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
585
-            do_action_ref_array(
586
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
587
-                array(
588
-                    $contacts,
589
-                    $Message_Template_Group->ID(),
590
-                )
591
-            );
592
-        }
593
-        $query_args = array(
594
-            'action' => ! empty($this->_req_data['redirect_back_to'])
595
-                ? $this->_req_data['redirect_back_to']
596
-                : 'default',
597
-        );
598
-        $this->_redirect_after_action(false, '', '', $query_args, true);
599
-    }
470
+	/**
471
+	 * Handles sending selected registrations/contacts a newsletter.
472
+	 *
473
+	 * @since  4.3.0
474
+	 * @return void
475
+	 * @throws EE_Error
476
+	 * @throws InvalidArgumentException
477
+	 * @throws InvalidDataTypeException
478
+	 * @throws InvalidInterfaceException
479
+	 */
480
+	protected function _newsletter_selected_send()
481
+	{
482
+		$success = true;
483
+		// first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
484
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
485
+			EE_Error::add_error(
486
+				esc_html__(
487
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
488
+					'event_espresso'
489
+				),
490
+				__FILE__,
491
+				__FUNCTION__,
492
+				__LINE__
493
+			);
494
+			$success = false;
495
+		}
496
+		if ($success) {
497
+			// update Message template in case there are any changes
498
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
499
+				$this->_req_data['newsletter_mtp_selected']
500
+			);
501
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
502
+				? $Message_Template_Group->context_templates()
503
+				: array();
504
+			if (empty($Message_Templates)) {
505
+				EE_Error::add_error(
506
+					esc_html__(
507
+						'Unable to retrieve message template fields from the db. Messages not sent.',
508
+						'event_espresso'
509
+					),
510
+					__FILE__,
511
+					__FUNCTION__,
512
+					__LINE__
513
+				);
514
+			}
515
+			// let's just update the specific fields
516
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
517
+				if ($Message_Template instanceof EE_Message_Template) {
518
+					$field = $Message_Template->get('MTP_template_field');
519
+					$content = $Message_Template->get('MTP_content');
520
+					$new_content = $content;
521
+					switch ($field) {
522
+						case 'from':
523
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
524
+								? $this->_req_data['batch_message']['from']
525
+								: $content;
526
+							break;
527
+						case 'subject':
528
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
529
+								? $this->_req_data['batch_message']['subject']
530
+								: $content;
531
+							break;
532
+						case 'content':
533
+							$new_content = $content;
534
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
535
+								? $this->_req_data['batch_message']['content']
536
+								: $content['newsletter_content'];
537
+							break;
538
+						default:
539
+							// continue the foreach loop, we don't want to set $new_content nor save.
540
+							continue 2;
541
+					}
542
+					$Message_Template->set('MTP_content', $new_content);
543
+					$Message_Template->save();
544
+				}
545
+			}
546
+			// great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
547
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
548
+				? $this->_req_data['batch_message']['id_type']
549
+				: 'registration';
550
+			// id_type will affect how we assemble the ids.
551
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
552
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
553
+				: array();
554
+			$registrations_used_for_contact_data = array();
555
+			// using switch because eventually we'll have other contexts that will be used for generating messages.
556
+			switch ($id_type) {
557
+				case 'registration':
558
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
559
+						array(
560
+							array(
561
+								'REG_ID' => array('IN', $ids),
562
+							),
563
+						)
564
+					);
565
+					break;
566
+				case 'contact':
567
+					$registrations_used_for_contact_data = EEM_Registration::instance()
568
+																		   ->get_latest_registration_for_each_of_given_contacts(
569
+																			   $ids
570
+																		   );
571
+					break;
572
+			}
573
+			do_action_ref_array(
574
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
575
+				array(
576
+					$registrations_used_for_contact_data,
577
+					$Message_Template_Group->ID(),
578
+				)
579
+			);
580
+			// kept for backward compat, internally we no longer use this action.
581
+			// @deprecated 4.8.36.rc.002
582
+			$contacts = $id_type === 'registration'
583
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
584
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
585
+			do_action_ref_array(
586
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
587
+				array(
588
+					$contacts,
589
+					$Message_Template_Group->ID(),
590
+				)
591
+			);
592
+		}
593
+		$query_args = array(
594
+			'action' => ! empty($this->_req_data['redirect_back_to'])
595
+				? $this->_req_data['redirect_back_to']
596
+				: 'default',
597
+		);
598
+		$this->_redirect_after_action(false, '', '', $query_args, true);
599
+	}
600 600
 
601 601
 
602
-    /**
603
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
604
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
605
-     */
606
-    protected function _registration_reports_js_setup()
607
-    {
608
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
609
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
610
-    }
602
+	/**
603
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
604
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
605
+	 */
606
+	protected function _registration_reports_js_setup()
607
+	{
608
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
609
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
610
+	}
611 611
 
612 612
 
613
-    /**
614
-     *        generates Business Reports regarding Registrations
615
-     *
616
-     * @access protected
617
-     * @return void
618
-     * @throws DomainException
619
-     */
620
-    protected function _registration_reports()
621
-    {
622
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
623
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
624
-            $template_path,
625
-            $this->_reports_template_data,
626
-            true
627
-        );
628
-        // the final template wrapper
629
-        $this->display_admin_page_with_no_sidebar();
630
-    }
613
+	/**
614
+	 *        generates Business Reports regarding Registrations
615
+	 *
616
+	 * @access protected
617
+	 * @return void
618
+	 * @throws DomainException
619
+	 */
620
+	protected function _registration_reports()
621
+	{
622
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
623
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
624
+			$template_path,
625
+			$this->_reports_template_data,
626
+			true
627
+		);
628
+		// the final template wrapper
629
+		$this->display_admin_page_with_no_sidebar();
630
+	}
631 631
 
632 632
 
633
-    /**
634
-     * Generates Business Report showing total registrations per day.
635
-     *
636
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
637
-     * @return string
638
-     * @throws EE_Error
639
-     * @throws InvalidArgumentException
640
-     * @throws InvalidDataTypeException
641
-     * @throws InvalidInterfaceException
642
-     */
643
-    private function _registrations_per_day_report($period = '-1 month')
644
-    {
645
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
646
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
647
-        $results = (array) $results;
648
-        $regs = array();
649
-        $subtitle = '';
650
-        if ($results) {
651
-            $column_titles = array();
652
-            $tracker = 0;
653
-            foreach ($results as $result) {
654
-                $report_column_values = array();
655
-                foreach ($result as $property_name => $property_value) {
656
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
657
-                        : (int) $property_value;
658
-                    $report_column_values[] = $property_value;
659
-                    if ($tracker === 0) {
660
-                        if ($property_name === 'Registration_REG_date') {
661
-                            $column_titles[] = esc_html__(
662
-                                'Date (only days with registrations are shown)',
663
-                                'event_espresso'
664
-                            );
665
-                        } else {
666
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
667
-                        }
668
-                    }
669
-                }
670
-                $tracker++;
671
-                $regs[] = $report_column_values;
672
-            }
673
-            // make sure the column_titles is pushed to the beginning of the array
674
-            array_unshift($regs, $column_titles);
675
-            // setup the date range.
676
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
677
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
678
-            $ending_date = new DateTime("now", $DateTimeZone);
679
-            $subtitle = sprintf(
680
-                wp_strip_all_tags(
681
-                    _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
682
-                ),
683
-                $beginning_date->format('Y-m-d'),
684
-                $ending_date->format('Y-m-d')
685
-            );
686
-        }
687
-        $report_title = wp_strip_all_tags(__('Total Registrations per Day', 'event_espresso'));
688
-        $report_params = array(
689
-            'title'     => $report_title,
690
-            'subtitle'  => $subtitle,
691
-            'id'        => $report_ID,
692
-            'regs'      => $regs,
693
-            'noResults' => empty($regs),
694
-            'noRegsMsg' => sprintf(
695
-                wp_strip_all_tags(
696
-                    __(
697
-                        '%sThere are currently no registration records in the last month for this report.%s',
698
-                        'event_espresso'
699
-                    )
700
-                ),
701
-                '<h2>' . $report_title . '</h2><p>',
702
-                '</p>'
703
-            ),
704
-        );
705
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
706
-        return $report_ID;
707
-    }
633
+	/**
634
+	 * Generates Business Report showing total registrations per day.
635
+	 *
636
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
637
+	 * @return string
638
+	 * @throws EE_Error
639
+	 * @throws InvalidArgumentException
640
+	 * @throws InvalidDataTypeException
641
+	 * @throws InvalidInterfaceException
642
+	 */
643
+	private function _registrations_per_day_report($period = '-1 month')
644
+	{
645
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
646
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
647
+		$results = (array) $results;
648
+		$regs = array();
649
+		$subtitle = '';
650
+		if ($results) {
651
+			$column_titles = array();
652
+			$tracker = 0;
653
+			foreach ($results as $result) {
654
+				$report_column_values = array();
655
+				foreach ($result as $property_name => $property_value) {
656
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
657
+						: (int) $property_value;
658
+					$report_column_values[] = $property_value;
659
+					if ($tracker === 0) {
660
+						if ($property_name === 'Registration_REG_date') {
661
+							$column_titles[] = esc_html__(
662
+								'Date (only days with registrations are shown)',
663
+								'event_espresso'
664
+							);
665
+						} else {
666
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
667
+						}
668
+					}
669
+				}
670
+				$tracker++;
671
+				$regs[] = $report_column_values;
672
+			}
673
+			// make sure the column_titles is pushed to the beginning of the array
674
+			array_unshift($regs, $column_titles);
675
+			// setup the date range.
676
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
677
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
678
+			$ending_date = new DateTime("now", $DateTimeZone);
679
+			$subtitle = sprintf(
680
+				wp_strip_all_tags(
681
+					_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
682
+				),
683
+				$beginning_date->format('Y-m-d'),
684
+				$ending_date->format('Y-m-d')
685
+			);
686
+		}
687
+		$report_title = wp_strip_all_tags(__('Total Registrations per Day', 'event_espresso'));
688
+		$report_params = array(
689
+			'title'     => $report_title,
690
+			'subtitle'  => $subtitle,
691
+			'id'        => $report_ID,
692
+			'regs'      => $regs,
693
+			'noResults' => empty($regs),
694
+			'noRegsMsg' => sprintf(
695
+				wp_strip_all_tags(
696
+					__(
697
+						'%sThere are currently no registration records in the last month for this report.%s',
698
+						'event_espresso'
699
+					)
700
+				),
701
+				'<h2>' . $report_title . '</h2><p>',
702
+				'</p>'
703
+			),
704
+		);
705
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
706
+		return $report_ID;
707
+	}
708 708
 
709 709
 
710
-    /**
711
-     * Generates Business Report showing total registrations per event.
712
-     *
713
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
714
-     * @return string
715
-     * @throws EE_Error
716
-     * @throws InvalidArgumentException
717
-     * @throws InvalidDataTypeException
718
-     * @throws InvalidInterfaceException
719
-     */
720
-    private function _registrations_per_event_report($period = '-1 month')
721
-    {
722
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
723
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
724
-        $results = (array) $results;
725
-        $regs = array();
726
-        $subtitle = '';
727
-        if ($results) {
728
-            $column_titles = array();
729
-            $tracker = 0;
730
-            foreach ($results as $result) {
731
-                $report_column_values = array();
732
-                foreach ($result as $property_name => $property_value) {
733
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
734
-                        $property_value,
735
-                        4,
736
-                        '...'
737
-                    ) : (int) $property_value;
738
-                    $report_column_values[] = $property_value;
739
-                    if ($tracker === 0) {
740
-                        if ($property_name === 'Registration_Event') {
741
-                            $column_titles[] = esc_html__('Event', 'event_espresso');
742
-                        } else {
743
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
744
-                        }
745
-                    }
746
-                }
747
-                $tracker++;
748
-                $regs[] = $report_column_values;
749
-            }
750
-            // make sure the column_titles is pushed to the beginning of the array
751
-            array_unshift($regs, $column_titles);
752
-            // setup the date range.
753
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
754
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
755
-            $ending_date = new DateTime("now", $DateTimeZone);
756
-            $subtitle = sprintf(
757
-                wp_strip_all_tags(
758
-                    _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
759
-                ),
760
-                $beginning_date->format('Y-m-d'),
761
-                $ending_date->format('Y-m-d')
762
-            );
763
-        }
764
-        $report_title = wp_strip_all_tags(__('Total Registrations per Event', 'event_espresso'));
765
-        $report_params = array(
766
-            'title'     => $report_title,
767
-            'subtitle'  => $subtitle,
768
-            'id'        => $report_ID,
769
-            'regs'      => $regs,
770
-            'noResults' => empty($regs),
771
-            'noRegsMsg' => sprintf(
772
-                wp_strip_all_tags(
773
-                    __(
774
-                        '%sThere are currently no registration records in the last month for this report.%s',
775
-                        'event_espresso'
776
-                    )
777
-                ),
778
-                '<h2>' . $report_title . '</h2><p>',
779
-                '</p>'
780
-            ),
781
-        );
782
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
783
-        return $report_ID;
784
-    }
710
+	/**
711
+	 * Generates Business Report showing total registrations per event.
712
+	 *
713
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
714
+	 * @return string
715
+	 * @throws EE_Error
716
+	 * @throws InvalidArgumentException
717
+	 * @throws InvalidDataTypeException
718
+	 * @throws InvalidInterfaceException
719
+	 */
720
+	private function _registrations_per_event_report($period = '-1 month')
721
+	{
722
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
723
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
724
+		$results = (array) $results;
725
+		$regs = array();
726
+		$subtitle = '';
727
+		if ($results) {
728
+			$column_titles = array();
729
+			$tracker = 0;
730
+			foreach ($results as $result) {
731
+				$report_column_values = array();
732
+				foreach ($result as $property_name => $property_value) {
733
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
734
+						$property_value,
735
+						4,
736
+						'...'
737
+					) : (int) $property_value;
738
+					$report_column_values[] = $property_value;
739
+					if ($tracker === 0) {
740
+						if ($property_name === 'Registration_Event') {
741
+							$column_titles[] = esc_html__('Event', 'event_espresso');
742
+						} else {
743
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
744
+						}
745
+					}
746
+				}
747
+				$tracker++;
748
+				$regs[] = $report_column_values;
749
+			}
750
+			// make sure the column_titles is pushed to the beginning of the array
751
+			array_unshift($regs, $column_titles);
752
+			// setup the date range.
753
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
754
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
755
+			$ending_date = new DateTime("now", $DateTimeZone);
756
+			$subtitle = sprintf(
757
+				wp_strip_all_tags(
758
+					_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso')
759
+				),
760
+				$beginning_date->format('Y-m-d'),
761
+				$ending_date->format('Y-m-d')
762
+			);
763
+		}
764
+		$report_title = wp_strip_all_tags(__('Total Registrations per Event', 'event_espresso'));
765
+		$report_params = array(
766
+			'title'     => $report_title,
767
+			'subtitle'  => $subtitle,
768
+			'id'        => $report_ID,
769
+			'regs'      => $regs,
770
+			'noResults' => empty($regs),
771
+			'noRegsMsg' => sprintf(
772
+				wp_strip_all_tags(
773
+					__(
774
+						'%sThere are currently no registration records in the last month for this report.%s',
775
+						'event_espresso'
776
+					)
777
+				),
778
+				'<h2>' . $report_title . '</h2><p>',
779
+				'</p>'
780
+			),
781
+		);
782
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
783
+		return $report_ID;
784
+	}
785 785
 
786 786
 
787
-    /**
788
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
789
-     *
790
-     * @access protected
791
-     * @return void
792
-     * @throws EE_Error
793
-     * @throws InvalidArgumentException
794
-     * @throws InvalidDataTypeException
795
-     * @throws InvalidInterfaceException
796
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
797
-     */
798
-    protected function _registration_checkin_list_table()
799
-    {
800
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
801
-        $reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
802
-        /** @var EE_Registration $registration */
803
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
804
-        if (! $registration instanceof EE_Registration) {
805
-            throw new EE_Error(
806
-                sprintf(
807
-                    esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
808
-                    $reg_id
809
-                )
810
-            );
811
-        }
812
-        $attendee = $registration->attendee();
813
-        $this->_admin_page_title .= $this->get_action_link_or_button(
814
-            'new_registration',
815
-            'add-registrant',
816
-            array('event_id' => $registration->event_ID()),
817
-            'add-new-h2'
818
-        );
819
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
820
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
821
-        $legend_items = array(
822
-            'checkin'  => array(
823
-                'class' => $checked_in->cssClasses(),
824
-                'desc'  => $checked_in->legendLabel(),
825
-            ),
826
-            'checkout' => array(
827
-                'class' => $checked_out->cssClasses(),
828
-                'desc'  => $checked_out->legendLabel(),
829
-            ),
830
-        );
831
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
832
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
833
-        /** @var EE_Datetime $datetime */
834
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
835
-        $datetime_label = '';
836
-        if ($datetime instanceof EE_Datetime) {
837
-            $datetime_label = $datetime->get_dtt_display_name(true);
838
-            $datetime_label .= ! empty($datetime_label)
839
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
840
-                : $datetime->get_dtt_display_name();
841
-        }
842
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
843
-            ? EE_Admin_Page::add_query_args_and_nonce(
844
-                array(
845
-                    'action'   => 'event_registrations',
846
-                    'event_id' => $registration->event_ID(),
847
-                    'DTT_ID'   => $dtt_id,
848
-                ),
849
-                $this->_admin_base_url
850
-            )
851
-            : '';
852
-        $datetime_link = ! empty($datetime_link)
853
-            ? '<a href="' . $datetime_link . '">'
854
-              . '<span id="checkin-dtt">'
855
-              . $datetime_label
856
-              . '</span></a>'
857
-            : $datetime_label;
858
-        $attendee_name = $attendee instanceof EE_Attendee
859
-            ? $attendee->full_name()
860
-            : '';
861
-        $attendee_link = $attendee instanceof EE_Attendee
862
-            ? $attendee->get_admin_details_link()
863
-            : '';
864
-        $attendee_link = ! empty($attendee_link)
865
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
866
-              . ' aria-label="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
867
-              . '<span id="checkin-attendee-name">'
868
-              . $attendee_name
869
-              . '</span></a>'
870
-            : '';
871
-        $event_link = $registration->event() instanceof EE_Event
872
-            ? $registration->event()->get_admin_details_link()
873
-            : '';
874
-        $event_link = ! empty($event_link)
875
-            ? '<a href="' . $event_link . '"'
876
-              . ' aria-label="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
877
-              . '<span id="checkin-event-name">'
878
-              . $registration->event_name()
879
-              . '</span>'
880
-              . '</a>'
881
-            : '';
882
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
883
-            ? '<h2>' . sprintf(
884
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
885
-                $attendee_link,
886
-                $datetime_link,
887
-                $event_link
888
-            ) . '</h2>'
889
-            : '';
890
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
891
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
892
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
893
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
894
-        $this->display_admin_list_table_page_with_no_sidebar();
895
-    }
787
+	/**
788
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
789
+	 *
790
+	 * @access protected
791
+	 * @return void
792
+	 * @throws EE_Error
793
+	 * @throws InvalidArgumentException
794
+	 * @throws InvalidDataTypeException
795
+	 * @throws InvalidInterfaceException
796
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
797
+	 */
798
+	protected function _registration_checkin_list_table()
799
+	{
800
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
801
+		$reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
802
+		/** @var EE_Registration $registration */
803
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
804
+		if (! $registration instanceof EE_Registration) {
805
+			throw new EE_Error(
806
+				sprintf(
807
+					esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
808
+					$reg_id
809
+				)
810
+			);
811
+		}
812
+		$attendee = $registration->attendee();
813
+		$this->_admin_page_title .= $this->get_action_link_or_button(
814
+			'new_registration',
815
+			'add-registrant',
816
+			array('event_id' => $registration->event_ID()),
817
+			'add-new-h2'
818
+		);
819
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
820
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
821
+		$legend_items = array(
822
+			'checkin'  => array(
823
+				'class' => $checked_in->cssClasses(),
824
+				'desc'  => $checked_in->legendLabel(),
825
+			),
826
+			'checkout' => array(
827
+				'class' => $checked_out->cssClasses(),
828
+				'desc'  => $checked_out->legendLabel(),
829
+			),
830
+		);
831
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
832
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
833
+		/** @var EE_Datetime $datetime */
834
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
835
+		$datetime_label = '';
836
+		if ($datetime instanceof EE_Datetime) {
837
+			$datetime_label = $datetime->get_dtt_display_name(true);
838
+			$datetime_label .= ! empty($datetime_label)
839
+				? ' (' . $datetime->get_dtt_display_name() . ')'
840
+				: $datetime->get_dtt_display_name();
841
+		}
842
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
843
+			? EE_Admin_Page::add_query_args_and_nonce(
844
+				array(
845
+					'action'   => 'event_registrations',
846
+					'event_id' => $registration->event_ID(),
847
+					'DTT_ID'   => $dtt_id,
848
+				),
849
+				$this->_admin_base_url
850
+			)
851
+			: '';
852
+		$datetime_link = ! empty($datetime_link)
853
+			? '<a href="' . $datetime_link . '">'
854
+			  . '<span id="checkin-dtt">'
855
+			  . $datetime_label
856
+			  . '</span></a>'
857
+			: $datetime_label;
858
+		$attendee_name = $attendee instanceof EE_Attendee
859
+			? $attendee->full_name()
860
+			: '';
861
+		$attendee_link = $attendee instanceof EE_Attendee
862
+			? $attendee->get_admin_details_link()
863
+			: '';
864
+		$attendee_link = ! empty($attendee_link)
865
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
866
+			  . ' aria-label="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
867
+			  . '<span id="checkin-attendee-name">'
868
+			  . $attendee_name
869
+			  . '</span></a>'
870
+			: '';
871
+		$event_link = $registration->event() instanceof EE_Event
872
+			? $registration->event()->get_admin_details_link()
873
+			: '';
874
+		$event_link = ! empty($event_link)
875
+			? '<a href="' . $event_link . '"'
876
+			  . ' aria-label="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
877
+			  . '<span id="checkin-event-name">'
878
+			  . $registration->event_name()
879
+			  . '</span>'
880
+			  . '</a>'
881
+			: '';
882
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
883
+			? '<h2>' . sprintf(
884
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
885
+				$attendee_link,
886
+				$datetime_link,
887
+				$event_link
888
+			) . '</h2>'
889
+			: '';
890
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
891
+			? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
892
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
893
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
894
+		$this->display_admin_list_table_page_with_no_sidebar();
895
+	}
896 896
 
897 897
 
898
-    /**
899
-     * toggle the Check-in status for the given registration (coming from ajax)
900
-     *
901
-     * @return void (JSON)
902
-     * @throws EE_Error
903
-     * @throws InvalidArgumentException
904
-     * @throws InvalidDataTypeException
905
-     * @throws InvalidInterfaceException
906
-     */
907
-    public function toggle_checkin_status()
908
-    {
909
-        // first make sure we have the necessary data
910
-        if (! isset($this->_req_data['_regid'])) {
911
-            EE_Error::add_error(
912
-                esc_html__(
913
-                    'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
914
-                    'event_espresso'
915
-                ),
916
-                __FILE__,
917
-                __FUNCTION__,
918
-                __LINE__
919
-            );
920
-            $this->_template_args['success'] = false;
921
-            $this->_template_args['error'] = true;
922
-            $this->_return_json();
923
-        };
924
-        // do a nonce check cause we're not coming in from an normal route here.
925
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
926
-            : '';
927
-        $nonce_ref = 'checkin_nonce';
928
-        $this->_verify_nonce($nonce, $nonce_ref);
929
-        // beautiful! Made it this far so let's get the status.
930
-        $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
931
-        // setup new class to return via ajax
932
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
933
-        $this->_template_args['success'] = true;
934
-        $this->_return_json();
935
-    }
898
+	/**
899
+	 * toggle the Check-in status for the given registration (coming from ajax)
900
+	 *
901
+	 * @return void (JSON)
902
+	 * @throws EE_Error
903
+	 * @throws InvalidArgumentException
904
+	 * @throws InvalidDataTypeException
905
+	 * @throws InvalidInterfaceException
906
+	 */
907
+	public function toggle_checkin_status()
908
+	{
909
+		// first make sure we have the necessary data
910
+		if (! isset($this->_req_data['_regid'])) {
911
+			EE_Error::add_error(
912
+				esc_html__(
913
+					'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
914
+					'event_espresso'
915
+				),
916
+				__FILE__,
917
+				__FUNCTION__,
918
+				__LINE__
919
+			);
920
+			$this->_template_args['success'] = false;
921
+			$this->_template_args['error'] = true;
922
+			$this->_return_json();
923
+		};
924
+		// do a nonce check cause we're not coming in from an normal route here.
925
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
926
+			: '';
927
+		$nonce_ref = 'checkin_nonce';
928
+		$this->_verify_nonce($nonce, $nonce_ref);
929
+		// beautiful! Made it this far so let's get the status.
930
+		$new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
931
+		// setup new class to return via ajax
932
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
933
+		$this->_template_args['success'] = true;
934
+		$this->_return_json();
935
+	}
936 936
 
937 937
 
938
-    /**
939
-     * handles toggling the checkin status for the registration,
940
-     *
941
-     * @access protected
942
-     * @return int|void
943
-     * @throws EE_Error
944
-     * @throws InvalidArgumentException
945
-     * @throws InvalidDataTypeException
946
-     * @throws InvalidInterfaceException
947
-     */
948
-    protected function _toggle_checkin_status()
949
-    {
950
-        // first let's get the query args out of the way for the redirect
951
-        $query_args = array(
952
-            'action'   => 'event_registrations',
953
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
954
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
955
-        );
956
-        $new_status = false;
957
-        // bulk action check in toggle
958
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
959
-            // cycle thru checkboxes
960
-            $checkboxes = $this->_req_data['checkbox'];
961
-            foreach (array_keys($checkboxes) as $REG_ID) {
962
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
963
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
964
-            }
965
-        } elseif (isset($this->_req_data['_regid'])) {
966
-            // coming from ajax request
967
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
968
-            $query_args['DTT_ID'] = $DTT_ID;
969
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
970
-        } else {
971
-            EE_Error::add_error(
972
-                esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
973
-                __FILE__,
974
-                __FUNCTION__,
975
-                __LINE__
976
-            );
977
-        }
978
-        if (defined('DOING_AJAX')) {
979
-            return $new_status;
980
-        }
981
-        $this->_redirect_after_action(false, '', '', $query_args, true);
982
-    }
938
+	/**
939
+	 * handles toggling the checkin status for the registration,
940
+	 *
941
+	 * @access protected
942
+	 * @return int|void
943
+	 * @throws EE_Error
944
+	 * @throws InvalidArgumentException
945
+	 * @throws InvalidDataTypeException
946
+	 * @throws InvalidInterfaceException
947
+	 */
948
+	protected function _toggle_checkin_status()
949
+	{
950
+		// first let's get the query args out of the way for the redirect
951
+		$query_args = array(
952
+			'action'   => 'event_registrations',
953
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
954
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
955
+		);
956
+		$new_status = false;
957
+		// bulk action check in toggle
958
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
959
+			// cycle thru checkboxes
960
+			$checkboxes = $this->_req_data['checkbox'];
961
+			foreach (array_keys($checkboxes) as $REG_ID) {
962
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
963
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
964
+			}
965
+		} elseif (isset($this->_req_data['_regid'])) {
966
+			// coming from ajax request
967
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
968
+			$query_args['DTT_ID'] = $DTT_ID;
969
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
970
+		} else {
971
+			EE_Error::add_error(
972
+				esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
973
+				__FILE__,
974
+				__FUNCTION__,
975
+				__LINE__
976
+			);
977
+		}
978
+		if (defined('DOING_AJAX')) {
979
+			return $new_status;
980
+		}
981
+		$this->_redirect_after_action(false, '', '', $query_args, true);
982
+	}
983 983
 
984 984
 
985
-    /**
986
-     * This is toggles a single Check-in for the given registration and datetime.
987
-     *
988
-     * @param  int $REG_ID The registration we're toggling
989
-     * @param  int $DTT_ID The datetime we're toggling
990
-     * @return int The new status toggled to.
991
-     * @throws EE_Error
992
-     * @throws InvalidArgumentException
993
-     * @throws InvalidDataTypeException
994
-     * @throws InvalidInterfaceException
995
-     */
996
-    private function _toggle_checkin($REG_ID, $DTT_ID)
997
-    {
998
-        /** @var EE_Registration $REG */
999
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1000
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
1001
-        if ($new_status !== false) {
1002
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
1003
-        } else {
1004
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
1005
-            $new_status = false;
1006
-        }
1007
-        return $new_status;
1008
-    }
985
+	/**
986
+	 * This is toggles a single Check-in for the given registration and datetime.
987
+	 *
988
+	 * @param  int $REG_ID The registration we're toggling
989
+	 * @param  int $DTT_ID The datetime we're toggling
990
+	 * @return int The new status toggled to.
991
+	 * @throws EE_Error
992
+	 * @throws InvalidArgumentException
993
+	 * @throws InvalidDataTypeException
994
+	 * @throws InvalidInterfaceException
995
+	 */
996
+	private function _toggle_checkin($REG_ID, $DTT_ID)
997
+	{
998
+		/** @var EE_Registration $REG */
999
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1000
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
1001
+		if ($new_status !== false) {
1002
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
1003
+		} else {
1004
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
1005
+			$new_status = false;
1006
+		}
1007
+		return $new_status;
1008
+	}
1009 1009
 
1010 1010
 
1011
-    /**
1012
-     * Takes care of deleting multiple EE_Checkin table rows
1013
-     *
1014
-     * @access protected
1015
-     * @return void
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     */
1021
-    protected function _delete_checkin_rows()
1022
-    {
1023
-        $query_args = array(
1024
-            'action'  => 'registration_checkins',
1025
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1026
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1027
-        );
1028
-        $errors = 0;
1029
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1030
-            $checkboxes = $this->_req_data['checkbox'];
1031
-            foreach (array_keys($checkboxes) as $CHK_ID) {
1032
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1033
-                    $errors++;
1034
-                }
1035
-            }
1036
-        } else {
1037
-            EE_Error::add_error(
1038
-                esc_html__(
1039
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1040
-                    'event_espresso'
1041
-                ),
1042
-                __FILE__,
1043
-                __FUNCTION__,
1044
-                __LINE__
1045
-            );
1046
-            $this->_redirect_after_action(false, '', '', $query_args, true);
1047
-        }
1048
-        if ($errors > 0) {
1049
-            EE_Error::add_error(
1050
-                sprintf(esc_html__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1051
-                __FILE__,
1052
-                __FUNCTION__,
1053
-                __LINE__
1054
-            );
1055
-        } else {
1056
-            EE_Error::add_success(esc_html__('Records were successfully deleted', 'event_espresso'));
1057
-        }
1058
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1059
-    }
1011
+	/**
1012
+	 * Takes care of deleting multiple EE_Checkin table rows
1013
+	 *
1014
+	 * @access protected
1015
+	 * @return void
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 */
1021
+	protected function _delete_checkin_rows()
1022
+	{
1023
+		$query_args = array(
1024
+			'action'  => 'registration_checkins',
1025
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1026
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1027
+		);
1028
+		$errors = 0;
1029
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1030
+			$checkboxes = $this->_req_data['checkbox'];
1031
+			foreach (array_keys($checkboxes) as $CHK_ID) {
1032
+				if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1033
+					$errors++;
1034
+				}
1035
+			}
1036
+		} else {
1037
+			EE_Error::add_error(
1038
+				esc_html__(
1039
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1040
+					'event_espresso'
1041
+				),
1042
+				__FILE__,
1043
+				__FUNCTION__,
1044
+				__LINE__
1045
+			);
1046
+			$this->_redirect_after_action(false, '', '', $query_args, true);
1047
+		}
1048
+		if ($errors > 0) {
1049
+			EE_Error::add_error(
1050
+				sprintf(esc_html__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1051
+				__FILE__,
1052
+				__FUNCTION__,
1053
+				__LINE__
1054
+			);
1055
+		} else {
1056
+			EE_Error::add_success(esc_html__('Records were successfully deleted', 'event_espresso'));
1057
+		}
1058
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1059
+	}
1060 1060
 
1061 1061
 
1062
-    /**
1063
-     * Deletes a single EE_Checkin row
1064
-     *
1065
-     * @return void
1066
-     * @throws EE_Error
1067
-     * @throws InvalidArgumentException
1068
-     * @throws InvalidDataTypeException
1069
-     * @throws InvalidInterfaceException
1070
-     */
1071
-    protected function _delete_checkin_row()
1072
-    {
1073
-        $query_args = array(
1074
-            'action'  => 'registration_checkins',
1075
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1076
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1077
-        );
1078
-        if (! empty($this->_req_data['CHK_ID'])) {
1079
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1080
-                EE_Error::add_error(
1081
-                    esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1082
-                    __FILE__,
1083
-                    __FUNCTION__,
1084
-                    __LINE__
1085
-                );
1086
-            } else {
1087
-                EE_Error::add_success(esc_html__('Check-In record successfully deleted', 'event_espresso'));
1088
-            }
1089
-        } else {
1090
-            EE_Error::add_error(
1091
-                esc_html__(
1092
-                    'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1093
-                    'event_espresso'
1094
-                ),
1095
-                __FILE__,
1096
-                __FUNCTION__,
1097
-                __LINE__
1098
-            );
1099
-        }
1100
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1101
-    }
1062
+	/**
1063
+	 * Deletes a single EE_Checkin row
1064
+	 *
1065
+	 * @return void
1066
+	 * @throws EE_Error
1067
+	 * @throws InvalidArgumentException
1068
+	 * @throws InvalidDataTypeException
1069
+	 * @throws InvalidInterfaceException
1070
+	 */
1071
+	protected function _delete_checkin_row()
1072
+	{
1073
+		$query_args = array(
1074
+			'action'  => 'registration_checkins',
1075
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1076
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1077
+		);
1078
+		if (! empty($this->_req_data['CHK_ID'])) {
1079
+			if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1080
+				EE_Error::add_error(
1081
+					esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1082
+					__FILE__,
1083
+					__FUNCTION__,
1084
+					__LINE__
1085
+				);
1086
+			} else {
1087
+				EE_Error::add_success(esc_html__('Check-In record successfully deleted', 'event_espresso'));
1088
+			}
1089
+		} else {
1090
+			EE_Error::add_error(
1091
+				esc_html__(
1092
+					'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1093
+					'event_espresso'
1094
+				),
1095
+				__FILE__,
1096
+				__FUNCTION__,
1097
+				__LINE__
1098
+			);
1099
+		}
1100
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1101
+	}
1102 1102
 
1103 1103
 
1104
-    /**
1105
-     *        generates HTML for the Event Registrations List Table
1106
-     *
1107
-     * @access protected
1108
-     * @return void
1109
-     * @throws EE_Error
1110
-     * @throws InvalidArgumentException
1111
-     * @throws InvalidDataTypeException
1112
-     * @throws InvalidInterfaceException
1113
-     */
1114
-    protected function _event_registrations_list_table()
1115
-    {
1116
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1117
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1118
-            ? $this->get_action_link_or_button(
1119
-                'new_registration',
1120
-                'add-registrant',
1121
-                array('event_id' => $this->_req_data['event_id']),
1122
-                'add-new-h2',
1123
-                '',
1124
-                false
1125
-            )
1126
-            : '';
1127
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1128
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1129
-        $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1130
-        $legend_items = array(
1131
-            'star-icon'        => array(
1132
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1133
-                'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1134
-            ),
1135
-            'checkin'          => array(
1136
-                'class' => $checked_in->cssClasses(),
1137
-                'desc'  => $checked_in->legendLabel(),
1138
-            ),
1139
-            'checkout'         => array(
1140
-                'class' => $checked_out->cssClasses(),
1141
-                'desc'  => $checked_out->legendLabel(),
1142
-            ),
1143
-            'nocheckinrecord'  => array(
1144
-                'class' => $checked_never->cssClasses(),
1145
-                'desc'  => $checked_never->legendLabel(),
1146
-            ),
1147
-            'approved_status'  => array(
1148
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1149
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1150
-            ),
1151
-            'cancelled_status' => array(
1152
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1153
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1154
-            ),
1155
-            'declined_status'  => array(
1156
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1157
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1158
-            ),
1159
-            'not_approved'     => array(
1160
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1161
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1162
-            ),
1163
-            'pending_status'   => array(
1164
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1165
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1166
-            ),
1167
-            'wait_list'        => array(
1168
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1169
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1170
-            ),
1171
-        );
1172
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1173
-        $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1174
-        /** @var EE_Event $event */
1175
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1176
-        $this->_template_args['before_list_table'] = $event instanceof EE_Event
1177
-            ? '<h2>' . sprintf(
1178
-                esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1179
-                EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1180
-            ) . '</h2>'
1181
-            : '';
1182
-        // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1183
-        // the event.
1184
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1185
-        $datetime = null;
1186
-        if ($event instanceof EE_Event) {
1187
-            $datetimes_on_event = $event->datetimes();
1188
-            if (count($datetimes_on_event) === 1) {
1189
-                $datetime = reset($datetimes_on_event);
1190
-            }
1191
-        }
1192
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1193
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1194
-            $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1195
-            $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1196
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1197
-            $this->_template_args['before_list_table'] .= $datetime->name();
1198
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1199
-            $this->_template_args['before_list_table'] .= '</span></h2>';
1200
-        }
1201
-        // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1202
-        // column represents
1203
-        if (! $datetime instanceof EE_Datetime) {
1204
-            $this->_template_args['before_list_table'] .= '<br><p class="description">'
1205
-                                                          . esc_html__(
1206
-                                                              'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1207
-                                                              'event_espresso'
1208
-                                                          )
1209
-                                                          . '</p>';
1210
-        }
1211
-        $this->display_admin_list_table_page_with_no_sidebar();
1212
-    }
1104
+	/**
1105
+	 *        generates HTML for the Event Registrations List Table
1106
+	 *
1107
+	 * @access protected
1108
+	 * @return void
1109
+	 * @throws EE_Error
1110
+	 * @throws InvalidArgumentException
1111
+	 * @throws InvalidDataTypeException
1112
+	 * @throws InvalidInterfaceException
1113
+	 */
1114
+	protected function _event_registrations_list_table()
1115
+	{
1116
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1117
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1118
+			? $this->get_action_link_or_button(
1119
+				'new_registration',
1120
+				'add-registrant',
1121
+				array('event_id' => $this->_req_data['event_id']),
1122
+				'add-new-h2',
1123
+				'',
1124
+				false
1125
+			)
1126
+			: '';
1127
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1128
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1129
+		$checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1130
+		$legend_items = array(
1131
+			'star-icon'        => array(
1132
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1133
+				'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1134
+			),
1135
+			'checkin'          => array(
1136
+				'class' => $checked_in->cssClasses(),
1137
+				'desc'  => $checked_in->legendLabel(),
1138
+			),
1139
+			'checkout'         => array(
1140
+				'class' => $checked_out->cssClasses(),
1141
+				'desc'  => $checked_out->legendLabel(),
1142
+			),
1143
+			'nocheckinrecord'  => array(
1144
+				'class' => $checked_never->cssClasses(),
1145
+				'desc'  => $checked_never->legendLabel(),
1146
+			),
1147
+			'approved_status'  => array(
1148
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1149
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1150
+			),
1151
+			'cancelled_status' => array(
1152
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1153
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1154
+			),
1155
+			'declined_status'  => array(
1156
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1157
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1158
+			),
1159
+			'not_approved'     => array(
1160
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1161
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1162
+			),
1163
+			'pending_status'   => array(
1164
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1165
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1166
+			),
1167
+			'wait_list'        => array(
1168
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1169
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1170
+			),
1171
+		);
1172
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1173
+		$event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1174
+		/** @var EE_Event $event */
1175
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1176
+		$this->_template_args['before_list_table'] = $event instanceof EE_Event
1177
+			? '<h2>' . sprintf(
1178
+				esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1179
+				EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1180
+			) . '</h2>'
1181
+			: '';
1182
+		// need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1183
+		// the event.
1184
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1185
+		$datetime = null;
1186
+		if ($event instanceof EE_Event) {
1187
+			$datetimes_on_event = $event->datetimes();
1188
+			if (count($datetimes_on_event) === 1) {
1189
+				$datetime = reset($datetimes_on_event);
1190
+			}
1191
+		}
1192
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1193
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1194
+			$this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1195
+			$this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1196
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1197
+			$this->_template_args['before_list_table'] .= $datetime->name();
1198
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1199
+			$this->_template_args['before_list_table'] .= '</span></h2>';
1200
+		}
1201
+		// if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1202
+		// column represents
1203
+		if (! $datetime instanceof EE_Datetime) {
1204
+			$this->_template_args['before_list_table'] .= '<br><p class="description">'
1205
+														  . esc_html__(
1206
+															  'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1207
+															  'event_espresso'
1208
+														  )
1209
+														  . '</p>';
1210
+		}
1211
+		$this->display_admin_list_table_page_with_no_sidebar();
1212
+	}
1213 1213
 
1214
-    /**
1215
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1216
-     * conditions)
1217
-     *
1218
-     * @return void ends the request by a redirect or download
1219
-     */
1220
-    public function _registrations_checkin_report()
1221
-    {
1222
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1223
-    }
1214
+	/**
1215
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1216
+	 * conditions)
1217
+	 *
1218
+	 * @return void ends the request by a redirect or download
1219
+	 */
1220
+	public function _registrations_checkin_report()
1221
+	{
1222
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1223
+	}
1224 1224
 
1225
-    /**
1226
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1227
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1228
-     *
1229
-     * @param array $request
1230
-     * @param int   $per_page
1231
-     * @param bool  $count
1232
-     * @return array
1233
-     * @throws EE_Error
1234
-     */
1235
-    protected function _get_checkin_query_params_from_request(
1236
-        $request,
1237
-        $per_page = 10,
1238
-        $count = false
1239
-    ) {
1240
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1241
-        // unlike the regular registrations list table,
1242
-        $status_ids_array = apply_filters(
1243
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1244
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1245
-        );
1246
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1247
-        return $query_params;
1248
-    }
1225
+	/**
1226
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1227
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1228
+	 *
1229
+	 * @param array $request
1230
+	 * @param int   $per_page
1231
+	 * @param bool  $count
1232
+	 * @return array
1233
+	 * @throws EE_Error
1234
+	 */
1235
+	protected function _get_checkin_query_params_from_request(
1236
+		$request,
1237
+		$per_page = 10,
1238
+		$count = false
1239
+	) {
1240
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1241
+		// unlike the regular registrations list table,
1242
+		$status_ids_array = apply_filters(
1243
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1244
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1245
+		);
1246
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1247
+		return $query_params;
1248
+	}
1249 1249
 
1250 1250
 
1251
-    /**
1252
-     * Gets registrations for an event
1253
-     *
1254
-     * @param int    $per_page
1255
-     * @param bool   $count whether to return count or data.
1256
-     * @param bool   $trash
1257
-     * @param string $orderby
1258
-     * @return EE_Registration[]|int
1259
-     * @throws EE_Error
1260
-     * @throws InvalidArgumentException
1261
-     * @throws InvalidDataTypeException
1262
-     * @throws InvalidInterfaceException
1263
-     */
1264
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1265
-    {
1266
-        // set some defaults, these will get overridden if included in the actual request parameters
1267
-        $defaults = [
1268
-            'orderby' => $orderby,
1269
-            'order' => 'ASC',
1270
-        ];
1271
-        if ($trash) {
1272
-            $defaults['status'] = 'trash';
1273
-        }
1274
-        $query_params = $this->_get_checkin_query_params_from_request($defaults, $per_page, $count);
1251
+	/**
1252
+	 * Gets registrations for an event
1253
+	 *
1254
+	 * @param int    $per_page
1255
+	 * @param bool   $count whether to return count or data.
1256
+	 * @param bool   $trash
1257
+	 * @param string $orderby
1258
+	 * @return EE_Registration[]|int
1259
+	 * @throws EE_Error
1260
+	 * @throws InvalidArgumentException
1261
+	 * @throws InvalidDataTypeException
1262
+	 * @throws InvalidInterfaceException
1263
+	 */
1264
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1265
+	{
1266
+		// set some defaults, these will get overridden if included in the actual request parameters
1267
+		$defaults = [
1268
+			'orderby' => $orderby,
1269
+			'order' => 'ASC',
1270
+		];
1271
+		if ($trash) {
1272
+			$defaults['status'] = 'trash';
1273
+		}
1274
+		$query_params = $this->_get_checkin_query_params_from_request($defaults, $per_page, $count);
1275 1275
 
1276
-        /**
1277
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1278
-         *
1279
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1280
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1281
-         *                             or if you have the development copy of EE you can view this at the path:
1282
-         *                             /docs/G--Model-System/model-query-params.md
1283
-         */
1284
-        $query_params['group_by'] = '';
1276
+		/**
1277
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1278
+		 *
1279
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1280
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1281
+		 *                             or if you have the development copy of EE you can view this at the path:
1282
+		 *                             /docs/G--Model-System/model-query-params.md
1283
+		 */
1284
+		$query_params['group_by'] = '';
1285 1285
 
1286
-        return $count
1287
-            ? EEM_Registration::instance()->count($query_params)
1288
-            /** @type EE_Registration[] */
1289
-            : EEM_Registration::instance()->get_all($query_params);
1290
-    }
1286
+		return $count
1287
+			? EEM_Registration::instance()->count($query_params)
1288
+			/** @type EE_Registration[] */
1289
+			: EEM_Registration::instance()->get_all($query_params);
1290
+	}
1291 1291
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -30,10 +30,10 @@  discard block
 block discarded – undo
30 30
     public function __construct($routing = true)
31 31
     {
32 32
         parent::__construct($routing);
33
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
34
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
35
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
36
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
33
+        if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
34
+            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'registrations/templates/');
35
+            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'registrations/assets/');
36
+            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registrations/assets/');
37 37
         }
38 38
     }
39 39
 
@@ -43,7 +43,7 @@  discard block
 block discarded – undo
43 43
      */
44 44
     protected function _extend_page_config()
45 45
     {
46
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
46
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'registrations';
47 47
         $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
48 48
             ? $this->_req_data['_REG_ID']
49 49
             : 0;
@@ -180,14 +180,14 @@  discard block
 block discarded – undo
180 180
             // enqueue newsletter js
181 181
             wp_enqueue_script(
182 182
                 'ee-newsletter-trigger',
183
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
183
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.js',
184 184
                 array('ee-dialog'),
185 185
                 EVENT_ESPRESSO_VERSION,
186 186
                 true
187 187
             );
188 188
             wp_enqueue_style(
189 189
                 'ee-newsletter-trigger-css',
190
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
190
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.css',
191 191
                 array(),
192 192
                 EVENT_ESPRESSO_VERSION
193 193
             );
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
     {
209 209
         wp_register_script(
210 210
             'ee-reg-reports-js',
211
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
211
+            REG_CAF_ASSETS_URL.'ee-registration-admin-reports.js',
212 212
             array('google-charts'),
213 213
             EVENT_ESPRESSO_VERSION,
214 214
             true
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
         $nonce_ref = 'get_newsletter_form_content_nonce';
295 295
         $this->_verify_nonce($nonce, $nonce_ref);
296 296
         // let's get the mtp for the incoming MTP_ ID
297
-        if (! isset($this->_req_data['GRP_ID'])) {
297
+        if ( ! isset($this->_req_data['GRP_ID'])) {
298 298
             EE_Error::add_error(
299 299
                 esc_html__(
300 300
                     'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
             $this->_return_json();
310 310
         }
311 311
         $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
312
-        if (! $MTPG instanceof EE_Message_Template_Group) {
312
+        if ( ! $MTPG instanceof EE_Message_Template_Group) {
313 313
             EE_Error::add_error(
314 314
                 sprintf(
315 315
                     esc_html__(
@@ -334,12 +334,12 @@  discard block
 block discarded – undo
334 334
             $field = $MTP->get('MTP_template_field');
335 335
             if ($field === 'content') {
336 336
                 $content = $MTP->get('MTP_content');
337
-                if (! empty($content['newsletter_content'])) {
337
+                if ( ! empty($content['newsletter_content'])) {
338 338
                     $template_fields['newsletter_content'] = $content['newsletter_content'];
339 339
                 }
340 340
                 continue;
341 341
             }
342
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
342
+            $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
343 343
         }
344 344
         $this->_template_args['success'] = true;
345 345
         $this->_template_args['error'] = false;
@@ -441,17 +441,17 @@  discard block
 block discarded – undo
441 441
                 $field_id = $field === '[NEWSLETTER_CONTENT]'
442 442
                     ? 'content'
443 443
                     : $field;
444
-                $field_id = 'batch-message-' . strtolower($field_id);
444
+                $field_id = 'batch-message-'.strtolower($field_id);
445 445
                 $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
446 446
                                           . $shortcode
447
-                                          . '" data-linked-input-id="' . $field_id . '">'
447
+                                          . '" data-linked-input-id="'.$field_id.'">'
448 448
                                           . $shortcode
449 449
                                           . '</span>';
450 450
             }
451
-            $codes[ $field ] = implode(', ', $available_shortcodes);
451
+            $codes[$field] = implode(', ', $available_shortcodes);
452 452
         }
453 453
         $shortcodes = $codes;
454
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
454
+        $form_template = REG_CAF_TEMPLATE_PATH.'newsletter-send-form.template.php';
455 455
         $form_template_args = array(
456 456
             'form_action'       => admin_url('admin.php?page=espresso_registrations'),
457 457
             'form_route'        => 'newsletter_selected_send',
@@ -619,7 +619,7 @@  discard block
 block discarded – undo
619 619
      */
620 620
     protected function _registration_reports()
621 621
     {
622
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
622
+        $template_path = EE_ADMIN_TEMPLATE.'admin_reports.template.php';
623 623
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
624 624
             $template_path,
625 625
             $this->_reports_template_data,
@@ -674,7 +674,7 @@  discard block
 block discarded – undo
674 674
             array_unshift($regs, $column_titles);
675 675
             // setup the date range.
676 676
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
677
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
677
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
678 678
             $ending_date = new DateTime("now", $DateTimeZone);
679 679
             $subtitle = sprintf(
680 680
                 wp_strip_all_tags(
@@ -698,7 +698,7 @@  discard block
 block discarded – undo
698 698
                         'event_espresso'
699 699
                     )
700 700
                 ),
701
-                '<h2>' . $report_title . '</h2><p>',
701
+                '<h2>'.$report_title.'</h2><p>',
702 702
                 '</p>'
703 703
             ),
704 704
         );
@@ -751,7 +751,7 @@  discard block
 block discarded – undo
751 751
             array_unshift($regs, $column_titles);
752 752
             // setup the date range.
753 753
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
754
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
754
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
755 755
             $ending_date = new DateTime("now", $DateTimeZone);
756 756
             $subtitle = sprintf(
757 757
                 wp_strip_all_tags(
@@ -775,7 +775,7 @@  discard block
 block discarded – undo
775 775
                         'event_espresso'
776 776
                     )
777 777
                 ),
778
-                '<h2>' . $report_title . '</h2><p>',
778
+                '<h2>'.$report_title.'</h2><p>',
779 779
                 '</p>'
780 780
             ),
781 781
         );
@@ -801,7 +801,7 @@  discard block
 block discarded – undo
801 801
         $reg_id = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : null;
802 802
         /** @var EE_Registration $registration */
803 803
         $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
804
-        if (! $registration instanceof EE_Registration) {
804
+        if ( ! $registration instanceof EE_Registration) {
805 805
             throw new EE_Error(
806 806
                 sprintf(
807 807
                     esc_html__('An error occurred. There is no registration with ID (%d)', 'event_espresso'),
@@ -836,7 +836,7 @@  discard block
 block discarded – undo
836 836
         if ($datetime instanceof EE_Datetime) {
837 837
             $datetime_label = $datetime->get_dtt_display_name(true);
838 838
             $datetime_label .= ! empty($datetime_label)
839
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
839
+                ? ' ('.$datetime->get_dtt_display_name().')'
840 840
                 : $datetime->get_dtt_display_name();
841 841
         }
842 842
         $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
@@ -850,7 +850,7 @@  discard block
 block discarded – undo
850 850
             )
851 851
             : '';
852 852
         $datetime_link = ! empty($datetime_link)
853
-            ? '<a href="' . $datetime_link . '">'
853
+            ? '<a href="'.$datetime_link.'">'
854 854
               . '<span id="checkin-dtt">'
855 855
               . $datetime_label
856 856
               . '</span></a>'
@@ -862,8 +862,8 @@  discard block
 block discarded – undo
862 862
             ? $attendee->get_admin_details_link()
863 863
             : '';
864 864
         $attendee_link = ! empty($attendee_link)
865
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
866
-              . ' aria-label="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
865
+            ? '<a href="'.$attendee->get_admin_details_link().'"'
866
+              . ' aria-label="'.esc_html__('Click for attendee details', 'event_espresso').'">'
867 867
               . '<span id="checkin-attendee-name">'
868 868
               . $attendee_name
869 869
               . '</span></a>'
@@ -872,25 +872,25 @@  discard block
 block discarded – undo
872 872
             ? $registration->event()->get_admin_details_link()
873 873
             : '';
874 874
         $event_link = ! empty($event_link)
875
-            ? '<a href="' . $event_link . '"'
876
-              . ' aria-label="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
875
+            ? '<a href="'.$event_link.'"'
876
+              . ' aria-label="'.esc_html__('Click here to edit event.', 'event_espresso').'">'
877 877
               . '<span id="checkin-event-name">'
878 878
               . $registration->event_name()
879 879
               . '</span>'
880 880
               . '</a>'
881 881
             : '';
882 882
         $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
883
-            ? '<h2>' . sprintf(
883
+            ? '<h2>'.sprintf(
884 884
                 esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
885 885
                 $attendee_link,
886 886
                 $datetime_link,
887 887
                 $event_link
888
-            ) . '</h2>'
888
+            ).'</h2>'
889 889
             : '';
890 890
         $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
891
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
891
+            ? '<input type="hidden" name="_REG_ID" value="'.$reg_id.'">' : '';
892 892
         $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
893
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
893
+            ? '<input type="hidden" name="DTT_ID" value="'.$dtt_id.'">' : '';
894 894
         $this->display_admin_list_table_page_with_no_sidebar();
895 895
     }
896 896
 
@@ -907,7 +907,7 @@  discard block
 block discarded – undo
907 907
     public function toggle_checkin_status()
908 908
     {
909 909
         // first make sure we have the necessary data
910
-        if (! isset($this->_req_data['_regid'])) {
910
+        if ( ! isset($this->_req_data['_regid'])) {
911 911
             EE_Error::add_error(
912 912
                 esc_html__(
913 913
                     'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
         // beautiful! Made it this far so let's get the status.
930 930
         $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
931 931
         // setup new class to return via ajax
932
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
932
+        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin '.$new_status->cssClasses();
933 933
         $this->_template_args['success'] = true;
934 934
         $this->_return_json();
935 935
     }
@@ -955,7 +955,7 @@  discard block
 block discarded – undo
955 955
         );
956 956
         $new_status = false;
957 957
         // bulk action check in toggle
958
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
958
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
959 959
             // cycle thru checkboxes
960 960
             $checkboxes = $this->_req_data['checkbox'];
961 961
             foreach (array_keys($checkboxes) as $REG_ID) {
@@ -1026,10 +1026,10 @@  discard block
 block discarded – undo
1026 1026
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1027 1027
         );
1028 1028
         $errors = 0;
1029
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1029
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1030 1030
             $checkboxes = $this->_req_data['checkbox'];
1031 1031
             foreach (array_keys($checkboxes) as $CHK_ID) {
1032
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1032
+                if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1033 1033
                     $errors++;
1034 1034
                 }
1035 1035
             }
@@ -1075,8 +1075,8 @@  discard block
 block discarded – undo
1075 1075
             'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1076 1076
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1077 1077
         );
1078
-        if (! empty($this->_req_data['CHK_ID'])) {
1079
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1078
+        if ( ! empty($this->_req_data['CHK_ID'])) {
1079
+            if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1080 1080
                 EE_Error::add_error(
1081 1081
                     esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1082 1082
                     __FILE__,
@@ -1145,27 +1145,27 @@  discard block
 block discarded – undo
1145 1145
                 'desc'  => $checked_never->legendLabel(),
1146 1146
             ),
1147 1147
             'approved_status'  => array(
1148
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1148
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
1149 1149
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1150 1150
             ),
1151 1151
             'cancelled_status' => array(
1152
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1152
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1153 1153
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1154 1154
             ),
1155 1155
             'declined_status'  => array(
1156
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1156
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
1157 1157
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1158 1158
             ),
1159 1159
             'not_approved'     => array(
1160
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1160
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
1161 1161
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1162 1162
             ),
1163 1163
             'pending_status'   => array(
1164
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1164
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
1165 1165
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1166 1166
             ),
1167 1167
             'wait_list'        => array(
1168
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1168
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
1169 1169
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1170 1170
             ),
1171 1171
         );
@@ -1174,10 +1174,10 @@  discard block
 block discarded – undo
1174 1174
         /** @var EE_Event $event */
1175 1175
         $event = EEM_Event::instance()->get_one_by_ID($event_id);
1176 1176
         $this->_template_args['before_list_table'] = $event instanceof EE_Event
1177
-            ? '<h2>' . sprintf(
1177
+            ? '<h2>'.sprintf(
1178 1178
                 esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1179 1179
                 EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1180
-            ) . '</h2>'
1180
+            ).'</h2>'
1181 1181
             : '';
1182 1182
         // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1183 1183
         // the event.
@@ -1195,12 +1195,12 @@  discard block
 block discarded – undo
1195 1195
             $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1196 1196
             $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1197 1197
             $this->_template_args['before_list_table'] .= $datetime->name();
1198
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1198
+            $this->_template_args['before_list_table'] .= ' ( '.$datetime->date_and_time_range().' )';
1199 1199
             $this->_template_args['before_list_table'] .= '</span></h2>';
1200 1200
         }
1201 1201
         // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1202 1202
         // column represents
1203
-        if (! $datetime instanceof EE_Datetime) {
1203
+        if ( ! $datetime instanceof EE_Datetime) {
1204 1204
             $this->_template_args['before_list_table'] .= '<br><p class="description">'
1205 1205
                                                           . esc_html__(
1206 1206
                                                               'In this view, the check-in status represents the latest check-in record for the registration in that row.',
Please login to merge, or discard this patch.
admin/extend/registration_form/Extend_Registration_Form_Admin_Page.core.php 2 patches
Indentation   +1440 added lines, -1440 removed lines patch added patch discarded remove patch
@@ -14,1444 +14,1444 @@
 block discarded – undo
14 14
  */
15 15
 class Extend_Registration_Form_Admin_Page extends Registration_Form_Admin_Page
16 16
 {
17
-    /**
18
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
19
-     */
20
-    public function __construct($routing = true)
21
-    {
22
-        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form/');
23
-        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets/');
24
-        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
25
-        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates/');
26
-        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
27
-        parent::__construct($routing);
28
-    }
29
-
30
-
31
-    /**
32
-     * @return void
33
-     */
34
-    protected function _extend_page_config()
35
-    {
36
-        $this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
37
-        $qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
38
-            ? $this->_req_data['QST_ID'] : 0;
39
-        $qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
40
-            ? $this->_req_data['QSG_ID'] : 0;
41
-
42
-        $new_page_routes = array(
43
-            'question_groups'    => array(
44
-                'func'       => '_question_groups_overview_list_table',
45
-                'capability' => 'ee_read_question_groups',
46
-            ),
47
-            'add_question'       => array(
48
-                'func'       => '_edit_question',
49
-                'capability' => 'ee_edit_questions',
50
-            ),
51
-            'insert_question'    => array(
52
-                'func'       => '_insert_or_update_question',
53
-                'args'       => array('new_question' => true),
54
-                'capability' => 'ee_edit_questions',
55
-                'noheader'   => true,
56
-            ),
57
-            'duplicate_question' => array(
58
-                'func'       => '_duplicate_question',
59
-                'capability' => 'ee_edit_questions',
60
-                'noheader'   => true,
61
-            ),
62
-            'trash_question'     => array(
63
-                'func'       => '_trash_question',
64
-                'capability' => 'ee_delete_question',
65
-                'obj_id'     => $qst_id,
66
-                'noheader'   => true,
67
-            ),
68
-
69
-            'restore_question' => array(
70
-                'func'       => '_trash_or_restore_questions',
71
-                'capability' => 'ee_delete_question',
72
-                'obj_id'     => $qst_id,
73
-                'args'       => array('trash' => false),
74
-                'noheader'   => true,
75
-            ),
76
-
77
-            'delete_question' => array(
78
-                'func'       => '_delete_question',
79
-                'capability' => 'ee_delete_question',
80
-                'obj_id'     => $qst_id,
81
-                'noheader'   => true,
82
-            ),
83
-
84
-            'trash_questions' => array(
85
-                'func'       => '_trash_or_restore_questions',
86
-                'capability' => 'ee_delete_questions',
87
-                'args'       => array('trash' => true),
88
-                'noheader'   => true,
89
-            ),
90
-
91
-            'restore_questions' => array(
92
-                'func'       => '_trash_or_restore_questions',
93
-                'capability' => 'ee_delete_questions',
94
-                'args'       => array('trash' => false),
95
-                'noheader'   => true,
96
-            ),
97
-
98
-            'delete_questions' => array(
99
-                'func'       => '_delete_questions',
100
-                'args'       => array(),
101
-                'capability' => 'ee_delete_questions',
102
-                'noheader'   => true,
103
-            ),
104
-
105
-            'add_question_group' => array(
106
-                'func'       => '_edit_question_group',
107
-                'capability' => 'ee_edit_question_groups',
108
-            ),
109
-
110
-            'edit_question_group' => array(
111
-                'func'       => '_edit_question_group',
112
-                'capability' => 'ee_edit_question_group',
113
-                'obj_id'     => $qsg_id,
114
-                'args'       => array('edit'),
115
-            ),
116
-
117
-            'delete_question_groups' => array(
118
-                'func'       => '_delete_question_groups',
119
-                'capability' => 'ee_delete_question_groups',
120
-                'noheader'   => true,
121
-            ),
122
-
123
-            'delete_question_group' => array(
124
-                'func'       => '_delete_question_groups',
125
-                'capability' => 'ee_delete_question_group',
126
-                'obj_id'     => $qsg_id,
127
-                'noheader'   => true,
128
-            ),
129
-
130
-            'trash_question_group' => array(
131
-                'func'       => '_trash_or_restore_question_groups',
132
-                'args'       => array('trash' => true),
133
-                'capability' => 'ee_delete_question_group',
134
-                'obj_id'     => $qsg_id,
135
-                'noheader'   => true,
136
-            ),
137
-
138
-            'restore_question_group' => array(
139
-                'func'       => '_trash_or_restore_question_groups',
140
-                'args'       => array('trash' => false),
141
-                'capability' => 'ee_delete_question_group',
142
-                'obj_id'     => $qsg_id,
143
-                'noheader'   => true,
144
-            ),
145
-
146
-            'insert_question_group' => array(
147
-                'func'       => '_insert_or_update_question_group',
148
-                'args'       => array('new_question_group' => true),
149
-                'capability' => 'ee_edit_question_groups',
150
-                'noheader'   => true,
151
-            ),
152
-
153
-            'update_question_group' => array(
154
-                'func'       => '_insert_or_update_question_group',
155
-                'args'       => array('new_question_group' => false),
156
-                'capability' => 'ee_edit_question_group',
157
-                'obj_id'     => $qsg_id,
158
-                'noheader'   => true,
159
-            ),
160
-
161
-            'trash_question_groups' => array(
162
-                'func'       => '_trash_or_restore_question_groups',
163
-                'args'       => array('trash' => true),
164
-                'capability' => 'ee_delete_question_groups',
165
-                'noheader'   => array('trash' => false),
166
-            ),
167
-
168
-            'restore_question_groups' => array(
169
-                'func'       => '_trash_or_restore_question_groups',
170
-                'args'       => array('trash' => false),
171
-                'capability' => 'ee_delete_question_groups',
172
-                'noheader'   => true,
173
-            ),
174
-
175
-
176
-            'espresso_update_question_group_order' => array(
177
-                'func'       => 'update_question_group_order',
178
-                'capability' => 'ee_edit_question_groups',
179
-                'noheader'   => true,
180
-            ),
181
-
182
-            'view_reg_form_settings' => array(
183
-                'func'       => '_reg_form_settings',
184
-                'capability' => 'manage_options',
185
-            ),
186
-
187
-            'update_reg_form_settings' => array(
188
-                'func'       => '_update_reg_form_settings',
189
-                'capability' => 'manage_options',
190
-                'noheader'   => true,
191
-            ),
192
-        );
193
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
194
-
195
-        $new_page_config = array(
196
-
197
-            'question_groups' => array(
198
-                'nav'           => array(
199
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
200
-                    'order' => 20,
201
-                ),
202
-                'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
203
-                'help_tabs'     => array(
204
-                    'registration_form_question_groups_help_tab'                           => array(
205
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
206
-                        'filename' => 'registration_form_question_groups',
207
-                    ),
208
-                    'registration_form_question_groups_table_column_headings_help_tab'     => array(
209
-                        'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
210
-                        'filename' => 'registration_form_question_groups_table_column_headings',
211
-                    ),
212
-                    'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
213
-                        'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
214
-                        'filename' => 'registration_form_question_groups_views_bulk_actions_search',
215
-                    ),
216
-                ),
217
-                'metaboxes'     => $this->_default_espresso_metaboxes,
218
-                'require_nonce' => false,
219
-                'qtips'         => array(
220
-                    'EE_Registration_Form_Tips',
221
-                ),
222
-            ),
223
-
224
-            'add_question' => array(
225
-                'nav'           => array(
226
-                    'label'      => esc_html__('Add Question', 'event_espresso'),
227
-                    'order'      => 5,
228
-                    'persistent' => false,
229
-                ),
230
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
231
-                'help_tabs'     => array(
232
-                    'registration_form_add_question_help_tab' => array(
233
-                        'title'    => esc_html__('Add Question', 'event_espresso'),
234
-                        'filename' => 'registration_form_add_question',
235
-                    ),
236
-                ),
237
-                'require_nonce' => false,
238
-            ),
239
-
240
-            'add_question_group' => array(
241
-                'nav'           => array(
242
-                    'label'      => esc_html__('Add Question Group', 'event_espresso'),
243
-                    'order'      => 5,
244
-                    'persistent' => false,
245
-                ),
246
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
247
-                'help_tabs'     => array(
248
-                    'registration_form_add_question_group_help_tab' => array(
249
-                        'title'    => esc_html__('Add Question Group', 'event_espresso'),
250
-                        'filename' => 'registration_form_add_question_group',
251
-                    ),
252
-                ),
253
-                'require_nonce' => false,
254
-            ),
255
-
256
-            'edit_question_group' => array(
257
-                'nav'           => array(
258
-                    'label'      => esc_html__('Edit Question Group', 'event_espresso'),
259
-                    'order'      => 5,
260
-                    'persistent' => false,
261
-                    'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
262
-                        array('question_group_id' => $this->_req_data['question_group_id']),
263
-                        $this->_current_page_view_url
264
-                    ) : $this->_admin_base_url,
265
-                ),
266
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
267
-                'help_tabs'     => array(
268
-                    'registration_form_edit_question_group_help_tab' => array(
269
-                        'title'    => esc_html__('Edit Question Group', 'event_espresso'),
270
-                        'filename' => 'registration_form_edit_question_group',
271
-                    ),
272
-                ),
273
-                'require_nonce' => false,
274
-            ),
275
-
276
-            'view_reg_form_settings' => array(
277
-                'nav'           => array(
278
-                    'label' => esc_html__('Reg Form Settings', 'event_espresso'),
279
-                    'order' => 40,
280
-                ),
281
-                'labels'        => array(
282
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
283
-                ),
284
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
285
-                'help_tabs'     => array(
286
-                    'registration_form_reg_form_settings_help_tab' => array(
287
-                        'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
288
-                        'filename' => 'registration_form_reg_form_settings',
289
-                    ),
290
-                ),
291
-                'require_nonce' => false,
292
-            ),
293
-
294
-        );
295
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
296
-
297
-        // change the list table we're going to use so it's the NEW list table!
298
-        $this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
299
-
300
-
301
-        // additional labels
302
-        $new_labels = array(
303
-            'add_question'          => esc_html__('Add New Question', 'event_espresso'),
304
-            'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
305
-            'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
306
-            'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
307
-            'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
308
-        );
309
-        $this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
310
-    }
311
-
312
-
313
-    /**
314
-     * @return void
315
-     */
316
-    protected function _ajax_hooks()
317
-    {
318
-        add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
319
-    }
320
-
321
-
322
-    /**
323
-     * @return void
324
-     */
325
-    public function load_scripts_styles_question_groups()
326
-    {
327
-        wp_enqueue_script('espresso_ajax_table_sorting');
328
-    }
329
-
330
-
331
-    /**
332
-     * @return void
333
-     */
334
-    public function load_scripts_styles_add_question_group()
335
-    {
336
-        $this->load_scripts_styles_forms();
337
-        $this->load_sortable_question_script();
338
-    }
339
-
340
-
341
-    /**
342
-     * @return void
343
-     */
344
-    public function load_scripts_styles_edit_question_group()
345
-    {
346
-        $this->load_scripts_styles_forms();
347
-        $this->load_sortable_question_script();
348
-    }
349
-
350
-
351
-    /**
352
-     * registers and enqueues script for questions
353
-     *
354
-     * @return void
355
-     */
356
-    public function load_sortable_question_script()
357
-    {
358
-        wp_register_script(
359
-            'ee-question-sortable',
360
-            REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
361
-            array('jquery-ui-sortable'),
362
-            EVENT_ESPRESSO_VERSION,
363
-            true
364
-        );
365
-        wp_enqueue_script('ee-question-sortable');
366
-    }
367
-
368
-
369
-    /**
370
-     * @return void
371
-     */
372
-    protected function _set_list_table_views_default()
373
-    {
374
-        $this->_views = array(
375
-            'all' => array(
376
-                'slug'        => 'all',
377
-                'label'       => esc_html__('View All Questions', 'event_espresso'),
378
-                'count'       => 0,
379
-                'bulk_action' => array(
380
-                    'trash_questions' => esc_html__('Trash', 'event_espresso'),
381
-                ),
382
-            ),
383
-        );
384
-
385
-        if (
386
-            EE_Registry::instance()->CAP->current_user_can(
387
-                'ee_delete_questions',
388
-                'espresso_registration_form_trash_questions'
389
-            )
390
-        ) {
391
-            $this->_views['trash'] = array(
392
-                'slug'        => 'trash',
393
-                'label'       => esc_html__('Trash', 'event_espresso'),
394
-                'count'       => 0,
395
-                'bulk_action' => array(
396
-                    'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
397
-                    'restore_questions' => esc_html__('Restore', 'event_espresso'),
398
-                ),
399
-            );
400
-        }
401
-    }
402
-
403
-
404
-    /**
405
-     * @return void
406
-     */
407
-    protected function _set_list_table_views_question_groups()
408
-    {
409
-        $this->_views = array(
410
-            'all' => array(
411
-                'slug'        => 'all',
412
-                'label'       => esc_html__('All', 'event_espresso'),
413
-                'count'       => 0,
414
-                'bulk_action' => array(
415
-                    'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
416
-                ),
417
-            ),
418
-        );
419
-
420
-        if (
421
-            EE_Registry::instance()->CAP->current_user_can(
422
-                'ee_delete_question_groups',
423
-                'espresso_registration_form_trash_question_groups'
424
-            )
425
-        ) {
426
-            $this->_views['trash'] = array(
427
-                'slug'        => 'trash',
428
-                'label'       => esc_html__('Trash', 'event_espresso'),
429
-                'count'       => 0,
430
-                'bulk_action' => array(
431
-                    'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
432
-                    'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
433
-                ),
434
-            );
435
-        }
436
-    }
437
-
438
-
439
-    /**
440
-     * @return void
441
-     * @throws EE_Error
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     */
446
-    protected function _questions_overview_list_table()
447
-    {
448
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
449
-            'add_question',
450
-            'add_question',
451
-            array(),
452
-            'add-new-h2'
453
-        );
454
-        parent::_questions_overview_list_table();
455
-    }
456
-
457
-
458
-    /**
459
-     * @return void
460
-     * @throws DomainException
461
-     * @throws EE_Error
462
-     * @throws InvalidArgumentException
463
-     * @throws InvalidDataTypeException
464
-     * @throws InvalidInterfaceException
465
-     */
466
-    protected function _question_groups_overview_list_table()
467
-    {
468
-        $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
469
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
470
-            'add_question_group',
471
-            'add_question_group',
472
-            array(),
473
-            'add-new-h2'
474
-        );
475
-        $this->display_admin_list_table_page_with_sidebar();
476
-    }
477
-
478
-
479
-    /**
480
-     * @return void
481
-     * @throws EE_Error
482
-     * @throws InvalidArgumentException
483
-     * @throws InvalidDataTypeException
484
-     * @throws InvalidInterfaceException
485
-     */
486
-    protected function _delete_question()
487
-    {
488
-        $success = $this->_delete_items($this->_question_model);
489
-        $this->_redirect_after_action(
490
-            $success,
491
-            $this->_question_model->item_name($success),
492
-            'deleted',
493
-            array('action' => 'default', 'status' => 'all')
494
-        );
495
-    }
496
-
497
-
498
-    /**
499
-     * @return void
500
-     * @throws EE_Error
501
-     * @throws InvalidArgumentException
502
-     * @throws InvalidDataTypeException
503
-     * @throws InvalidInterfaceException
504
-     */
505
-    protected function _delete_questions()
506
-    {
507
-        $success = $this->_delete_items($this->_question_model);
508
-        $this->_redirect_after_action(
509
-            $success,
510
-            $this->_question_model->item_name($success),
511
-            'deleted permanently',
512
-            array('action' => 'default', 'status' => 'trash')
513
-        );
514
-    }
515
-
516
-
517
-    /**
518
-     * Performs the deletion of a single or multiple questions or question groups.
519
-     *
520
-     * @param EEM_Soft_Delete_Base $model
521
-     * @return int number of items deleted permanently
522
-     * @throws EE_Error
523
-     * @throws InvalidArgumentException
524
-     * @throws InvalidDataTypeException
525
-     * @throws InvalidInterfaceException
526
-     */
527
-    private function _delete_items(EEM_Soft_Delete_Base $model)
528
-    {
529
-        $success = 0;
530
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
531
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
532
-            // if array has more than one element than success message should be plural
533
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
534
-            // cycle thru bulk action checkboxes
535
-            $checkboxes = $this->_req_data['checkbox'];
536
-            foreach (array_keys($checkboxes) as $ID) {
537
-                if (! $this->_delete_item($ID, $model)) {
538
-                    $success = 0;
539
-                }
540
-            }
541
-        } elseif (! empty($this->_req_data['QSG_ID'])) {
542
-            $success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
543
-        } elseif (! empty($this->_req_data['QST_ID'])) {
544
-            $success = $this->_delete_item($this->_req_data['QST_ID'], $model);
545
-        } else {
546
-            EE_Error::add_error(
547
-                sprintf(
548
-                    esc_html__(
549
-                        "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.",
550
-                        "event_espresso"
551
-                    )
552
-                ),
553
-                __FILE__,
554
-                __FUNCTION__,
555
-                __LINE__
556
-            );
557
-        }
558
-        return $success;
559
-    }
560
-
561
-
562
-    /**
563
-     * Deletes the specified question (and its associated question options) or question group
564
-     *
565
-     * @param int                  $id
566
-     * @param EEM_Soft_Delete_Base $model
567
-     * @return boolean
568
-     * @throws EE_Error
569
-     * @throws InvalidArgumentException
570
-     * @throws InvalidDataTypeException
571
-     * @throws InvalidInterfaceException
572
-     */
573
-    protected function _delete_item($id, $model)
574
-    {
575
-        if ($model instanceof EEM_Question) {
576
-            EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
577
-        }
578
-        return $model->delete_permanently_by_ID(absint($id));
579
-    }
580
-
581
-
582
-    /******************************    QUESTION GROUPS    ******************************/
583
-
584
-
585
-    /**
586
-     * @param string $type
587
-     * @return void
588
-     * @throws DomainException
589
-     * @throws EE_Error
590
-     * @throws InvalidArgumentException
591
-     * @throws InvalidDataTypeException
592
-     * @throws InvalidInterfaceException
593
-     */
594
-    protected function _edit_question_group($type = 'add')
595
-    {
596
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
597
-        $ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID'])
598
-            ? absint($this->_req_data['QSG_ID'])
599
-            : false;
600
-
601
-        switch ($this->_req_action) {
602
-            case 'add_question_group':
603
-                $this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
604
-                break;
605
-            case 'edit_question_group':
606
-                $this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
607
-                break;
608
-            default:
609
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
610
-        }
611
-        // add ID to title if editing
612
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
613
-        if ($ID) {
614
-            /** @var EE_Question_Group $questionGroup */
615
-            $questionGroup = $this->_question_group_model->get_one_by_ID($ID);
616
-            $additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
617
-            $this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
618
-        } else {
619
-            /** @var EE_Question_Group $questionGroup */
620
-            $questionGroup = EEM_Question_Group::instance()->create_default_object();
621
-            $questionGroup->set_order_to_latest();
622
-            $this->_set_add_edit_form_tags('insert_question_group');
623
-        }
624
-        $this->_template_args['values'] = $this->_yes_no_values;
625
-        $this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
626
-        $this->_template_args['QSG_ID'] = $ID ? $ID : true;
627
-        $this->_template_args['question_group'] = $questionGroup;
628
-
629
-        $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
630
-        $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
631
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
632
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
633
-            $this->_template_args,
634
-            true
635
-        );
636
-
637
-        // the details template wrapper
638
-        $this->display_admin_page_with_sidebar();
639
-    }
640
-
641
-
642
-    /**
643
-     * @return void
644
-     * @throws EE_Error
645
-     * @throws InvalidArgumentException
646
-     * @throws InvalidDataTypeException
647
-     * @throws InvalidInterfaceException
648
-     */
649
-    protected function _delete_question_groups()
650
-    {
651
-        $success = $this->_delete_items($this->_question_group_model);
652
-        $this->_redirect_after_action(
653
-            $success,
654
-            $this->_question_group_model->item_name($success),
655
-            'deleted permanently',
656
-            array('action' => 'question_groups', 'status' => 'trash')
657
-        );
658
-    }
659
-
660
-
661
-    /**
662
-     * @param bool $new_question_group
663
-     * @throws EE_Error
664
-     * @throws InvalidArgumentException
665
-     * @throws InvalidDataTypeException
666
-     * @throws InvalidInterfaceException
667
-     */
668
-    protected function _insert_or_update_question_group($new_question_group = true)
669
-    {
670
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
671
-        $set_column_values = $this->_set_column_values_for($this->_question_group_model);
672
-
673
-        // make sure identifier is unique
674
-        $identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : '';
675
-        $where_values = ['QSG_identifier' => $set_column_values['QSG_identifier']];
676
-        if (! $new_question_group && isset($set_column_values['QSG_ID'])) {
677
-            $where_values['QSG_ID'] = ['!=', $set_column_values['QSG_ID']];
678
-        }
679
-        $identifier_exists = ! empty($identifier_value)
680
-            ? $this->_question_group_model->count([$where_values]) > 0
681
-            : false;
682
-        if ($identifier_exists) {
683
-            $set_column_values['QSG_identifier'] .= uniqid('id', true);
684
-        }
685
-
686
-        if ($new_question_group) {
687
-            $QSG_ID = $this->_question_group_model->insert($set_column_values);
688
-            $success = $QSG_ID ? 1 : 0;
689
-            if ($success === 0) {
690
-                EE_Error::add_error(
691
-                    esc_html__('Something went wrong saving the question group.', 'event_espresso'),
692
-                    __FILE__,
693
-                    __FUNCTION__,
694
-                    __LINE__
695
-                );
696
-                $this->_redirect_after_action(
697
-                    false,
698
-                    '',
699
-                    '',
700
-                    array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
701
-                    true
702
-                );
703
-            }
704
-        } else {
705
-            $QSG_ID = absint($this->_req_data['QSG_ID']);
706
-            unset($set_column_values['QSG_ID']);
707
-            $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
708
-        }
709
-
710
-        $phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
711
-            EEM_Attendee::system_question_phone
712
-        );
713
-        // update the existing related questions
714
-        // BUT FIRST...  delete the phone question from the Question_Group_Question
715
-        // if it is being added to this question group (therefore removed from the existing group)
716
-        if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
717
-            // delete where QST ID = system phone question ID and Question Group ID is NOT this group
718
-            EEM_Question_Group_Question::instance()->delete(
719
-                array(
720
-                    array(
721
-                        'QST_ID' => $phone_question_id,
722
-                        'QSG_ID' => array('!=', $QSG_ID),
723
-                    ),
724
-                )
725
-            );
726
-        }
727
-        /** @type EE_Question_Group $question_group */
728
-        $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
729
-        $questions = $question_group->questions();
730
-        // make sure system phone question is added to list of questions for this group
731
-        if (! isset($questions[ $phone_question_id ])) {
732
-            $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
733
-        }
734
-
735
-        foreach ($questions as $question_ID => $question) {
736
-            // first we always check for order.
737
-            if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
738
-                // update question order
739
-                $question_group->update_question_order(
740
-                    $question_ID,
741
-                    $this->_req_data['question_orders'][ $question_ID ]
742
-                );
743
-            }
744
-
745
-            // then we always check if adding or removing.
746
-            if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
747
-                $question_group->add_question($question_ID);
748
-            } else {
749
-                // not found, remove it (but only if not a system question for the personal group
750
-                // with the exception of lname system question - we allow removal of it)
751
-                if (
752
-                    in_array(
753
-                        $question->system_ID(),
754
-                        EEM_Question::instance()->required_system_questions_in_system_question_group(
755
-                            $question_group->system_group()
756
-                        )
757
-                    )
758
-                ) {
759
-                    continue;
760
-                } else {
761
-                    $question_group->remove_question($question_ID);
762
-                }
763
-            }
764
-        }
765
-        // save new related questions
766
-        if (isset($this->_req_data['questions'])) {
767
-            foreach ($this->_req_data['questions'] as $QST_ID) {
768
-                $question_group->add_question($QST_ID);
769
-                if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
770
-                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
771
-                }
772
-            }
773
-        }
774
-
775
-        if ($success !== false) {
776
-            $msg = $new_question_group
777
-                ? sprintf(
778
-                    esc_html__('The %s has been created', 'event_espresso'),
779
-                    $this->_question_group_model->item_name()
780
-                )
781
-                : sprintf(
782
-                    esc_html__(
783
-                        'The %s has been updated',
784
-                        'event_espresso'
785
-                    ),
786
-                    $this->_question_group_model->item_name()
787
-                );
788
-            EE_Error::add_success($msg);
789
-        }
790
-        $this->_redirect_after_action(
791
-            false,
792
-            '',
793
-            '',
794
-            array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
795
-            true
796
-        );
797
-    }
798
-
799
-
800
-    /**
801
-     * duplicates a question and all its question options and redirects to the new question.
802
-     *
803
-     * @return void
804
-     * @throws EE_Error
805
-     * @throws InvalidArgumentException
806
-     * @throws ReflectionException
807
-     * @throws InvalidDataTypeException
808
-     * @throws InvalidInterfaceException
809
-     */
810
-    public function _duplicate_question()
811
-    {
812
-        $question_ID = (int) $this->_req_data['QST_ID'];
813
-        $question = EEM_Question::instance()->get_one_by_ID($question_ID);
814
-        if ($question instanceof EE_Question) {
815
-            $new_question = $question->duplicate();
816
-            if ($new_question instanceof EE_Question) {
817
-                $this->_redirect_after_action(
818
-                    true,
819
-                    esc_html__('Question', 'event_espresso'),
820
-                    esc_html__('Duplicated', 'event_espresso'),
821
-                    array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
822
-                    true
823
-                );
824
-            } else {
825
-                global $wpdb;
826
-                EE_Error::add_error(
827
-                    sprintf(
828
-                        esc_html__(
829
-                            'Could not duplicate question with ID %1$d because: %2$s',
830
-                            'event_espresso'
831
-                        ),
832
-                        $question_ID,
833
-                        $wpdb->last_error
834
-                    ),
835
-                    __FILE__,
836
-                    __FUNCTION__,
837
-                    __LINE__
838
-                );
839
-                $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
840
-            }
841
-        } else {
842
-            EE_Error::add_error(
843
-                sprintf(
844
-                    esc_html__(
845
-                        'Could not duplicate question with ID %d because it didn\'t exist!',
846
-                        'event_espresso'
847
-                    ),
848
-                    $question_ID
849
-                ),
850
-                __FILE__,
851
-                __FUNCTION__,
852
-                __LINE__
853
-            );
854
-            $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
855
-        }
856
-    }
857
-
858
-
859
-    /**
860
-     * @param bool $trash
861
-     * @throws EE_Error
862
-     */
863
-    protected function _trash_or_restore_question_groups($trash = true)
864
-    {
865
-        $this->_trash_or_restore_items($this->_question_group_model, $trash);
866
-    }
867
-
868
-
869
-    /**
870
-     *_trash_question
871
-     *
872
-     * @return void
873
-     * @throws EE_Error
874
-     */
875
-    protected function _trash_question()
876
-    {
877
-        $success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
878
-        $query_args = array('action' => 'default', 'status' => 'all');
879
-        $this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
880
-    }
881
-
882
-
883
-    /**
884
-     * @param bool $trash
885
-     * @throws EE_Error
886
-     */
887
-    protected function _trash_or_restore_questions($trash = true)
888
-    {
889
-        $this->_trash_or_restore_items($this->_question_model, $trash);
890
-    }
891
-
892
-
893
-    /**
894
-     * Internally used to delete or restore items, using the request data. Meant to be
895
-     * flexible between question or question groups
896
-     *
897
-     * @param EEM_Soft_Delete_Base $model
898
-     * @param boolean              $trash whether to trash or restore
899
-     * @throws EE_Error
900
-     */
901
-    private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
902
-    {
903
-
904
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
905
-
906
-        $success = 1;
907
-        // Checkboxes
908
-        // echo "trash $trash";
909
-        // var_dump($this->_req_data['checkbox']);die;
910
-        if (isset($this->_req_data['checkbox'])) {
911
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
912
-                // if array has more than one element than success message should be plural
913
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
914
-                // cycle thru bulk action checkboxes
915
-                $checkboxes = $this->_req_data['checkbox'];
916
-                foreach (array_keys($checkboxes) as $ID) {
917
-                    if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
918
-                        $success = 0;
919
-                    }
920
-                }
921
-            } else {
922
-                // grab single id and delete
923
-                $ID = absint($this->_req_data['checkbox']);
924
-                if (! $model->delete_or_restore_by_ID($trash, $ID)) {
925
-                    $success = 0;
926
-                }
927
-            }
928
-        } else {
929
-            // delete via trash link
930
-            // grab single id and delete
931
-            $ID = absint($this->_req_data[ $model->primary_key_name() ]);
932
-            if (! $model->delete_or_restore_by_ID($trash, $ID)) {
933
-                $success = 0;
934
-            }
935
-        }
936
-
937
-
938
-        $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
939
-        // echo "action :$action";
940
-        // $action = 'questions' ? 'default' : $action;
941
-        if ($trash) {
942
-            $action_desc = 'trashed';
943
-            $status = 'trash';
944
-        } else {
945
-            $action_desc = 'restored';
946
-            $status = 'all';
947
-        }
948
-        $this->_redirect_after_action(
949
-            $success,
950
-            $model->item_name($success),
951
-            $action_desc,
952
-            array('action' => $action, 'status' => $status)
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * @param            $per_page
959
-     * @param int        $current_page
960
-     * @param bool|false $count
961
-     * @return EE_Soft_Delete_Base_Class[]|int
962
-     * @throws EE_Error
963
-     * @throws InvalidArgumentException
964
-     * @throws InvalidDataTypeException
965
-     * @throws InvalidInterfaceException
966
-     */
967
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
968
-    {
969
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
970
-
971
-        if ($count) {
972
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
973
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
974
-            $results = $this->_question_model->count_deleted($where);
975
-        } else {
976
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
977
-            $results = $this->_question_model->get_all_deleted($query_params);
978
-        }
979
-        return $results;
980
-    }
981
-
982
-
983
-    /**
984
-     * @param            $per_page
985
-     * @param int        $current_page
986
-     * @param bool|false $count
987
-     * @return EE_Soft_Delete_Base_Class[]|int
988
-     * @throws EE_Error
989
-     * @throws InvalidArgumentException
990
-     * @throws InvalidDataTypeException
991
-     * @throws InvalidInterfaceException
992
-     */
993
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
994
-    {
995
-        $questionGroupModel = EEM_Question_Group::instance();
996
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
997
-        if ($count) {
998
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
999
-            $results = $questionGroupModel->count($where);
1000
-        } else {
1001
-            $results = $questionGroupModel->get_all($query_params);
1002
-        }
1003
-        return $results;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * @param      $per_page
1009
-     * @param int  $current_page
1010
-     * @param bool $count
1011
-     * @return EE_Soft_Delete_Base_Class[]|int
1012
-     * @throws EE_Error
1013
-     * @throws InvalidArgumentException
1014
-     * @throws InvalidDataTypeException
1015
-     * @throws InvalidInterfaceException
1016
-     */
1017
-    public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
1018
-    {
1019
-        $questionGroupModel = EEM_Question_Group::instance();
1020
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
1021
-        if ($count) {
1022
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
1023
-            $query_params['limit'] = null;
1024
-            $results = $questionGroupModel->count_deleted($where);
1025
-        } else {
1026
-            $results = $questionGroupModel->get_all_deleted($query_params);
1027
-        }
1028
-        return $results;
1029
-    }
1030
-
1031
-
1032
-    /**
1033
-     * method for performing updates to question order
1034
-     *
1035
-     * @return void results array
1036
-     * @throws EE_Error
1037
-     * @throws InvalidArgumentException
1038
-     * @throws InvalidDataTypeException
1039
-     * @throws InvalidInterfaceException
1040
-     */
1041
-    public function update_question_group_order()
1042
-    {
1043
-
1044
-        $success = esc_html__('Question group order was updated successfully.', 'event_espresso');
1045
-
1046
-        // grab our row IDs
1047
-        $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
1048
-            ? explode(',', rtrim($this->_req_data['row_ids'], ','))
1049
-            : array();
1050
-
1051
-        $perpage = ! empty($this->_req_data['perpage'])
1052
-            ? (int) $this->_req_data['perpage']
1053
-            : null;
1054
-        $curpage = ! empty($this->_req_data['curpage'])
1055
-            ? (int) $this->_req_data['curpage']
1056
-            : null;
1057
-
1058
-        if (! empty($row_ids)) {
1059
-            // figure out where we start the row_id count at for the current page.
1060
-            $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
1061
-
1062
-            $row_count = count($row_ids);
1063
-            for ($i = 0; $i < $row_count; $i++) {
1064
-                // Update the questions when re-ordering
1065
-                $updated = EEM_Question_Group::instance()->update(
1066
-                    array('QSG_order' => $qsgcount),
1067
-                    array(array('QSG_ID' => $row_ids[ $i ]))
1068
-                );
1069
-                if ($updated === false) {
1070
-                    $success = false;
1071
-                }
1072
-                $qsgcount++;
1073
-            }
1074
-        } else {
1075
-            $success = false;
1076
-        }
1077
-
1078
-        $errors = ! $success
1079
-            ? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
1080
-            : false;
1081
-
1082
-        echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
1083
-        die();
1084
-    }
1085
-
1086
-
1087
-
1088
-    /***************************************       REGISTRATION SETTINGS       ***************************************/
1089
-
1090
-
1091
-    /**
1092
-     * @throws DomainException
1093
-     * @throws EE_Error
1094
-     * @throws InvalidArgumentException
1095
-     * @throws InvalidDataTypeException
1096
-     * @throws InvalidInterfaceException
1097
-     */
1098
-    protected function _reg_form_settings()
1099
-    {
1100
-        $this->_template_args['values'] = $this->_yes_no_values;
1101
-        add_action(
1102
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1103
-            array($this, 'email_validation_settings_form'),
1104
-            2
1105
-        );
1106
-        add_action(
1107
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1108
-            array($this, 'copy_attendee_info_settings_form'),
1109
-            4
1110
-        );
1111
-        $this->_template_args = (array) apply_filters(
1112
-            'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
1113
-            $this->_template_args
1114
-        );
1115
-        $this->_set_add_edit_form_tags('update_reg_form_settings');
1116
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
1117
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1118
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
1119
-            $this->_template_args,
1120
-            true
1121
-        );
1122
-        $this->display_admin_page_with_sidebar();
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * @return void
1128
-     * @throws EE_Error
1129
-     * @throws InvalidArgumentException
1130
-     * @throws ReflectionException
1131
-     * @throws InvalidDataTypeException
1132
-     * @throws InvalidInterfaceException
1133
-     */
1134
-    protected function _update_reg_form_settings()
1135
-    {
1136
-        EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
1137
-            EE_Registry::instance()->CFG->registration
1138
-        );
1139
-        EE_Registry::instance()->CFG->registration = $this->update_copy_attendee_info_settings_form(
1140
-            EE_Registry::instance()->CFG->registration
1141
-        );
1142
-        EE_Registry::instance()->CFG->registration = apply_filters(
1143
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
1144
-            EE_Registry::instance()->CFG->registration
1145
-        );
1146
-        $success = $this->_update_espresso_configuration(
1147
-            esc_html__('Registration Form Options', 'event_espresso'),
1148
-            EE_Registry::instance()->CFG,
1149
-            __FILE__,
1150
-            __FUNCTION__,
1151
-            __LINE__
1152
-        );
1153
-        $this->_redirect_after_action(
1154
-            $success,
1155
-            esc_html__('Registration Form Options', 'event_espresso'),
1156
-            'updated',
1157
-            array('action' => 'view_reg_form_settings')
1158
-        );
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * @return void
1164
-     * @throws EE_Error
1165
-     * @throws InvalidArgumentException
1166
-     * @throws InvalidDataTypeException
1167
-     * @throws InvalidInterfaceException
1168
-     */
1169
-    public function copy_attendee_info_settings_form()
1170
-    {
1171
-        echo wp_kses($this->_copy_attendee_info_settings_form()->get_html(), AllowedTags::getWithFormTags());
1172
-    }
1173
-
1174
-    /**
1175
-     * _copy_attendee_info_settings_form
1176
-     *
1177
-     * @access protected
1178
-     * @return EE_Form_Section_Proper
1179
-     * @throws \EE_Error
1180
-     */
1181
-    protected function _copy_attendee_info_settings_form()
1182
-    {
1183
-        return new EE_Form_Section_Proper(
1184
-            array(
1185
-                'name'            => 'copy_attendee_info_settings',
1186
-                'html_id'         => 'copy_attendee_info_settings',
1187
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1188
-                'subsections'     => apply_filters(
1189
-                    'FHEE__Extend_Registration_Form_Admin_Page___copy_attendee_info_settings_form__form_subsections',
1190
-                    array(
1191
-                        'copy_attendee_info_hdr'   => new EE_Form_Section_HTML(
1192
-                            EEH_HTML::h2(esc_html__('Copy Attendee Info Settings', 'event_espresso'))
1193
-                        ),
1194
-                        'copy_attendee_info' => new EE_Yes_No_Input(
1195
-                            array(
1196
-                                'html_label_text' => esc_html__(
1197
-                                    'Allow copy #1 attendee info to extra attendees?',
1198
-                                    'event_espresso'
1199
-                                ),
1200
-                                'html_help_text'  => esc_html__(
1201
-                                    'Set to yes if you want to enable the copy of #1 attendee info to extra attendees at Registration Form.',
1202
-                                    'event_espresso'
1203
-                                ),
1204
-                                'default'         => EE_Registry::instance()->CFG->registration->copyAttendeeInfo(),
1205
-                                'required'        => false,
1206
-                                'display_html_label_text' => false,
1207
-                            )
1208
-                        ),
1209
-                    )
1210
-                ),
1211
-            )
1212
-        );
1213
-    }
1214
-
1215
-    /**
1216
-     * @param EE_Registration_Config $EE_Registration_Config
1217
-     * @return EE_Registration_Config
1218
-     * @throws EE_Error
1219
-     * @throws InvalidArgumentException
1220
-     * @throws ReflectionException
1221
-     * @throws InvalidDataTypeException
1222
-     * @throws InvalidInterfaceException
1223
-     */
1224
-    public function update_copy_attendee_info_settings_form(EE_Registration_Config $EE_Registration_Config)
1225
-    {
1226
-        $prev_copy_attendee_info = $EE_Registration_Config->copyAttendeeInfo();
1227
-        try {
1228
-            $copy_attendee_info_settings_form = $this->_copy_attendee_info_settings_form();
1229
-            // if not displaying a form, then check for form submission
1230
-            if ($copy_attendee_info_settings_form->was_submitted()) {
1231
-                // capture form data
1232
-                $copy_attendee_info_settings_form->receive_form_submission();
1233
-                // validate form data
1234
-                if ($copy_attendee_info_settings_form->is_valid()) {
1235
-                    // grab validated data from form
1236
-                    $valid_data = $copy_attendee_info_settings_form->valid_data();
1237
-                    if (isset($valid_data['copy_attendee_info'])) {
1238
-                        $EE_Registration_Config->setCopyAttendeeInfo($valid_data['copy_attendee_info']);
1239
-                    } else {
1240
-                        EE_Error::add_error(
1241
-                            esc_html__(
1242
-                                'Invalid or missing Copy Attendee Info settings. Please refresh the form and try again.',
1243
-                                'event_espresso'
1244
-                            ),
1245
-                            __FILE__,
1246
-                            __FUNCTION__,
1247
-                            __LINE__
1248
-                        );
1249
-                    }
1250
-                } else {
1251
-                    if ($copy_attendee_info_settings_form->submission_error_message() !== '') {
1252
-                        EE_Error::add_error(
1253
-                            $copy_attendee_info_settings_form->submission_error_message(),
1254
-                            __FILE__,
1255
-                            __FUNCTION__,
1256
-                            __LINE__
1257
-                        );
1258
-                    }
1259
-                }
1260
-            }
1261
-        } catch (EE_Error $e) {
1262
-            $e->get_error();
1263
-        }
1264
-        return $EE_Registration_Config;
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * @return void
1270
-     * @throws EE_Error
1271
-     * @throws InvalidArgumentException
1272
-     * @throws InvalidDataTypeException
1273
-     * @throws InvalidInterfaceException
1274
-     */
1275
-    public function email_validation_settings_form()
1276
-    {
1277
-        echo wp_kses($this->_email_validation_settings_form()->get_html(), AllowedTags::getWithFormTags());
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * _email_validation_settings_form
1283
-     *
1284
-     * @access protected
1285
-     * @return EE_Form_Section_Proper
1286
-     * @throws \EE_Error
1287
-     */
1288
-    protected function _email_validation_settings_form()
1289
-    {
1290
-        return new EE_Form_Section_Proper(
1291
-            array(
1292
-                'name'            => 'email_validation_settings',
1293
-                'html_id'         => 'email_validation_settings',
1294
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1295
-                'subsections'     => apply_filters(
1296
-                    'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1297
-                    array(
1298
-                        'email_validation_hdr'   => new EE_Form_Section_HTML(
1299
-                            EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1300
-                        ),
1301
-                        'email_validation_level' => new EE_Select_Input(
1302
-                            array(
1303
-                                'basic'      => esc_html__('Basic', 'event_espresso'),
1304
-                                'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1305
-                                'i18n'       => esc_html__('International', 'event_espresso'),
1306
-                                'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1307
-                            ),
1308
-                            array(
1309
-                                'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1310
-                                                     . EEH_Template::get_help_tab_link('email_validation_info'),
1311
-                                'html_help_text'  => esc_html__(
1312
-                                    '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.',
1313
-                                    'event_espresso'
1314
-                                ),
1315
-                                'default'         => isset(
1316
-                                    EE_Registry::instance()->CFG->registration->email_validation_level
1317
-                                )
1318
-                                    ? EE_Registry::instance()->CFG->registration->email_validation_level
1319
-                                    : 'wp_default',
1320
-                                'required'        => false,
1321
-                            )
1322
-                        ),
1323
-                    )
1324
-                ),
1325
-            )
1326
-        );
1327
-    }
1328
-
1329
-
1330
-    /**
1331
-     * @param EE_Registration_Config $EE_Registration_Config
1332
-     * @return EE_Registration_Config
1333
-     * @throws EE_Error
1334
-     * @throws InvalidArgumentException
1335
-     * @throws ReflectionException
1336
-     * @throws InvalidDataTypeException
1337
-     * @throws InvalidInterfaceException
1338
-     */
1339
-    public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1340
-    {
1341
-        $prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1342
-        try {
1343
-            $email_validation_settings_form = $this->_email_validation_settings_form();
1344
-            // if not displaying a form, then check for form submission
1345
-            if ($email_validation_settings_form->was_submitted()) {
1346
-                // capture form data
1347
-                $email_validation_settings_form->receive_form_submission();
1348
-                // validate form data
1349
-                if ($email_validation_settings_form->is_valid()) {
1350
-                    // grab validated data from form
1351
-                    $valid_data = $email_validation_settings_form->valid_data();
1352
-                    if (isset($valid_data['email_validation_level'])) {
1353
-                        $email_validation_level = $valid_data['email_validation_level'];
1354
-                        // now if they want to use international email addresses
1355
-                        if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1356
-                            // in case we need to reset their email validation level,
1357
-                            // make sure that the previous value wasn't already set to one of the i18n options.
1358
-                            if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1359
-                                // if so, then reset it back to "basic" since that is the only other option that,
1360
-                                // despite offering poor validation, supports i18n email addresses
1361
-                                $prev_email_validation_level = 'basic';
1362
-                            }
1363
-                            // confirm our i18n email validation will work on the server
1364
-                            if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1365
-                                // or reset email validation level to previous value
1366
-                                $email_validation_level = $prev_email_validation_level;
1367
-                            }
1368
-                        }
1369
-                        $EE_Registration_Config->email_validation_level = $email_validation_level;
1370
-                    } else {
1371
-                        EE_Error::add_error(
1372
-                            esc_html__(
1373
-                                'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1374
-                                'event_espresso'
1375
-                            ),
1376
-                            __FILE__,
1377
-                            __FUNCTION__,
1378
-                            __LINE__
1379
-                        );
1380
-                    }
1381
-                } else {
1382
-                    if ($email_validation_settings_form->submission_error_message() !== '') {
1383
-                        EE_Error::add_error(
1384
-                            $email_validation_settings_form->submission_error_message(),
1385
-                            __FILE__,
1386
-                            __FUNCTION__,
1387
-                            __LINE__
1388
-                        );
1389
-                    }
1390
-                }
1391
-            }
1392
-        } catch (EE_Error $e) {
1393
-            $e->get_error();
1394
-        }
1395
-        return $EE_Registration_Config;
1396
-    }
1397
-
1398
-
1399
-    /**
1400
-     * confirms that the server's PHP version has the PCRE module enabled,
1401
-     * and that the PCRE version works with our i18n email validation
1402
-     *
1403
-     * @param EE_Registration_Config $EE_Registration_Config
1404
-     * @param string                 $email_validation_level
1405
-     * @return bool
1406
-     */
1407
-    private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1408
-    {
1409
-        // first check that PCRE is enabled
1410
-        if (! defined('PREG_BAD_UTF8_ERROR')) {
1411
-            EE_Error::add_error(
1412
-                sprintf(
1413
-                    esc_html__(
1414
-                        '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.',
1415
-                        'event_espresso'
1416
-                    ),
1417
-                    '<br />'
1418
-                ),
1419
-                __FILE__,
1420
-                __FUNCTION__,
1421
-                __LINE__
1422
-            );
1423
-            return false;
1424
-        } else {
1425
-            // PCRE support is enabled, but let's still
1426
-            // perform a test to see if the server will support it.
1427
-            // but first, save the updated validation level to the config,
1428
-            // so that the validation strategy picks it up.
1429
-            // this will get bumped back down if it doesn't work
1430
-            $EE_Registration_Config->email_validation_level = $email_validation_level;
1431
-            try {
1432
-                $email_validator = new EE_Email_Validation_Strategy();
1433
-                $i18n_email_address = apply_filters(
1434
-                    'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1435
-                    'jägerjü[email protected]'
1436
-                );
1437
-                $email_validator->validate($i18n_email_address);
1438
-            } catch (Exception $e) {
1439
-                EE_Error::add_error(
1440
-                    sprintf(
1441
-                        esc_html__(
1442
-                            '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',
1443
-                            'event_espresso'
1444
-                        ),
1445
-                        '<br />',
1446
-                        '<a href="http://php.net/manual/en/pcre.installation.php" target="_blank" rel="noopener noreferrer">http://php.net/manual/en/pcre.installation.php</a>'
1447
-                    ),
1448
-                    __FILE__,
1449
-                    __FUNCTION__,
1450
-                    __LINE__
1451
-                );
1452
-                return false;
1453
-            }
1454
-        }
1455
-        return true;
1456
-    }
17
+	/**
18
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
19
+	 */
20
+	public function __construct($routing = true)
21
+	{
22
+		define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form/');
23
+		define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets/');
24
+		define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
25
+		define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates/');
26
+		define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
27
+		parent::__construct($routing);
28
+	}
29
+
30
+
31
+	/**
32
+	 * @return void
33
+	 */
34
+	protected function _extend_page_config()
35
+	{
36
+		$this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
37
+		$qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
38
+			? $this->_req_data['QST_ID'] : 0;
39
+		$qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
40
+			? $this->_req_data['QSG_ID'] : 0;
41
+
42
+		$new_page_routes = array(
43
+			'question_groups'    => array(
44
+				'func'       => '_question_groups_overview_list_table',
45
+				'capability' => 'ee_read_question_groups',
46
+			),
47
+			'add_question'       => array(
48
+				'func'       => '_edit_question',
49
+				'capability' => 'ee_edit_questions',
50
+			),
51
+			'insert_question'    => array(
52
+				'func'       => '_insert_or_update_question',
53
+				'args'       => array('new_question' => true),
54
+				'capability' => 'ee_edit_questions',
55
+				'noheader'   => true,
56
+			),
57
+			'duplicate_question' => array(
58
+				'func'       => '_duplicate_question',
59
+				'capability' => 'ee_edit_questions',
60
+				'noheader'   => true,
61
+			),
62
+			'trash_question'     => array(
63
+				'func'       => '_trash_question',
64
+				'capability' => 'ee_delete_question',
65
+				'obj_id'     => $qst_id,
66
+				'noheader'   => true,
67
+			),
68
+
69
+			'restore_question' => array(
70
+				'func'       => '_trash_or_restore_questions',
71
+				'capability' => 'ee_delete_question',
72
+				'obj_id'     => $qst_id,
73
+				'args'       => array('trash' => false),
74
+				'noheader'   => true,
75
+			),
76
+
77
+			'delete_question' => array(
78
+				'func'       => '_delete_question',
79
+				'capability' => 'ee_delete_question',
80
+				'obj_id'     => $qst_id,
81
+				'noheader'   => true,
82
+			),
83
+
84
+			'trash_questions' => array(
85
+				'func'       => '_trash_or_restore_questions',
86
+				'capability' => 'ee_delete_questions',
87
+				'args'       => array('trash' => true),
88
+				'noheader'   => true,
89
+			),
90
+
91
+			'restore_questions' => array(
92
+				'func'       => '_trash_or_restore_questions',
93
+				'capability' => 'ee_delete_questions',
94
+				'args'       => array('trash' => false),
95
+				'noheader'   => true,
96
+			),
97
+
98
+			'delete_questions' => array(
99
+				'func'       => '_delete_questions',
100
+				'args'       => array(),
101
+				'capability' => 'ee_delete_questions',
102
+				'noheader'   => true,
103
+			),
104
+
105
+			'add_question_group' => array(
106
+				'func'       => '_edit_question_group',
107
+				'capability' => 'ee_edit_question_groups',
108
+			),
109
+
110
+			'edit_question_group' => array(
111
+				'func'       => '_edit_question_group',
112
+				'capability' => 'ee_edit_question_group',
113
+				'obj_id'     => $qsg_id,
114
+				'args'       => array('edit'),
115
+			),
116
+
117
+			'delete_question_groups' => array(
118
+				'func'       => '_delete_question_groups',
119
+				'capability' => 'ee_delete_question_groups',
120
+				'noheader'   => true,
121
+			),
122
+
123
+			'delete_question_group' => array(
124
+				'func'       => '_delete_question_groups',
125
+				'capability' => 'ee_delete_question_group',
126
+				'obj_id'     => $qsg_id,
127
+				'noheader'   => true,
128
+			),
129
+
130
+			'trash_question_group' => array(
131
+				'func'       => '_trash_or_restore_question_groups',
132
+				'args'       => array('trash' => true),
133
+				'capability' => 'ee_delete_question_group',
134
+				'obj_id'     => $qsg_id,
135
+				'noheader'   => true,
136
+			),
137
+
138
+			'restore_question_group' => array(
139
+				'func'       => '_trash_or_restore_question_groups',
140
+				'args'       => array('trash' => false),
141
+				'capability' => 'ee_delete_question_group',
142
+				'obj_id'     => $qsg_id,
143
+				'noheader'   => true,
144
+			),
145
+
146
+			'insert_question_group' => array(
147
+				'func'       => '_insert_or_update_question_group',
148
+				'args'       => array('new_question_group' => true),
149
+				'capability' => 'ee_edit_question_groups',
150
+				'noheader'   => true,
151
+			),
152
+
153
+			'update_question_group' => array(
154
+				'func'       => '_insert_or_update_question_group',
155
+				'args'       => array('new_question_group' => false),
156
+				'capability' => 'ee_edit_question_group',
157
+				'obj_id'     => $qsg_id,
158
+				'noheader'   => true,
159
+			),
160
+
161
+			'trash_question_groups' => array(
162
+				'func'       => '_trash_or_restore_question_groups',
163
+				'args'       => array('trash' => true),
164
+				'capability' => 'ee_delete_question_groups',
165
+				'noheader'   => array('trash' => false),
166
+			),
167
+
168
+			'restore_question_groups' => array(
169
+				'func'       => '_trash_or_restore_question_groups',
170
+				'args'       => array('trash' => false),
171
+				'capability' => 'ee_delete_question_groups',
172
+				'noheader'   => true,
173
+			),
174
+
175
+
176
+			'espresso_update_question_group_order' => array(
177
+				'func'       => 'update_question_group_order',
178
+				'capability' => 'ee_edit_question_groups',
179
+				'noheader'   => true,
180
+			),
181
+
182
+			'view_reg_form_settings' => array(
183
+				'func'       => '_reg_form_settings',
184
+				'capability' => 'manage_options',
185
+			),
186
+
187
+			'update_reg_form_settings' => array(
188
+				'func'       => '_update_reg_form_settings',
189
+				'capability' => 'manage_options',
190
+				'noheader'   => true,
191
+			),
192
+		);
193
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
194
+
195
+		$new_page_config = array(
196
+
197
+			'question_groups' => array(
198
+				'nav'           => array(
199
+					'label' => esc_html__('Question Groups', 'event_espresso'),
200
+					'order' => 20,
201
+				),
202
+				'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
203
+				'help_tabs'     => array(
204
+					'registration_form_question_groups_help_tab'                           => array(
205
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
206
+						'filename' => 'registration_form_question_groups',
207
+					),
208
+					'registration_form_question_groups_table_column_headings_help_tab'     => array(
209
+						'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
210
+						'filename' => 'registration_form_question_groups_table_column_headings',
211
+					),
212
+					'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
213
+						'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
214
+						'filename' => 'registration_form_question_groups_views_bulk_actions_search',
215
+					),
216
+				),
217
+				'metaboxes'     => $this->_default_espresso_metaboxes,
218
+				'require_nonce' => false,
219
+				'qtips'         => array(
220
+					'EE_Registration_Form_Tips',
221
+				),
222
+			),
223
+
224
+			'add_question' => array(
225
+				'nav'           => array(
226
+					'label'      => esc_html__('Add Question', 'event_espresso'),
227
+					'order'      => 5,
228
+					'persistent' => false,
229
+				),
230
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
231
+				'help_tabs'     => array(
232
+					'registration_form_add_question_help_tab' => array(
233
+						'title'    => esc_html__('Add Question', 'event_espresso'),
234
+						'filename' => 'registration_form_add_question',
235
+					),
236
+				),
237
+				'require_nonce' => false,
238
+			),
239
+
240
+			'add_question_group' => array(
241
+				'nav'           => array(
242
+					'label'      => esc_html__('Add Question Group', 'event_espresso'),
243
+					'order'      => 5,
244
+					'persistent' => false,
245
+				),
246
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
247
+				'help_tabs'     => array(
248
+					'registration_form_add_question_group_help_tab' => array(
249
+						'title'    => esc_html__('Add Question Group', 'event_espresso'),
250
+						'filename' => 'registration_form_add_question_group',
251
+					),
252
+				),
253
+				'require_nonce' => false,
254
+			),
255
+
256
+			'edit_question_group' => array(
257
+				'nav'           => array(
258
+					'label'      => esc_html__('Edit Question Group', 'event_espresso'),
259
+					'order'      => 5,
260
+					'persistent' => false,
261
+					'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
262
+						array('question_group_id' => $this->_req_data['question_group_id']),
263
+						$this->_current_page_view_url
264
+					) : $this->_admin_base_url,
265
+				),
266
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
267
+				'help_tabs'     => array(
268
+					'registration_form_edit_question_group_help_tab' => array(
269
+						'title'    => esc_html__('Edit Question Group', 'event_espresso'),
270
+						'filename' => 'registration_form_edit_question_group',
271
+					),
272
+				),
273
+				'require_nonce' => false,
274
+			),
275
+
276
+			'view_reg_form_settings' => array(
277
+				'nav'           => array(
278
+					'label' => esc_html__('Reg Form Settings', 'event_espresso'),
279
+					'order' => 40,
280
+				),
281
+				'labels'        => array(
282
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
283
+				),
284
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
285
+				'help_tabs'     => array(
286
+					'registration_form_reg_form_settings_help_tab' => array(
287
+						'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
288
+						'filename' => 'registration_form_reg_form_settings',
289
+					),
290
+				),
291
+				'require_nonce' => false,
292
+			),
293
+
294
+		);
295
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
296
+
297
+		// change the list table we're going to use so it's the NEW list table!
298
+		$this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
299
+
300
+
301
+		// additional labels
302
+		$new_labels = array(
303
+			'add_question'          => esc_html__('Add New Question', 'event_espresso'),
304
+			'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
305
+			'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
306
+			'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
307
+			'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
308
+		);
309
+		$this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
310
+	}
311
+
312
+
313
+	/**
314
+	 * @return void
315
+	 */
316
+	protected function _ajax_hooks()
317
+	{
318
+		add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
319
+	}
320
+
321
+
322
+	/**
323
+	 * @return void
324
+	 */
325
+	public function load_scripts_styles_question_groups()
326
+	{
327
+		wp_enqueue_script('espresso_ajax_table_sorting');
328
+	}
329
+
330
+
331
+	/**
332
+	 * @return void
333
+	 */
334
+	public function load_scripts_styles_add_question_group()
335
+	{
336
+		$this->load_scripts_styles_forms();
337
+		$this->load_sortable_question_script();
338
+	}
339
+
340
+
341
+	/**
342
+	 * @return void
343
+	 */
344
+	public function load_scripts_styles_edit_question_group()
345
+	{
346
+		$this->load_scripts_styles_forms();
347
+		$this->load_sortable_question_script();
348
+	}
349
+
350
+
351
+	/**
352
+	 * registers and enqueues script for questions
353
+	 *
354
+	 * @return void
355
+	 */
356
+	public function load_sortable_question_script()
357
+	{
358
+		wp_register_script(
359
+			'ee-question-sortable',
360
+			REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
361
+			array('jquery-ui-sortable'),
362
+			EVENT_ESPRESSO_VERSION,
363
+			true
364
+		);
365
+		wp_enqueue_script('ee-question-sortable');
366
+	}
367
+
368
+
369
+	/**
370
+	 * @return void
371
+	 */
372
+	protected function _set_list_table_views_default()
373
+	{
374
+		$this->_views = array(
375
+			'all' => array(
376
+				'slug'        => 'all',
377
+				'label'       => esc_html__('View All Questions', 'event_espresso'),
378
+				'count'       => 0,
379
+				'bulk_action' => array(
380
+					'trash_questions' => esc_html__('Trash', 'event_espresso'),
381
+				),
382
+			),
383
+		);
384
+
385
+		if (
386
+			EE_Registry::instance()->CAP->current_user_can(
387
+				'ee_delete_questions',
388
+				'espresso_registration_form_trash_questions'
389
+			)
390
+		) {
391
+			$this->_views['trash'] = array(
392
+				'slug'        => 'trash',
393
+				'label'       => esc_html__('Trash', 'event_espresso'),
394
+				'count'       => 0,
395
+				'bulk_action' => array(
396
+					'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
397
+					'restore_questions' => esc_html__('Restore', 'event_espresso'),
398
+				),
399
+			);
400
+		}
401
+	}
402
+
403
+
404
+	/**
405
+	 * @return void
406
+	 */
407
+	protected function _set_list_table_views_question_groups()
408
+	{
409
+		$this->_views = array(
410
+			'all' => array(
411
+				'slug'        => 'all',
412
+				'label'       => esc_html__('All', 'event_espresso'),
413
+				'count'       => 0,
414
+				'bulk_action' => array(
415
+					'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
416
+				),
417
+			),
418
+		);
419
+
420
+		if (
421
+			EE_Registry::instance()->CAP->current_user_can(
422
+				'ee_delete_question_groups',
423
+				'espresso_registration_form_trash_question_groups'
424
+			)
425
+		) {
426
+			$this->_views['trash'] = array(
427
+				'slug'        => 'trash',
428
+				'label'       => esc_html__('Trash', 'event_espresso'),
429
+				'count'       => 0,
430
+				'bulk_action' => array(
431
+					'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
432
+					'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
433
+				),
434
+			);
435
+		}
436
+	}
437
+
438
+
439
+	/**
440
+	 * @return void
441
+	 * @throws EE_Error
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 */
446
+	protected function _questions_overview_list_table()
447
+	{
448
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
449
+			'add_question',
450
+			'add_question',
451
+			array(),
452
+			'add-new-h2'
453
+		);
454
+		parent::_questions_overview_list_table();
455
+	}
456
+
457
+
458
+	/**
459
+	 * @return void
460
+	 * @throws DomainException
461
+	 * @throws EE_Error
462
+	 * @throws InvalidArgumentException
463
+	 * @throws InvalidDataTypeException
464
+	 * @throws InvalidInterfaceException
465
+	 */
466
+	protected function _question_groups_overview_list_table()
467
+	{
468
+		$this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
469
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
470
+			'add_question_group',
471
+			'add_question_group',
472
+			array(),
473
+			'add-new-h2'
474
+		);
475
+		$this->display_admin_list_table_page_with_sidebar();
476
+	}
477
+
478
+
479
+	/**
480
+	 * @return void
481
+	 * @throws EE_Error
482
+	 * @throws InvalidArgumentException
483
+	 * @throws InvalidDataTypeException
484
+	 * @throws InvalidInterfaceException
485
+	 */
486
+	protected function _delete_question()
487
+	{
488
+		$success = $this->_delete_items($this->_question_model);
489
+		$this->_redirect_after_action(
490
+			$success,
491
+			$this->_question_model->item_name($success),
492
+			'deleted',
493
+			array('action' => 'default', 'status' => 'all')
494
+		);
495
+	}
496
+
497
+
498
+	/**
499
+	 * @return void
500
+	 * @throws EE_Error
501
+	 * @throws InvalidArgumentException
502
+	 * @throws InvalidDataTypeException
503
+	 * @throws InvalidInterfaceException
504
+	 */
505
+	protected function _delete_questions()
506
+	{
507
+		$success = $this->_delete_items($this->_question_model);
508
+		$this->_redirect_after_action(
509
+			$success,
510
+			$this->_question_model->item_name($success),
511
+			'deleted permanently',
512
+			array('action' => 'default', 'status' => 'trash')
513
+		);
514
+	}
515
+
516
+
517
+	/**
518
+	 * Performs the deletion of a single or multiple questions or question groups.
519
+	 *
520
+	 * @param EEM_Soft_Delete_Base $model
521
+	 * @return int number of items deleted permanently
522
+	 * @throws EE_Error
523
+	 * @throws InvalidArgumentException
524
+	 * @throws InvalidDataTypeException
525
+	 * @throws InvalidInterfaceException
526
+	 */
527
+	private function _delete_items(EEM_Soft_Delete_Base $model)
528
+	{
529
+		$success = 0;
530
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
531
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
532
+			// if array has more than one element than success message should be plural
533
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
534
+			// cycle thru bulk action checkboxes
535
+			$checkboxes = $this->_req_data['checkbox'];
536
+			foreach (array_keys($checkboxes) as $ID) {
537
+				if (! $this->_delete_item($ID, $model)) {
538
+					$success = 0;
539
+				}
540
+			}
541
+		} elseif (! empty($this->_req_data['QSG_ID'])) {
542
+			$success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
543
+		} elseif (! empty($this->_req_data['QST_ID'])) {
544
+			$success = $this->_delete_item($this->_req_data['QST_ID'], $model);
545
+		} else {
546
+			EE_Error::add_error(
547
+				sprintf(
548
+					esc_html__(
549
+						"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.",
550
+						"event_espresso"
551
+					)
552
+				),
553
+				__FILE__,
554
+				__FUNCTION__,
555
+				__LINE__
556
+			);
557
+		}
558
+		return $success;
559
+	}
560
+
561
+
562
+	/**
563
+	 * Deletes the specified question (and its associated question options) or question group
564
+	 *
565
+	 * @param int                  $id
566
+	 * @param EEM_Soft_Delete_Base $model
567
+	 * @return boolean
568
+	 * @throws EE_Error
569
+	 * @throws InvalidArgumentException
570
+	 * @throws InvalidDataTypeException
571
+	 * @throws InvalidInterfaceException
572
+	 */
573
+	protected function _delete_item($id, $model)
574
+	{
575
+		if ($model instanceof EEM_Question) {
576
+			EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
577
+		}
578
+		return $model->delete_permanently_by_ID(absint($id));
579
+	}
580
+
581
+
582
+	/******************************    QUESTION GROUPS    ******************************/
583
+
584
+
585
+	/**
586
+	 * @param string $type
587
+	 * @return void
588
+	 * @throws DomainException
589
+	 * @throws EE_Error
590
+	 * @throws InvalidArgumentException
591
+	 * @throws InvalidDataTypeException
592
+	 * @throws InvalidInterfaceException
593
+	 */
594
+	protected function _edit_question_group($type = 'add')
595
+	{
596
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
597
+		$ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID'])
598
+			? absint($this->_req_data['QSG_ID'])
599
+			: false;
600
+
601
+		switch ($this->_req_action) {
602
+			case 'add_question_group':
603
+				$this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
604
+				break;
605
+			case 'edit_question_group':
606
+				$this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
607
+				break;
608
+			default:
609
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
610
+		}
611
+		// add ID to title if editing
612
+		$this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
613
+		if ($ID) {
614
+			/** @var EE_Question_Group $questionGroup */
615
+			$questionGroup = $this->_question_group_model->get_one_by_ID($ID);
616
+			$additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
617
+			$this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
618
+		} else {
619
+			/** @var EE_Question_Group $questionGroup */
620
+			$questionGroup = EEM_Question_Group::instance()->create_default_object();
621
+			$questionGroup->set_order_to_latest();
622
+			$this->_set_add_edit_form_tags('insert_question_group');
623
+		}
624
+		$this->_template_args['values'] = $this->_yes_no_values;
625
+		$this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
626
+		$this->_template_args['QSG_ID'] = $ID ? $ID : true;
627
+		$this->_template_args['question_group'] = $questionGroup;
628
+
629
+		$redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
630
+		$this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
631
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
632
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
633
+			$this->_template_args,
634
+			true
635
+		);
636
+
637
+		// the details template wrapper
638
+		$this->display_admin_page_with_sidebar();
639
+	}
640
+
641
+
642
+	/**
643
+	 * @return void
644
+	 * @throws EE_Error
645
+	 * @throws InvalidArgumentException
646
+	 * @throws InvalidDataTypeException
647
+	 * @throws InvalidInterfaceException
648
+	 */
649
+	protected function _delete_question_groups()
650
+	{
651
+		$success = $this->_delete_items($this->_question_group_model);
652
+		$this->_redirect_after_action(
653
+			$success,
654
+			$this->_question_group_model->item_name($success),
655
+			'deleted permanently',
656
+			array('action' => 'question_groups', 'status' => 'trash')
657
+		);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param bool $new_question_group
663
+	 * @throws EE_Error
664
+	 * @throws InvalidArgumentException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws InvalidInterfaceException
667
+	 */
668
+	protected function _insert_or_update_question_group($new_question_group = true)
669
+	{
670
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
671
+		$set_column_values = $this->_set_column_values_for($this->_question_group_model);
672
+
673
+		// make sure identifier is unique
674
+		$identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : '';
675
+		$where_values = ['QSG_identifier' => $set_column_values['QSG_identifier']];
676
+		if (! $new_question_group && isset($set_column_values['QSG_ID'])) {
677
+			$where_values['QSG_ID'] = ['!=', $set_column_values['QSG_ID']];
678
+		}
679
+		$identifier_exists = ! empty($identifier_value)
680
+			? $this->_question_group_model->count([$where_values]) > 0
681
+			: false;
682
+		if ($identifier_exists) {
683
+			$set_column_values['QSG_identifier'] .= uniqid('id', true);
684
+		}
685
+
686
+		if ($new_question_group) {
687
+			$QSG_ID = $this->_question_group_model->insert($set_column_values);
688
+			$success = $QSG_ID ? 1 : 0;
689
+			if ($success === 0) {
690
+				EE_Error::add_error(
691
+					esc_html__('Something went wrong saving the question group.', 'event_espresso'),
692
+					__FILE__,
693
+					__FUNCTION__,
694
+					__LINE__
695
+				);
696
+				$this->_redirect_after_action(
697
+					false,
698
+					'',
699
+					'',
700
+					array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
701
+					true
702
+				);
703
+			}
704
+		} else {
705
+			$QSG_ID = absint($this->_req_data['QSG_ID']);
706
+			unset($set_column_values['QSG_ID']);
707
+			$success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
708
+		}
709
+
710
+		$phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
711
+			EEM_Attendee::system_question_phone
712
+		);
713
+		// update the existing related questions
714
+		// BUT FIRST...  delete the phone question from the Question_Group_Question
715
+		// if it is being added to this question group (therefore removed from the existing group)
716
+		if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
717
+			// delete where QST ID = system phone question ID and Question Group ID is NOT this group
718
+			EEM_Question_Group_Question::instance()->delete(
719
+				array(
720
+					array(
721
+						'QST_ID' => $phone_question_id,
722
+						'QSG_ID' => array('!=', $QSG_ID),
723
+					),
724
+				)
725
+			);
726
+		}
727
+		/** @type EE_Question_Group $question_group */
728
+		$question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
729
+		$questions = $question_group->questions();
730
+		// make sure system phone question is added to list of questions for this group
731
+		if (! isset($questions[ $phone_question_id ])) {
732
+			$questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
733
+		}
734
+
735
+		foreach ($questions as $question_ID => $question) {
736
+			// first we always check for order.
737
+			if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
738
+				// update question order
739
+				$question_group->update_question_order(
740
+					$question_ID,
741
+					$this->_req_data['question_orders'][ $question_ID ]
742
+				);
743
+			}
744
+
745
+			// then we always check if adding or removing.
746
+			if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
747
+				$question_group->add_question($question_ID);
748
+			} else {
749
+				// not found, remove it (but only if not a system question for the personal group
750
+				// with the exception of lname system question - we allow removal of it)
751
+				if (
752
+					in_array(
753
+						$question->system_ID(),
754
+						EEM_Question::instance()->required_system_questions_in_system_question_group(
755
+							$question_group->system_group()
756
+						)
757
+					)
758
+				) {
759
+					continue;
760
+				} else {
761
+					$question_group->remove_question($question_ID);
762
+				}
763
+			}
764
+		}
765
+		// save new related questions
766
+		if (isset($this->_req_data['questions'])) {
767
+			foreach ($this->_req_data['questions'] as $QST_ID) {
768
+				$question_group->add_question($QST_ID);
769
+				if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
770
+					$question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
771
+				}
772
+			}
773
+		}
774
+
775
+		if ($success !== false) {
776
+			$msg = $new_question_group
777
+				? sprintf(
778
+					esc_html__('The %s has been created', 'event_espresso'),
779
+					$this->_question_group_model->item_name()
780
+				)
781
+				: sprintf(
782
+					esc_html__(
783
+						'The %s has been updated',
784
+						'event_espresso'
785
+					),
786
+					$this->_question_group_model->item_name()
787
+				);
788
+			EE_Error::add_success($msg);
789
+		}
790
+		$this->_redirect_after_action(
791
+			false,
792
+			'',
793
+			'',
794
+			array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
795
+			true
796
+		);
797
+	}
798
+
799
+
800
+	/**
801
+	 * duplicates a question and all its question options and redirects to the new question.
802
+	 *
803
+	 * @return void
804
+	 * @throws EE_Error
805
+	 * @throws InvalidArgumentException
806
+	 * @throws ReflectionException
807
+	 * @throws InvalidDataTypeException
808
+	 * @throws InvalidInterfaceException
809
+	 */
810
+	public function _duplicate_question()
811
+	{
812
+		$question_ID = (int) $this->_req_data['QST_ID'];
813
+		$question = EEM_Question::instance()->get_one_by_ID($question_ID);
814
+		if ($question instanceof EE_Question) {
815
+			$new_question = $question->duplicate();
816
+			if ($new_question instanceof EE_Question) {
817
+				$this->_redirect_after_action(
818
+					true,
819
+					esc_html__('Question', 'event_espresso'),
820
+					esc_html__('Duplicated', 'event_espresso'),
821
+					array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
822
+					true
823
+				);
824
+			} else {
825
+				global $wpdb;
826
+				EE_Error::add_error(
827
+					sprintf(
828
+						esc_html__(
829
+							'Could not duplicate question with ID %1$d because: %2$s',
830
+							'event_espresso'
831
+						),
832
+						$question_ID,
833
+						$wpdb->last_error
834
+					),
835
+					__FILE__,
836
+					__FUNCTION__,
837
+					__LINE__
838
+				);
839
+				$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
840
+			}
841
+		} else {
842
+			EE_Error::add_error(
843
+				sprintf(
844
+					esc_html__(
845
+						'Could not duplicate question with ID %d because it didn\'t exist!',
846
+						'event_espresso'
847
+					),
848
+					$question_ID
849
+				),
850
+				__FILE__,
851
+				__FUNCTION__,
852
+				__LINE__
853
+			);
854
+			$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
855
+		}
856
+	}
857
+
858
+
859
+	/**
860
+	 * @param bool $trash
861
+	 * @throws EE_Error
862
+	 */
863
+	protected function _trash_or_restore_question_groups($trash = true)
864
+	{
865
+		$this->_trash_or_restore_items($this->_question_group_model, $trash);
866
+	}
867
+
868
+
869
+	/**
870
+	 *_trash_question
871
+	 *
872
+	 * @return void
873
+	 * @throws EE_Error
874
+	 */
875
+	protected function _trash_question()
876
+	{
877
+		$success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
878
+		$query_args = array('action' => 'default', 'status' => 'all');
879
+		$this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
880
+	}
881
+
882
+
883
+	/**
884
+	 * @param bool $trash
885
+	 * @throws EE_Error
886
+	 */
887
+	protected function _trash_or_restore_questions($trash = true)
888
+	{
889
+		$this->_trash_or_restore_items($this->_question_model, $trash);
890
+	}
891
+
892
+
893
+	/**
894
+	 * Internally used to delete or restore items, using the request data. Meant to be
895
+	 * flexible between question or question groups
896
+	 *
897
+	 * @param EEM_Soft_Delete_Base $model
898
+	 * @param boolean              $trash whether to trash or restore
899
+	 * @throws EE_Error
900
+	 */
901
+	private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
902
+	{
903
+
904
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
905
+
906
+		$success = 1;
907
+		// Checkboxes
908
+		// echo "trash $trash";
909
+		// var_dump($this->_req_data['checkbox']);die;
910
+		if (isset($this->_req_data['checkbox'])) {
911
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
912
+				// if array has more than one element than success message should be plural
913
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
914
+				// cycle thru bulk action checkboxes
915
+				$checkboxes = $this->_req_data['checkbox'];
916
+				foreach (array_keys($checkboxes) as $ID) {
917
+					if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
918
+						$success = 0;
919
+					}
920
+				}
921
+			} else {
922
+				// grab single id and delete
923
+				$ID = absint($this->_req_data['checkbox']);
924
+				if (! $model->delete_or_restore_by_ID($trash, $ID)) {
925
+					$success = 0;
926
+				}
927
+			}
928
+		} else {
929
+			// delete via trash link
930
+			// grab single id and delete
931
+			$ID = absint($this->_req_data[ $model->primary_key_name() ]);
932
+			if (! $model->delete_or_restore_by_ID($trash, $ID)) {
933
+				$success = 0;
934
+			}
935
+		}
936
+
937
+
938
+		$action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
939
+		// echo "action :$action";
940
+		// $action = 'questions' ? 'default' : $action;
941
+		if ($trash) {
942
+			$action_desc = 'trashed';
943
+			$status = 'trash';
944
+		} else {
945
+			$action_desc = 'restored';
946
+			$status = 'all';
947
+		}
948
+		$this->_redirect_after_action(
949
+			$success,
950
+			$model->item_name($success),
951
+			$action_desc,
952
+			array('action' => $action, 'status' => $status)
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * @param            $per_page
959
+	 * @param int        $current_page
960
+	 * @param bool|false $count
961
+	 * @return EE_Soft_Delete_Base_Class[]|int
962
+	 * @throws EE_Error
963
+	 * @throws InvalidArgumentException
964
+	 * @throws InvalidDataTypeException
965
+	 * @throws InvalidInterfaceException
966
+	 */
967
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
968
+	{
969
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
970
+
971
+		if ($count) {
972
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
973
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
974
+			$results = $this->_question_model->count_deleted($where);
975
+		} else {
976
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
977
+			$results = $this->_question_model->get_all_deleted($query_params);
978
+		}
979
+		return $results;
980
+	}
981
+
982
+
983
+	/**
984
+	 * @param            $per_page
985
+	 * @param int        $current_page
986
+	 * @param bool|false $count
987
+	 * @return EE_Soft_Delete_Base_Class[]|int
988
+	 * @throws EE_Error
989
+	 * @throws InvalidArgumentException
990
+	 * @throws InvalidDataTypeException
991
+	 * @throws InvalidInterfaceException
992
+	 */
993
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
994
+	{
995
+		$questionGroupModel = EEM_Question_Group::instance();
996
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
997
+		if ($count) {
998
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
999
+			$results = $questionGroupModel->count($where);
1000
+		} else {
1001
+			$results = $questionGroupModel->get_all($query_params);
1002
+		}
1003
+		return $results;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * @param      $per_page
1009
+	 * @param int  $current_page
1010
+	 * @param bool $count
1011
+	 * @return EE_Soft_Delete_Base_Class[]|int
1012
+	 * @throws EE_Error
1013
+	 * @throws InvalidArgumentException
1014
+	 * @throws InvalidDataTypeException
1015
+	 * @throws InvalidInterfaceException
1016
+	 */
1017
+	public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
1018
+	{
1019
+		$questionGroupModel = EEM_Question_Group::instance();
1020
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
1021
+		if ($count) {
1022
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
1023
+			$query_params['limit'] = null;
1024
+			$results = $questionGroupModel->count_deleted($where);
1025
+		} else {
1026
+			$results = $questionGroupModel->get_all_deleted($query_params);
1027
+		}
1028
+		return $results;
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * method for performing updates to question order
1034
+	 *
1035
+	 * @return void results array
1036
+	 * @throws EE_Error
1037
+	 * @throws InvalidArgumentException
1038
+	 * @throws InvalidDataTypeException
1039
+	 * @throws InvalidInterfaceException
1040
+	 */
1041
+	public function update_question_group_order()
1042
+	{
1043
+
1044
+		$success = esc_html__('Question group order was updated successfully.', 'event_espresso');
1045
+
1046
+		// grab our row IDs
1047
+		$row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
1048
+			? explode(',', rtrim($this->_req_data['row_ids'], ','))
1049
+			: array();
1050
+
1051
+		$perpage = ! empty($this->_req_data['perpage'])
1052
+			? (int) $this->_req_data['perpage']
1053
+			: null;
1054
+		$curpage = ! empty($this->_req_data['curpage'])
1055
+			? (int) $this->_req_data['curpage']
1056
+			: null;
1057
+
1058
+		if (! empty($row_ids)) {
1059
+			// figure out where we start the row_id count at for the current page.
1060
+			$qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
1061
+
1062
+			$row_count = count($row_ids);
1063
+			for ($i = 0; $i < $row_count; $i++) {
1064
+				// Update the questions when re-ordering
1065
+				$updated = EEM_Question_Group::instance()->update(
1066
+					array('QSG_order' => $qsgcount),
1067
+					array(array('QSG_ID' => $row_ids[ $i ]))
1068
+				);
1069
+				if ($updated === false) {
1070
+					$success = false;
1071
+				}
1072
+				$qsgcount++;
1073
+			}
1074
+		} else {
1075
+			$success = false;
1076
+		}
1077
+
1078
+		$errors = ! $success
1079
+			? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
1080
+			: false;
1081
+
1082
+		echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
1083
+		die();
1084
+	}
1085
+
1086
+
1087
+
1088
+	/***************************************       REGISTRATION SETTINGS       ***************************************/
1089
+
1090
+
1091
+	/**
1092
+	 * @throws DomainException
1093
+	 * @throws EE_Error
1094
+	 * @throws InvalidArgumentException
1095
+	 * @throws InvalidDataTypeException
1096
+	 * @throws InvalidInterfaceException
1097
+	 */
1098
+	protected function _reg_form_settings()
1099
+	{
1100
+		$this->_template_args['values'] = $this->_yes_no_values;
1101
+		add_action(
1102
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1103
+			array($this, 'email_validation_settings_form'),
1104
+			2
1105
+		);
1106
+		add_action(
1107
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1108
+			array($this, 'copy_attendee_info_settings_form'),
1109
+			4
1110
+		);
1111
+		$this->_template_args = (array) apply_filters(
1112
+			'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
1113
+			$this->_template_args
1114
+		);
1115
+		$this->_set_add_edit_form_tags('update_reg_form_settings');
1116
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
1117
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1118
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
1119
+			$this->_template_args,
1120
+			true
1121
+		);
1122
+		$this->display_admin_page_with_sidebar();
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * @return void
1128
+	 * @throws EE_Error
1129
+	 * @throws InvalidArgumentException
1130
+	 * @throws ReflectionException
1131
+	 * @throws InvalidDataTypeException
1132
+	 * @throws InvalidInterfaceException
1133
+	 */
1134
+	protected function _update_reg_form_settings()
1135
+	{
1136
+		EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
1137
+			EE_Registry::instance()->CFG->registration
1138
+		);
1139
+		EE_Registry::instance()->CFG->registration = $this->update_copy_attendee_info_settings_form(
1140
+			EE_Registry::instance()->CFG->registration
1141
+		);
1142
+		EE_Registry::instance()->CFG->registration = apply_filters(
1143
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
1144
+			EE_Registry::instance()->CFG->registration
1145
+		);
1146
+		$success = $this->_update_espresso_configuration(
1147
+			esc_html__('Registration Form Options', 'event_espresso'),
1148
+			EE_Registry::instance()->CFG,
1149
+			__FILE__,
1150
+			__FUNCTION__,
1151
+			__LINE__
1152
+		);
1153
+		$this->_redirect_after_action(
1154
+			$success,
1155
+			esc_html__('Registration Form Options', 'event_espresso'),
1156
+			'updated',
1157
+			array('action' => 'view_reg_form_settings')
1158
+		);
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * @return void
1164
+	 * @throws EE_Error
1165
+	 * @throws InvalidArgumentException
1166
+	 * @throws InvalidDataTypeException
1167
+	 * @throws InvalidInterfaceException
1168
+	 */
1169
+	public function copy_attendee_info_settings_form()
1170
+	{
1171
+		echo wp_kses($this->_copy_attendee_info_settings_form()->get_html(), AllowedTags::getWithFormTags());
1172
+	}
1173
+
1174
+	/**
1175
+	 * _copy_attendee_info_settings_form
1176
+	 *
1177
+	 * @access protected
1178
+	 * @return EE_Form_Section_Proper
1179
+	 * @throws \EE_Error
1180
+	 */
1181
+	protected function _copy_attendee_info_settings_form()
1182
+	{
1183
+		return new EE_Form_Section_Proper(
1184
+			array(
1185
+				'name'            => 'copy_attendee_info_settings',
1186
+				'html_id'         => 'copy_attendee_info_settings',
1187
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1188
+				'subsections'     => apply_filters(
1189
+					'FHEE__Extend_Registration_Form_Admin_Page___copy_attendee_info_settings_form__form_subsections',
1190
+					array(
1191
+						'copy_attendee_info_hdr'   => new EE_Form_Section_HTML(
1192
+							EEH_HTML::h2(esc_html__('Copy Attendee Info Settings', 'event_espresso'))
1193
+						),
1194
+						'copy_attendee_info' => new EE_Yes_No_Input(
1195
+							array(
1196
+								'html_label_text' => esc_html__(
1197
+									'Allow copy #1 attendee info to extra attendees?',
1198
+									'event_espresso'
1199
+								),
1200
+								'html_help_text'  => esc_html__(
1201
+									'Set to yes if you want to enable the copy of #1 attendee info to extra attendees at Registration Form.',
1202
+									'event_espresso'
1203
+								),
1204
+								'default'         => EE_Registry::instance()->CFG->registration->copyAttendeeInfo(),
1205
+								'required'        => false,
1206
+								'display_html_label_text' => false,
1207
+							)
1208
+						),
1209
+					)
1210
+				),
1211
+			)
1212
+		);
1213
+	}
1214
+
1215
+	/**
1216
+	 * @param EE_Registration_Config $EE_Registration_Config
1217
+	 * @return EE_Registration_Config
1218
+	 * @throws EE_Error
1219
+	 * @throws InvalidArgumentException
1220
+	 * @throws ReflectionException
1221
+	 * @throws InvalidDataTypeException
1222
+	 * @throws InvalidInterfaceException
1223
+	 */
1224
+	public function update_copy_attendee_info_settings_form(EE_Registration_Config $EE_Registration_Config)
1225
+	{
1226
+		$prev_copy_attendee_info = $EE_Registration_Config->copyAttendeeInfo();
1227
+		try {
1228
+			$copy_attendee_info_settings_form = $this->_copy_attendee_info_settings_form();
1229
+			// if not displaying a form, then check for form submission
1230
+			if ($copy_attendee_info_settings_form->was_submitted()) {
1231
+				// capture form data
1232
+				$copy_attendee_info_settings_form->receive_form_submission();
1233
+				// validate form data
1234
+				if ($copy_attendee_info_settings_form->is_valid()) {
1235
+					// grab validated data from form
1236
+					$valid_data = $copy_attendee_info_settings_form->valid_data();
1237
+					if (isset($valid_data['copy_attendee_info'])) {
1238
+						$EE_Registration_Config->setCopyAttendeeInfo($valid_data['copy_attendee_info']);
1239
+					} else {
1240
+						EE_Error::add_error(
1241
+							esc_html__(
1242
+								'Invalid or missing Copy Attendee Info settings. Please refresh the form and try again.',
1243
+								'event_espresso'
1244
+							),
1245
+							__FILE__,
1246
+							__FUNCTION__,
1247
+							__LINE__
1248
+						);
1249
+					}
1250
+				} else {
1251
+					if ($copy_attendee_info_settings_form->submission_error_message() !== '') {
1252
+						EE_Error::add_error(
1253
+							$copy_attendee_info_settings_form->submission_error_message(),
1254
+							__FILE__,
1255
+							__FUNCTION__,
1256
+							__LINE__
1257
+						);
1258
+					}
1259
+				}
1260
+			}
1261
+		} catch (EE_Error $e) {
1262
+			$e->get_error();
1263
+		}
1264
+		return $EE_Registration_Config;
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * @return void
1270
+	 * @throws EE_Error
1271
+	 * @throws InvalidArgumentException
1272
+	 * @throws InvalidDataTypeException
1273
+	 * @throws InvalidInterfaceException
1274
+	 */
1275
+	public function email_validation_settings_form()
1276
+	{
1277
+		echo wp_kses($this->_email_validation_settings_form()->get_html(), AllowedTags::getWithFormTags());
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * _email_validation_settings_form
1283
+	 *
1284
+	 * @access protected
1285
+	 * @return EE_Form_Section_Proper
1286
+	 * @throws \EE_Error
1287
+	 */
1288
+	protected function _email_validation_settings_form()
1289
+	{
1290
+		return new EE_Form_Section_Proper(
1291
+			array(
1292
+				'name'            => 'email_validation_settings',
1293
+				'html_id'         => 'email_validation_settings',
1294
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1295
+				'subsections'     => apply_filters(
1296
+					'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1297
+					array(
1298
+						'email_validation_hdr'   => new EE_Form_Section_HTML(
1299
+							EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1300
+						),
1301
+						'email_validation_level' => new EE_Select_Input(
1302
+							array(
1303
+								'basic'      => esc_html__('Basic', 'event_espresso'),
1304
+								'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1305
+								'i18n'       => esc_html__('International', 'event_espresso'),
1306
+								'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1307
+							),
1308
+							array(
1309
+								'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1310
+													 . EEH_Template::get_help_tab_link('email_validation_info'),
1311
+								'html_help_text'  => esc_html__(
1312
+									'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.',
1313
+									'event_espresso'
1314
+								),
1315
+								'default'         => isset(
1316
+									EE_Registry::instance()->CFG->registration->email_validation_level
1317
+								)
1318
+									? EE_Registry::instance()->CFG->registration->email_validation_level
1319
+									: 'wp_default',
1320
+								'required'        => false,
1321
+							)
1322
+						),
1323
+					)
1324
+				),
1325
+			)
1326
+		);
1327
+	}
1328
+
1329
+
1330
+	/**
1331
+	 * @param EE_Registration_Config $EE_Registration_Config
1332
+	 * @return EE_Registration_Config
1333
+	 * @throws EE_Error
1334
+	 * @throws InvalidArgumentException
1335
+	 * @throws ReflectionException
1336
+	 * @throws InvalidDataTypeException
1337
+	 * @throws InvalidInterfaceException
1338
+	 */
1339
+	public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1340
+	{
1341
+		$prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1342
+		try {
1343
+			$email_validation_settings_form = $this->_email_validation_settings_form();
1344
+			// if not displaying a form, then check for form submission
1345
+			if ($email_validation_settings_form->was_submitted()) {
1346
+				// capture form data
1347
+				$email_validation_settings_form->receive_form_submission();
1348
+				// validate form data
1349
+				if ($email_validation_settings_form->is_valid()) {
1350
+					// grab validated data from form
1351
+					$valid_data = $email_validation_settings_form->valid_data();
1352
+					if (isset($valid_data['email_validation_level'])) {
1353
+						$email_validation_level = $valid_data['email_validation_level'];
1354
+						// now if they want to use international email addresses
1355
+						if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1356
+							// in case we need to reset their email validation level,
1357
+							// make sure that the previous value wasn't already set to one of the i18n options.
1358
+							if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1359
+								// if so, then reset it back to "basic" since that is the only other option that,
1360
+								// despite offering poor validation, supports i18n email addresses
1361
+								$prev_email_validation_level = 'basic';
1362
+							}
1363
+							// confirm our i18n email validation will work on the server
1364
+							if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1365
+								// or reset email validation level to previous value
1366
+								$email_validation_level = $prev_email_validation_level;
1367
+							}
1368
+						}
1369
+						$EE_Registration_Config->email_validation_level = $email_validation_level;
1370
+					} else {
1371
+						EE_Error::add_error(
1372
+							esc_html__(
1373
+								'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1374
+								'event_espresso'
1375
+							),
1376
+							__FILE__,
1377
+							__FUNCTION__,
1378
+							__LINE__
1379
+						);
1380
+					}
1381
+				} else {
1382
+					if ($email_validation_settings_form->submission_error_message() !== '') {
1383
+						EE_Error::add_error(
1384
+							$email_validation_settings_form->submission_error_message(),
1385
+							__FILE__,
1386
+							__FUNCTION__,
1387
+							__LINE__
1388
+						);
1389
+					}
1390
+				}
1391
+			}
1392
+		} catch (EE_Error $e) {
1393
+			$e->get_error();
1394
+		}
1395
+		return $EE_Registration_Config;
1396
+	}
1397
+
1398
+
1399
+	/**
1400
+	 * confirms that the server's PHP version has the PCRE module enabled,
1401
+	 * and that the PCRE version works with our i18n email validation
1402
+	 *
1403
+	 * @param EE_Registration_Config $EE_Registration_Config
1404
+	 * @param string                 $email_validation_level
1405
+	 * @return bool
1406
+	 */
1407
+	private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1408
+	{
1409
+		// first check that PCRE is enabled
1410
+		if (! defined('PREG_BAD_UTF8_ERROR')) {
1411
+			EE_Error::add_error(
1412
+				sprintf(
1413
+					esc_html__(
1414
+						'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.',
1415
+						'event_espresso'
1416
+					),
1417
+					'<br />'
1418
+				),
1419
+				__FILE__,
1420
+				__FUNCTION__,
1421
+				__LINE__
1422
+			);
1423
+			return false;
1424
+		} else {
1425
+			// PCRE support is enabled, but let's still
1426
+			// perform a test to see if the server will support it.
1427
+			// but first, save the updated validation level to the config,
1428
+			// so that the validation strategy picks it up.
1429
+			// this will get bumped back down if it doesn't work
1430
+			$EE_Registration_Config->email_validation_level = $email_validation_level;
1431
+			try {
1432
+				$email_validator = new EE_Email_Validation_Strategy();
1433
+				$i18n_email_address = apply_filters(
1434
+					'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1435
+					'jägerjü[email protected]'
1436
+				);
1437
+				$email_validator->validate($i18n_email_address);
1438
+			} catch (Exception $e) {
1439
+				EE_Error::add_error(
1440
+					sprintf(
1441
+						esc_html__(
1442
+							'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',
1443
+							'event_espresso'
1444
+						),
1445
+						'<br />',
1446
+						'<a href="http://php.net/manual/en/pcre.installation.php" target="_blank" rel="noopener noreferrer">http://php.net/manual/en/pcre.installation.php</a>'
1447
+					),
1448
+					__FILE__,
1449
+					__FUNCTION__,
1450
+					__LINE__
1451
+				);
1452
+				return false;
1453
+			}
1454
+		}
1455
+		return true;
1456
+	}
1457 1457
 }
Please login to merge, or discard this patch.
Spacing   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -19,11 +19,11 @@  discard block
 block discarded – undo
19 19
      */
20 20
     public function __construct($routing = true)
21 21
     {
22
-        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form/');
23
-        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets/');
24
-        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
25
-        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates/');
26
-        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
22
+        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND.'registration_form/');
23
+        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN.'assets/');
24
+        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registration_form/assets/');
25
+        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN.'templates/');
26
+        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registration_form/templates/');
27 27
         parent::__construct($routing);
28 28
     }
29 29
 
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
     {
358 358
         wp_register_script(
359 359
             'ee-question-sortable',
360
-            REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
360
+            REGISTRATION_FORM_CAF_ASSETS_URL.'ee_question_order.js',
361 361
             array('jquery-ui-sortable'),
362 362
             EVENT_ESPRESSO_VERSION,
363 363
             true
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
      */
446 446
     protected function _questions_overview_list_table()
447 447
     {
448
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
448
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
449 449
             'add_question',
450 450
             'add_question',
451 451
             array(),
@@ -466,7 +466,7 @@  discard block
 block discarded – undo
466 466
     protected function _question_groups_overview_list_table()
467 467
     {
468 468
         $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
469
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
469
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
470 470
             'add_question_group',
471 471
             'add_question_group',
472 472
             array(),
@@ -528,19 +528,19 @@  discard block
 block discarded – undo
528 528
     {
529 529
         $success = 0;
530 530
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
531
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
531
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
532 532
             // if array has more than one element than success message should be plural
533 533
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
534 534
             // cycle thru bulk action checkboxes
535 535
             $checkboxes = $this->_req_data['checkbox'];
536 536
             foreach (array_keys($checkboxes) as $ID) {
537
-                if (! $this->_delete_item($ID, $model)) {
537
+                if ( ! $this->_delete_item($ID, $model)) {
538 538
                     $success = 0;
539 539
                 }
540 540
             }
541
-        } elseif (! empty($this->_req_data['QSG_ID'])) {
541
+        } elseif ( ! empty($this->_req_data['QSG_ID'])) {
542 542
             $success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
543
-        } elseif (! empty($this->_req_data['QST_ID'])) {
543
+        } elseif ( ! empty($this->_req_data['QST_ID'])) {
544 544
             $success = $this->_delete_item($this->_req_data['QST_ID'], $model);
545 545
         } else {
546 546
             EE_Error::add_error(
@@ -609,7 +609,7 @@  discard block
 block discarded – undo
609 609
                 $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
610 610
         }
611 611
         // add ID to title if editing
612
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
612
+        $this->_admin_page_title = $ID ? $this->_admin_page_title.' # '.$ID : $this->_admin_page_title;
613 613
         if ($ID) {
614 614
             /** @var EE_Question_Group $questionGroup */
615 615
             $questionGroup = $this->_question_group_model->get_one_by_ID($ID);
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
630 630
         $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
631 631
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
632
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
632
+            REGISTRATION_FORM_CAF_TEMPLATE_PATH.'question_groups_main_meta_box.template.php',
633 633
             $this->_template_args,
634 634
             true
635 635
         );
@@ -673,7 +673,7 @@  discard block
 block discarded – undo
673 673
         // make sure identifier is unique
674 674
         $identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : '';
675 675
         $where_values = ['QSG_identifier' => $set_column_values['QSG_identifier']];
676
-        if (! $new_question_group && isset($set_column_values['QSG_ID'])) {
676
+        if ( ! $new_question_group && isset($set_column_values['QSG_ID'])) {
677 677
             $where_values['QSG_ID'] = ['!=', $set_column_values['QSG_ID']];
678 678
         }
679 679
         $identifier_exists = ! empty($identifier_value)
@@ -713,7 +713,7 @@  discard block
 block discarded – undo
713 713
         // update the existing related questions
714 714
         // BUT FIRST...  delete the phone question from the Question_Group_Question
715 715
         // if it is being added to this question group (therefore removed from the existing group)
716
-        if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
716
+        if (isset($this->_req_data['questions'], $this->_req_data['questions'][$phone_question_id])) {
717 717
             // delete where QST ID = system phone question ID and Question Group ID is NOT this group
718 718
             EEM_Question_Group_Question::instance()->delete(
719 719
                 array(
@@ -728,22 +728,22 @@  discard block
 block discarded – undo
728 728
         $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
729 729
         $questions = $question_group->questions();
730 730
         // make sure system phone question is added to list of questions for this group
731
-        if (! isset($questions[ $phone_question_id ])) {
732
-            $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
731
+        if ( ! isset($questions[$phone_question_id])) {
732
+            $questions[$phone_question_id] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
733 733
         }
734 734
 
735 735
         foreach ($questions as $question_ID => $question) {
736 736
             // first we always check for order.
737
-            if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
737
+            if ( ! empty($this->_req_data['question_orders'][$question_ID])) {
738 738
                 // update question order
739 739
                 $question_group->update_question_order(
740 740
                     $question_ID,
741
-                    $this->_req_data['question_orders'][ $question_ID ]
741
+                    $this->_req_data['question_orders'][$question_ID]
742 742
                 );
743 743
             }
744 744
 
745 745
             // then we always check if adding or removing.
746
-            if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
746
+            if (isset($this->_req_data['questions'], $this->_req_data['questions'][$question_ID])) {
747 747
                 $question_group->add_question($question_ID);
748 748
             } else {
749 749
                 // not found, remove it (but only if not a system question for the personal group
@@ -766,8 +766,8 @@  discard block
 block discarded – undo
766 766
         if (isset($this->_req_data['questions'])) {
767 767
             foreach ($this->_req_data['questions'] as $QST_ID) {
768 768
                 $question_group->add_question($QST_ID);
769
-                if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
770
-                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
769
+                if (isset($this->_req_data['question_orders'][$QST_ID])) {
770
+                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][$QST_ID]);
771 771
                 }
772 772
             }
773 773
         }
@@ -908,34 +908,34 @@  discard block
 block discarded – undo
908 908
         // echo "trash $trash";
909 909
         // var_dump($this->_req_data['checkbox']);die;
910 910
         if (isset($this->_req_data['checkbox'])) {
911
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
911
+            if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
912 912
                 // if array has more than one element than success message should be plural
913 913
                 $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
914 914
                 // cycle thru bulk action checkboxes
915 915
                 $checkboxes = $this->_req_data['checkbox'];
916 916
                 foreach (array_keys($checkboxes) as $ID) {
917
-                    if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
917
+                    if ( ! $model->delete_or_restore_by_ID($trash, absint($ID))) {
918 918
                         $success = 0;
919 919
                     }
920 920
                 }
921 921
             } else {
922 922
                 // grab single id and delete
923 923
                 $ID = absint($this->_req_data['checkbox']);
924
-                if (! $model->delete_or_restore_by_ID($trash, $ID)) {
924
+                if ( ! $model->delete_or_restore_by_ID($trash, $ID)) {
925 925
                     $success = 0;
926 926
                 }
927 927
             }
928 928
         } else {
929 929
             // delete via trash link
930 930
             // grab single id and delete
931
-            $ID = absint($this->_req_data[ $model->primary_key_name() ]);
932
-            if (! $model->delete_or_restore_by_ID($trash, $ID)) {
931
+            $ID = absint($this->_req_data[$model->primary_key_name()]);
932
+            if ( ! $model->delete_or_restore_by_ID($trash, $ID)) {
933 933
                 $success = 0;
934 934
             }
935 935
         }
936 936
 
937 937
 
938
-        $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
938
+        $action = $model instanceof EEM_Question ? 'default' : 'question_groups'; // strtolower( $model->item_name(2) );
939 939
         // echo "action :$action";
940 940
         // $action = 'questions' ? 'default' : $action;
941 941
         if ($trash) {
@@ -1055,7 +1055,7 @@  discard block
 block discarded – undo
1055 1055
             ? (int) $this->_req_data['curpage']
1056 1056
             : null;
1057 1057
 
1058
-        if (! empty($row_ids)) {
1058
+        if ( ! empty($row_ids)) {
1059 1059
             // figure out where we start the row_id count at for the current page.
1060 1060
             $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
1061 1061
 
@@ -1064,7 +1064,7 @@  discard block
 block discarded – undo
1064 1064
                 // Update the questions when re-ordering
1065 1065
                 $updated = EEM_Question_Group::instance()->update(
1066 1066
                     array('QSG_order' => $qsgcount),
1067
-                    array(array('QSG_ID' => $row_ids[ $i ]))
1067
+                    array(array('QSG_ID' => $row_ids[$i]))
1068 1068
                 );
1069 1069
                 if ($updated === false) {
1070 1070
                     $success = false;
@@ -1115,7 +1115,7 @@  discard block
 block discarded – undo
1115 1115
         $this->_set_add_edit_form_tags('update_reg_form_settings');
1116 1116
         $this->_set_publish_post_box_vars(null, false, false, null, false);
1117 1117
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1118
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
1118
+            REGISTRATION_FORM_CAF_TEMPLATE_PATH.'reg_form_settings.template.php',
1119 1119
             $this->_template_args,
1120 1120
             true
1121 1121
         );
@@ -1361,7 +1361,7 @@  discard block
 block discarded – undo
1361 1361
                                 $prev_email_validation_level = 'basic';
1362 1362
                             }
1363 1363
                             // confirm our i18n email validation will work on the server
1364
-                            if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1364
+                            if ( ! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1365 1365
                                 // or reset email validation level to previous value
1366 1366
                                 $email_validation_level = $prev_email_validation_level;
1367 1367
                             }
@@ -1407,7 +1407,7 @@  discard block
 block discarded – undo
1407 1407
     private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1408 1408
     {
1409 1409
         // first check that PCRE is enabled
1410
-        if (! defined('PREG_BAD_UTF8_ERROR')) {
1410
+        if ( ! defined('PREG_BAD_UTF8_ERROR')) {
1411 1411
             EE_Error::add_error(
1412 1412
                 sprintf(
1413 1413
                     esc_html__(
Please login to merge, or discard this patch.